JavaWeb-HttpServletRequest請求域接口

文章目錄

  • HttpServletRequest請求域接口
    • HttpServletRequest請求域接口簡介
    • 關于請求域和應用域的區別
  • 請求域接口中的相關方法
    • 獲取前端請求參數(getParameter系列方法)
    • 存儲請求域名參數(Attribute系列方法)
    • 獲取客戶端的相關地址信息
    • 獲取項目的根路徑
  • 關于轉發和重定向的細致剖析
    • 轉發代碼實現及相關問題
    • 重定向代碼實現及相關問題

HttpServletRequest請求域接口

HttpServletRequest請求域接口簡介

其實關于請求域這個詞也蠻熟悉的, 因為我們之前學習過 應用域 這一概念, 應用域的生命周期很長, 伴隨這服務器的啟動和終止, 作用范圍也很廣, 對所有的處于當前 webapp 也就是 web 應用的所有Servlet對象都生效


  • HttpServletRequest 是位于jakarta.servlet.http.*包下面的一個接口

  • 繼承了ServletRequest接口
    public interface HttpServletRequest extends ServletRequest

  • 之前我們學習過HTTP協議的相關內容, 這個對象中封裝的其實就是網絡傳輸的時候, 發送的HTTP請求(Request)中封裝的相關參數內容信息

  • 實現這個接口是Tomcat服務器實現的, 傳遞對象封裝參數也是Tomcat服務器完成好的內容, 我們作為Java程序員, 只需要學習獲取其中封裝的相關參數即可


關于請求域和應用域的區別

  • 生命周期不同, 應用域伴隨著Tomcat的生命周期 而 請求域 只作用域這一次請求之內, 而且http協議的特點就是, 一次請求一次創建一次請求域對象
  • 而且在進行參數設定的時候, 盡量的去選擇請求域的參數而不是應用域的參數, 因為小的域的對象占用的資源比較小

請求域接口中的相關方法

上面都說了, 請求域是封裝了相關的http協議的參數信息, 所以必定提供了一些方法來讓我們程序員獲取到這些參數的信息…


獲取前端請求參數(getParameter系列方法)

首先我們思考, 前端傳遞過來的參數應該采用什么數據結構來組織比較好

我們從下面的前端的頁面中獲取信息

<!DOCTYPE html>
<html lang='en'>
<head><meta charset='UTF-8'><meta name='viewport' content='width=device-width, initial-scale=1.0'><title>個人信息</title>
</head>
<body><h2>個人信息</h2><form action="" method="get">姓名:<input type="text" name="name" value=""><br>年齡:<input type="text" name="age" value=""><br>性別:<input type="radio" name="sex" value=""><input type="radio" name="sex" value=""><br>愛好:<input type="checkbox" name="hobby" value="吃飯"><input type="checkbox" name="hobby" value="睡覺"><input type="checkbox" name="hobby" value="打游戲"><br><input type="submit" value="提交"></form>
</body>
</html>

我們執行 http://127.0.0.1:8080/servlet08/test.html

在這里插入圖片描述

我們對URL拆解如下(涉及URLEncoding)

在這里插入圖片描述

我們可以發現, 前端向后端提交數據的格式其實并不是單純的鍵值對的結構存儲的, 因為如果是鍵值對結構存儲的話, 一個key只能對應一個value, 但是復選框這種提交信息的結構, 一個key可以對應多個value信息

所以實際上, 我們的前端發來的數據存儲格式是一個特殊的map集合

Map<String, String[]> map = new HashMap<>();

一個String類型的key可以對應一個String[] 數組, 也就是多個value(前端傳遞參數都是String類型)


上面是一個html頁面, 其中包含test類型文本, 單選框, 復選框

在這里插入圖片描述

上面的方法的解釋:

  • String getParameter(String name): 根據key返回String數組中的第一個參數
  • String[] getParameterValues(String name): 根據key返回完整的String[]數組
  • Enumeration< String > getParameterNames(): 返回一個由所有key組成的集合
  • Map<String, String[]> getParameterMap(): 返回一個key和value組成的完整的集合

還拿我們上面寫的那個html頁面進行測試(設置一下傳遞的Servlet路徑地址)
(注意, 我們下面的method其實寫錯了, 實際上是post請求)

在這里插入圖片描述

Servlet對象的源碼如下

import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;import java.io.*;
import java.util.Enumeration;
import java.util.Map;@WebServlet(urlPatterns = "/getparameter")
public class GetParameterServlet extends HttpServlet {// 由于是form表單提交的數據, 我們盡量采用重寫doPost的方式進行測試@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {// 最好還是設置一下字符集, 防止出現亂碼response.setContentType("text/html;charset=UTF-8");PrintWriter out = response.getWriter();// 1. 使用getParameterMap獲取整個的map形式參數集合out.print("<h3>使用getParameterMap獲取整個集合</h3>");Map<String, String[]> parameterMap = request.getParameterMap();for(Map.Entry<String, String[]> entry : parameterMap.entrySet()){out.print(entry.getKey() + "=");for(String value : entry.getValue()){out.print(value + " ");}}out.print("<br>");out.print("====================================<br>");// 2. 使用getParameterNames獲取整個參數集合的keyout.print("<h3>使用getParameterNames獲取整個集合中的key</h3>");Enumeration<String> parameterNames = request.getParameterNames();while(parameterNames.hasMoreElements()){String name = parameterNames.nextElement();out.print(name + " ");}out.print("<br>");out.print("====================================<br>");// 3. 使用getParameterValues, 根據key獲取參數集合的value數組String[] hobbys = request.getParameterValues("hobby");out.print("hobby=");for(String hobby : hobbys){out.print(hobby + " ");}out.print("<br>");out.print("====================================<br>");// 4. 使用getParameter, 根據key獲取到value數組中的第一個值String name = request.getParameter("name");out.print("name=" + name);out.print("<br>");out.print("====================================<br>");}
}

測試:

下面是form表單中提交的數據信息

在這里插入圖片描述


下面是在瀏覽器中輸出的內容

在這里插入圖片描述


存儲請求域名參數(Attribute系列方法)

Attribute 這個詞其實我們很熟悉了, 因為之前學習ServletContext就出現過這個詞, 也出現了和下面一模一樣的一系列方法, 當時是設置應用域對象, 但是現在是設置請求域對象

在這里插入圖片描述
在這里插入圖片描述

  • void setAttribute(String name, Object o): 設置請求域參數
  • Object getAttribute(String name): 獲取請求域參數
  • Enumeration< String > getAttributeNames(): 獲取所有請求域的key組成的集合
  • void removeAttribute(String name): 移除 key 為參數的請求域信息

沒啥可說的, 直接上測試代碼

import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;import java.io.*;
import java.util.Enumeration;// 使用注解來配置Servlet
@WebServlet("/attribute")
public class AttributeInfoServlet extends HttpServlet {// 重寫doGet方法@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {response.setContentType("text/html");PrintWriter out = response.getWriter();// 1. 使用 void setAttribute(String name, Object o) 設置請求域參數request.setAttribute("name", "Jack");request.setAttribute("age", 18);// 2. 使用 Object getAttribute(String name) 獲取請求域參數Object name = request.getAttribute("name");Object age = request.getAttribute("age");out.print("<h3>" + name + " " + age + "</h3>");out.print("<br>========================================<br>");// 3. 使用 Enumeration< String > getAttributeNames() 獲取所有的請求域參數key集合Enumeration<String> attributeNames = request.getAttributeNames();while (attributeNames.hasMoreElements()) {String attributeName = attributeNames.nextElement();out.print("<h3>" + attributeName + "</h3>");}out.print("<br>========================================<br>");// 4. 使用 void removeAttribute(String name) 移除參數request.removeAttribute("name");Object name1 = request.getAttribute("name");out.print("<h3>" + name1 + "</h3>");}
}

測試結果如下

在這里插入圖片描述

獲取客戶端的相關地址信息

我們需要掌握下面的三個獲取地址相關信息的方法

  • getRemoteAddr(): 獲取客戶端主機IP
  • getRemotePort(): 獲取客戶端的應用端port(端口號)
  • getRemoteHost(): 獲取客戶端主機名稱

下面是關于上面的三個方法的測試代碼(我們直接給出)

import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;import java.io.*;// 使用注解代替web.xml進行Servlet的配置
@WebServlet(urlPatterns = "/addr")
public class GetAddr extends HttpServlet {// 重寫doGet方法@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {// 設置返回的類型以及獲取輸出流信息response.setContentType("text/html");PrintWriter out = response.getWriter();// 1. 使用getRemoteAddr獲取客戶端的IP信息String remoteAddr = request.getRemoteAddr();out.print("<h3>客戶端的IP地址為</h3><br>");out.print(remoteAddr);out.print("<br>=====================================");// 2. 使用getRemotePort獲取客戶端的端口號的信息int remotePort = request.getRemotePort();out.print("<h3>客戶端的端口號為</h3><br>");out.print(remotePort);out.print("<br>======================================");// 3. 使用getRemoteHost獲取客戶端的主機名稱String remoteHost = request.getRemoteHost();out.print("<h3>客戶端的主機名號為</h3><br>");out.print(remoteHost);}
}

在瀏覽器上面訪問這個資源, 可以得到下面的內容

在這里插入圖片描述

注意我們的端口號其實不是固定的, 每一次請求的端口號都是在一個范圍之內進行隨機的, 因為我們的規范建議客戶端的端口號設置為變化的, 服務器端的端口號設置為不變的…


獲取項目的根路徑

這個方法其實用的還是很多的, 因為我們在大量的場景中都需要動態獲取根路徑, 也就是項目路徑, 我們在先前的內容中其實也提到過這個方法…

  • getContextPath(): 獲取項目部署的路徑…

測試就省略了, 主要是想說這個方法的作用非常的重要, 我們好多地方獲取項目的路徑都需要這個方法…


關于轉發和重定向的細致剖析

首先要了解, 不管是轉發和重定向, 其目的都是為了實現資源的跳轉

也就是Java中有兩種方式實現資源的跳轉

  • 轉發
  • 重定向

轉發代碼實現及相關問題

在這里插入圖片描述
在這里插入圖片描述

  • getRequestDispatch(String servletName): 通過給定的轉發的ServletName地址獲取一個分發器對象
  • forward(request, response): 把當前Servlet對象的請求響應對象作為參數傳遞到轉發當中去, 從而實現位于同一個請求域的作用…

轉發的代碼實現

首先創建一個AServlet對象(相關注釋都在代碼中)

import bean.User;
import jakarta.servlet.RequestDispatcher;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;import java.io.*;// 使用注解信息簡化Servlet配置
// 我們把這個 AServlet 作為資源訪問的入口, 然后對 BServlet進行資源的轉發(所以二者本質上還是一次請求, 共享同一個請求域)
@WebServlet(urlPatterns = "/a")
public class AServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {// 因為要測試轉發是不是在一次請求之內轉發(也就是多個Servlet共享同一個request和response對象)// 我們設置相關的請求域參數(我們把用戶定義在了另一個包當中, 等會我們復制代碼就不展示User類了, 應該可以看懂)request.setAttribute("user", new User("huahua", "19", "zz"));// 獲取分發器對象, 調用分發器對象的forward方法對這次請求進行轉發RequestDispatcher requestDispatcher = request.getRequestDispatcher("/b");requestDispatcher.forward(request, response);}
}

創建一個BServlet對象作為AServlet的轉發請求的地址

import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import bean.User;import java.io.*;// 使用注解簡化Servlet配置
// 這個BServlet作為轉發的接收方, 接收AServlet的轉發
@WebServlet(urlPatterns = "/b")
public class BServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {response.setContentType("text/html");PrintWriter out = response.getWriter();// 獲取AServlet中的應用域的參數Object user = request.getAttribute("user");// 強制類型轉化User us = (User) user;// 輸出其中的信息內容out.print(us);}
}

在這里插入圖片描述

我們現在在瀏覽器中訪問AServlet的資源, 顯然, 跳轉到了BServlet中

  • 可以發現, 在A中設置的請求域參數, B中同樣可以獲取, 所以可以判定二者位于同一個請求域
  • 通過URL可以發現, 雖然資源跳轉到了BServlet, 但是URL中的地址還是顯示的AServlet的地址, 所以我們可以了解到, 其實轉發是一種Tomcat服務器內部進行的資源跳轉, 和瀏覽器無關(和重定向區分的重要依據)
  • 根據上面的提示, 我們可以了解到, 轉發是同一次請求的轉發, 也就是只能在一種方法當中之間進行轉發, 全部都在doGet內部轉發, 或者全部都在doPost請求中進行轉發…

轉發不可以在不同的方法之間完成跳轉, 測試如下
假設我們把 BServlet中的 doGet 方法轉換為 doPost 方法

在這里插入圖片描述

其他代碼完全不變, 此時再次向AServlet發送請求

在這里插入圖片描述

會發現直接報錯, 報錯信息是 405 method not allowed

其實針對上述問題, 我們還是有解決方案的, 只需要在doGet方法內部調用doPost就可以避免這種問題

在這里插入圖片描述

繼續訪問AServlet, 會發現程序還是可以正常執行
在這里插入圖片描述


重定向代碼實現及相關問題

和轉發不同, 重定向調用的API位于response對象中

通過 response 對象調用 sendReDirect(/項目路徑/Servlet路徑)方法進行重定向

代碼測試

CServlet如下

import bean.User;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;import java.io.*;// 使用注解簡化開發
@WebServlet(urlPatterns = "/c")
public class CServlet extends HttpServlet {// 重寫doGet方法@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {// 在CServlet類中設置請求域參數, 然后在DServlet中獲取這個請求域參數, 查看是否可以獲取得到...request.setAttribute("user", new User("huahua", "19", "zz"));// 調用 sendRedirt 進行重定向操作(重定向要加上項目的地址), 重定向至DServletresponse.sendRedirect(request.getContextPath() + "/d");}
}

DServlet

import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;import java.io.*;// 使用注解簡化開發
@WebServlet(urlPatterns = "/d")
public class DServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {response.setContentType("text/html");PrintWriter out = response.getWriter();// 嘗試接收CServlet中設置的請求域參數, 查看是不是可以獲取到(其實本質是查看是不是一次請求)Object user = request.getAttribute("user");out.println(user == null ? "不是一個請求" : "是一個請求");}
}

向CServlet發送請求
在這里插入圖片描述

獲取響應結果如下

在這里插入圖片描述

  • 很明顯的看到URL中的資源明顯的發生了改變

我們不妨抓個包看一看剛才發生了什么

會發現出現了兩次請求…

在這里插入圖片描述

第一次向CServlet發送了請求, 這是第一次的請求響應信息

在這里插入圖片描述

可以發現, 響應時的狀態碼是 302 Found

在這里插入圖片描述

也就是發生了重定向的操作

第二次請求是直接通過瀏覽器向DServlet發送了一個請求而不是Tomcat資源內部的跳轉, 具體不再演示了


本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/71461.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/71461.shtml
英文地址,請注明出處:http://en.pswp.cn/web/71461.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

deepseek在pycharm 中的配置和簡單應用

對于最常用的調試python腳本開發環境pycharm&#xff0c;如何接入deepseek是我們窺探ai代碼編寫的第一步&#xff0c;熟悉起來總沒壞處。 1、官網安裝pycharm社區版&#xff08;免費&#xff09;&#xff0c;如果需要安裝專業版&#xff0c;需要另外找破解碼。 2、安裝Ollama…

AAA協議:從零認識網絡的“身份管家”

AAA&#xff08;Authentication, Authorization, Accounting&#xff0c;認證、授權和計費&#xff09;是網絡世界的“身份管理員”&#xff0c;負責確認“你是誰”、決定“你能干啥”、記錄“你干了啥”。如果你用過華三的交換機或路由器&#xff0c;可能在配置用戶管理時見過…

動態規劃01背包問題系列一>最后一塊石頭的重量II

這里寫目錄標題 題目分析&#xff1a;狀態表示&#xff1a;狀態轉移方程&#xff1a;初始化&#xff1a;填表順序&#xff1a;返回值&#xff1a;代碼呈現&#xff1a;優化版本&#xff1a;代碼呈現&#xff1a; 題目分析&#xff1a; 狀態表示&#xff1a; 狀態轉移方程&#…

逐行拆解 C 語言:數據類型、變量

今日&#xff0c;我們即將踏上一段充滿趣味與挑戰的學習之旅&#xff0c;深度鉆研數據類型的多樣奧秘&#xff0c;解鎖變量創建的實用技巧。不僅如此&#xff0c;還會邂逅兩個實用的基礎庫函數&#xff0c;探索它們在程序中穿針引線的奇妙作用。同時&#xff0c;幾個簡潔卻強大…

【音視頻】ffplay簡單過濾器

一、ffplay簡單過濾器 視頻旋轉&#xff1a;借助transpose濾鏡 ffplay -i 1.mp4 -vf transpose1這里選擇不同的數字是不同的方向&#xff1a; 視頻翻轉&#xff1a;借助hflip/vflip實現水平和垂直翻轉&#xff1a; 水平翻轉 ffplay 1.mp4 -vf hflip垂直翻轉 ffplay 1.mp4 …

springboot中注解有什么用

注解&#xff08;Annotation&#xff09;是 Java 的一個重要特性&#xff0c;我用幾個具體例子來解釋&#xff1a; 1、標記功能 Service // 告訴Spring這是一個服務類 public class UserService { }Data // 告訴Lombok自動生成getter/setter public class User {private…

Excel中COUNTIF用法解析

COUNTIF 是 Excel 中一個非常實用的函數&#xff0c;用于統計滿足某個條件的單元格數量。它的基本語法如下&#xff1a; 基本語法 COUNTIF(范圍, 條件) 范圍&#xff1a;需要統計的單元格區域&#xff0c;例如 A1:A10 或整列 A:A。 條件&#xff1a;用于判斷哪些單元格需要被…

java根據List<Object>中的某個屬性排序(數據極少,順序固定)

public static void main(String[] args) { List<HashMap<String, Object>> dydj new ArrayList<>(); // 模擬原始數據 HashMap<String, Object> map1 new HashMap<>(); map1.put(“city_name”, “張家口”); map1.put(“wjs”, 0); map1.put…

4G工業路由器在公交充電樁中的應用與優勢

隨著電動公交車的普及&#xff0c;公交充電樁的穩定運行和高效管理是交通營運部門最關心的問題。4G工業路由器憑借其卓越的數據采集和通訊能力&#xff0c;成為實現充電樁智能化管理的關鍵。 公交充電樁運維管理需求概述&#xff1a; 1.實時性&#xff1a;實時監控充電狀態、剩…

利用golang embed特性嵌入前端資源問題解決

embed嵌入前端資源&#xff0c;配置前端路由的代碼如下 func StartHttpService(port string, assetsFs embed.FS) error {//r : gin.Default()gin.SetMode(gin.ReleaseMode)r : gin.New()r.Use(CORSMiddleware())// 靜態文件服務dist, err : fs.Sub(assetsFs, "assets/di…

【LangChain 數據連接封裝】 文檔加載器、文檔處理器

小結&#xff1a; 文檔處理部分&#xff0c;建議在實際應用中詳細測試后使用與向量數據庫的鏈接部分本質是接口封裝&#xff0c;向量數據庫需要自己選型類似 LlamaIndex&#xff0c;LangChain 也提供了豐富的 Document Loaders DocumentLoaders和 Text Splitters Text Splitte…

Springboot集成dubbo完整過程(三)

準備工作 1&#xff0c;準備mysql服務環境2&#xff0c;準備redis服務環境3&#xff0c;準備zookeeper服務環境4&#xff0c;準備逆向生成bean的xml配置文件5&#xff0c;準備slf4j日志xml配置文件6&#xff0c;準備一個sql腳本 1&#xff0c;搭建創建服務工程 1&#xff0c;創…

【DeepSeek 】學習編程的利器:DeepSeek 使用指南

學習編程的利器&#xff1a;DeepSeek 使用指南 如果你正苦于如何開始學習 Python/R/Linux/HTML 語法&#xff0c;這個方法或許是你學習過程中的利器&#xff0c;又不用考慮請教真人&#xff0c;麻煩別人。 學習階段 第一階段&#xff1a;通讀語法書籍 第一步通讀一些相關語法…

【大模型篇】目前主流 AI 大模型體系全解析:架構、特點與應用

大家好,我是大 F,深耕AI算法十余年,互聯網大廠技術崗。分享AI算法干貨、技術心得。 歡迎關注《大模型理論和實戰》、《DeepSeek技術解析和實戰》,一起探索技術的無限可能! 閱讀完本文,您將知道:目前主流的大模型體系有哪些?及其架構的特點。 前言 在自然語言處理(NL…

電池管理系統(BMS)架構詳細解析:原理與器件選型指南

BMS&#xff08;電池管理系統&#xff09;架構詳細講解 從你提供的BMS&#xff08;Battery Management System&#xff09;架構圖來看&#xff0c;主要涉及到電池監控模塊、通信模塊、功率控制模塊等部分。下面我將詳細講解該架構的各個功能模塊及其工作原理。 1. 電池管理核…

決策樹(Decision Tree)基礎知識

目錄 一、回憶1、*機器學習的三要素&#xff1a;1&#xff09;*函數族2&#xff09;*目標函數2.1&#xff09;*模型的其他復雜度參數 3&#xff09;*優化算法 2、*前處理/后處理1&#xff09;前處理&#xff1a;特征工程2&#xff09;后處理&#xff1a;模型選擇和模型評估 3、…

洛谷 P3648 APIO2014 序列分割 題解

寫了挺多斜率優化的題目了&#xff0c;這道&#xff08;差點&#xff09;就速切了&#xff0c;原因還是單調隊列維護斜率的寫法出鍋。 題意 題目描述 你正在玩一個關于長度為 n n n 的非負整數序列的游戲。這個游戲中你需要把序列分成 k 1 k 1 k1 個非空的塊。為了得到 …

策略模式的C++實現示例

核心思想 策略模式是一種行為型設計模式&#xff0c;它定義了一系列算法&#xff0c;并將每個算法封裝在獨立的類中&#xff0c;使得它們可以互相替換。策略模式讓算法的變化獨立于使用它的客戶端&#xff0c;從而使得客戶端可以根據需要動態切換算法&#xff0c;而不需要修改…

Loki+Promtail+Grafana監控K8s日志

在現代云原生架構中&#xff0c;監控與日志管理對于確保系統穩定性和可靠性至關重要。Kubernetes&#xff08;K8s&#xff09;作為當下流行的容器編排平臺&#xff0c;對日志的監控管理需求尤為突出。Loki, Promtail 和 Grafana 構成了一套強大的日志監控解決方案&#xff0c;它…

Git 批量合并 Commit 并且保留之前的 Commit 快速實現的思路

文章目錄 需求Rebase / Pick / squashVim 的快速全局字符串替換 需求 我想把如下的提交 commit&#xff0c;變成一個 Commit&#xff0c;并且合并這些 Commit 的消息到一個節點 Rebase / Pick / squash 我合并到 5e59217 這個hash 上&#xff0c;這樣合并后會保留兩個 Commit…