最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

淺析SpringBoot中的過濾器和攔截器

 更新時間:2024年03月11日 11:18:43   作者:void  
過濾器和攔截器都是為了在請求到達(dá)目標(biāo)處理器(Servlet或Controller)之前或者之后插入自定義的處理邏輯,下面就跟隨小編來看看它們二者的區(qū)別和具體使用吧

介紹

過濾器和攔截器都是為了在請求到達(dá)目標(biāo)處理器(Servlet或Controller)之前或者之后插入自定義的處理邏輯

過濾器:

遵循AOP(面向切面編程)思想實現(xiàn),基于Servlet規(guī)范提供的Filter接口,它是位于客戶端請求與服務(wù)器響應(yīng)之間的一個組件,依賴于Servlet容器。當(dāng)請求到達(dá)服務(wù)器時,過濾器會在請求進(jìn)入實際目標(biāo)資源(如Servlet、JSP頁面)之前或之后執(zhí)行特定的操作,原理是基于函數(shù)回調(diào)

攔截器

遵循AOP(面向切面編程)思想實現(xiàn),如Spring MVC中的HandlerInterceptor接口,它不依賴于Servlet容器的具體實現(xiàn),而是由應(yīng)用框架管理。攔截器是在請求進(jìn)入到控制器層(Controller)方法前后執(zhí)行自定義邏輯

原理解析

過濾器

為什么說過濾器基于函數(shù)回調(diào)?

過濾器基于函數(shù)回調(diào),所謂函數(shù)回調(diào)/回調(diào)函數(shù)指的是:一個函數(shù)(稱為回調(diào)函數(shù))作為參數(shù)傳遞給另一個函數(shù)(稱為調(diào)用函數(shù)),當(dāng)滿足一定條件或者在某個特定時刻,調(diào)用函數(shù)會調(diào)用傳遞過來的回調(diào)函數(shù)

由于Java中不直接支持函數(shù)指針,所以常常通過接口來實現(xiàn)回調(diào)機(jī)制

FilterChain就是一個接口

public interface FilterChain {

    public void doFilter(ServletRequest request, ServletResponse response)
            throws IOException, ServletException;

}

Filter的實現(xiàn)類中doFilter()方法中FilterChain作為參數(shù)被傳進(jìn)來,并且在合適的時機(jī)被回調(diào)了其doFilter方法

public class MyFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        Filter.super.init(filterConfig);
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        log.info("hello");
        chain.doFilter(request,response);
    }

    @Override
    public void destroy() {
        Filter.super.destroy();
    }
}

攔截器

攔截器基于AOP(面向切面編程)思想實現(xiàn),但是并不一定用到動態(tài)代理或者切面,切點之類的技術(shù),以如Spring MVC中的HandlerInterceptor接口為例,從源碼看更像是直接將攔截器注入,形成了一個攔截器鏈,在controller層面上進(jìn)行代碼織入

DispatcherServlet作為SpringMVC框架的核心類,http請求的核心執(zhí)行方法為doService(),再進(jìn)入doDispatch()方法

protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
		HttpServletRequest processedRequest = request;
        /**
         * 1.
         * HandlerExecutionChain 是一個對象
         * 包含了以下重要的屬性
         * private final Object handler; //處理器(controller和其最后的方法)
         * List<HandlerInterceptor> interceptorList = new ArrayList<>();//攔截器列表,用來存儲匹配處理器的攔截器
         */
		HandlerExecutionChain mappedHandler = null;
		boolean multipartRequestParsed = false;

		WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);

		try {
			ModelAndView mv = null;
			Exception dispatchException = null;

			try {
				processedRequest = checkMultipart(request);
				multipartRequestParsed = (processedRequest != request);

                /**
                 * 2.
                 * 下面這行代碼 大概做了以下事情
                 * 1.通過request和url 匹配了對應(yīng)的controller以及調(diào)用的方法 填充了HandlerExecutionChain.handler
                 * 2.通過匹配request和HandlerInterceptor的注冊信息(攔截哪些,放行哪些),往HandlerExecutionChain.interceptorList中添加對應(yīng)的攔截器
                 */
				mappedHandler = getHandler(processedRequest);
				if (mappedHandler == null) {
					noHandlerFound(processedRequest, response);
					return;
				}

				// Determine handler adapter for the current request.
				HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());

				// Process last-modified header, if supported by the handler.
				String method = request.getMethod();
				boolean isGet = HttpMethod.GET.matches(method);
				if (isGet || HttpMethod.HEAD.matches(method)) {
					long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
					if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {
						return;
					}
				}
                /**
                 * 3.執(zhí)行 攔截器鏈條中的所有前置方法
                 */
				if (!mappedHandler.applyPreHandle(processedRequest, response)) {
					return;
				}

                /**
                 * 4.交由處理器(controller對應(yīng)的方法)去處理方法中的業(yè)務(wù)邏輯
                 */
				mv = ha.handle(processedRequest, response, mappedHandler.getHandler());

				if (asyncManager.isConcurrentHandlingStarted()) {
					return;
				}

				applyDefaultViewName(processedRequest, mv);
                
                /**
                 * 5.倒序執(zhí)行 攔截器鏈條中的所有后置方法
                 */
				mappedHandler.applyPostHandle(processedRequest, response, mv);
			}}
        //...

流程解析

由于Filter依賴于Servlet容器所以不同的容器Filter,FilterChain的實現(xiàn)類存在差異,這里以Tomcat為例分析

1.向后臺發(fā)起一次請求

2.接待線程接收到,將任務(wù)轉(zhuǎn)交給工作線程

3.判斷協(xié)議,封裝必要對象

4.將request,response一路轉(zhuǎn)交至StandardWrapperValve.invoke(Request request, Response response)

5.創(chuàng)建過濾鏈ApplicationFilterFactory.createFilterChain(request, wrapper, servlet);

? 5.1從上下文中獲取注冊好的過濾器

? 5.2遍歷過濾器,匹配URL,Servlet等,將匹配好的過濾器加入到過濾器鏈

6.依次回調(diào)FilterChain的doFilter方法filterChain.doFilter(request.getRequest(),response.getResponse());

7.將所有過濾器的前置代碼執(zhí)行完畢,進(jìn)入servlet,servlet.service(request, response);

8.進(jìn)入DispatcherServlet統(tǒng)一調(diào)度

9.調(diào)用攔截器前置方法

10.進(jìn)入controller中的對應(yīng)方法,執(zhí)行具體的業(yè)務(wù)邏輯

11.調(diào)用攔截器后置(數(shù)組倒序執(zhí)行)

12.將所有過濾器的后置代碼執(zhí)行完畢(方法棧,先進(jìn)后出)

13.將結(jié)果返回給請求者

注意,過濾器和攔截器實現(xiàn)先進(jìn)后出的實現(xiàn)方式是不同的,過濾器基于函數(shù)回調(diào),方法棧結(jié)構(gòu)天生支持先進(jìn)后出;攔截器則是直接使用循環(huán)倒序遍歷

總結(jié)

同:

過濾器和攔截器都遵循面向切面編程的思想(AOP),實現(xiàn)了在請求到達(dá)目標(biāo)處理器(Servlet/Controller)之前或者之后插入自定義的處理邏輯

異:

1.使用范圍不同

  • 過濾器實現(xiàn)的是javax.servlet.Filter該接口在Servlet規(guī)范中定義,依賴WEB容器
  • 攔截器是一個Spring組件,由Spring管理,并不依賴Tomcat容器,可以單獨使用(Application,Swing)

2.使用的場景不同

  • 攔截器更加接近業(yè)務(wù)系統(tǒng),所以攔截器更適用于處理統(tǒng)一的業(yè)務(wù)邏輯,比如權(quán)限判斷等
  • 過濾器通常用來實現(xiàn)通用功能,比如xss過濾,敏感詞,處理跨域等等

3.觸發(fā)的時機(jī)不同

過濾器的觸發(fā)時機(jī)早于攔截器

4.底層實現(xiàn)細(xì)節(jié)不同

  • 過濾器實現(xiàn)先進(jìn)后出基于方法棧的數(shù)據(jù)結(jié)構(gòu)
  • 攔截器實現(xiàn)先進(jìn)后出基于循環(huán)倒序遍歷

到此這篇關(guān)于淺析SpringBoot中的過濾器和攔截器的文章就介紹到這了,更多相關(guān)SpringBoot過濾器和攔截器內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • SpringCloud遠(yuǎn)程服務(wù)調(diào)用三種方式及原理

    SpringCloud遠(yuǎn)程服務(wù)調(diào)用三種方式及原理

    本文給大家介紹SpringCloud遠(yuǎn)程服務(wù)調(diào)用實戰(zhàn)筆記,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友參考下吧
    2022-12-12
  • java虛擬線程的超詳細(xì)講解

    java虛擬線程的超詳細(xì)講解

    虛擬線程是由Java運行時而不是操作系統(tǒng)實現(xiàn)的Java線程,和傳統(tǒng)線程(或稱之為平臺線程)之間的主要區(qū)別在于,我們可以很容易地在同一個Java進(jìn)程中運行大量活動的虛擬線程,甚至數(shù)百萬個,這篇文章主要介紹了java虛擬線程的相關(guān)資料,需要的朋友可以參考下
    2025-10-10
  • Mybatis實現(xiàn)一對多映射處理

    Mybatis實現(xiàn)一對多映射處理

    MyBatis是一種流行的Java持久化框架,這篇文章主要為大家介紹了Mybatis如何實現(xiàn)一對多映射處理,文中的示例代碼講解詳細(xì),需要的可以參考下
    2023-08-08
  • 利用Spring框架為自己的校園卡充值(推薦)

    利用Spring框架為自己的校園卡充值(推薦)

    這篇文章主要介紹了利用Spring框架為自己的校園卡充值,本次實驗主要運用了Spring的控制反轉(zhuǎn)(IOC)和依賴注入(DI)等知識,通過利用Spring框架編寫Java程序,實現(xiàn)學(xué)生卡的單次充值,如需對學(xué)生卡進(jìn)行多次充值,可將部分代碼修改即可實現(xiàn),需要的朋友可以參考下
    2022-10-10
  • java限流算法詳細(xì)

    java限流算法詳細(xì)

    這篇文章詳細(xì)的介紹了java限流算法常用到的算法計數(shù)算法、漏桶算法、令牌桶等算法的相關(guān)資料,需要的朋友可以參考下文,希望本篇文章能幫助到您
    2021-09-09
  • Spring Boot2與Spring Boot3的區(qū)別小結(jié)

    Spring Boot2與Spring Boot3的區(qū)別小結(jié)

    SpringBoot2和SpringBoot3之間有一些重要的區(qū)別,本文就來探討SpringBoot2和SpringBoot3之間的區(qū)別,具有一定的參考價值,感興趣的可以了解一下
    2023-10-10
  • java實現(xiàn)學(xué)生信息錄入界面

    java實現(xiàn)學(xué)生信息錄入界面

    這篇文章主要為大家詳細(xì)介紹了java實現(xiàn)學(xué)生信息錄入界面,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-04-04
  • 淺談Java編程ToString()方法重寫的意義

    淺談Java編程ToString()方法重寫的意義

    這篇文章主要介紹了淺談Java編程ToString()方法重寫的意義,還是挺不錯的,這里分享給大家,供朋友們學(xué)習(xí)和參考。
    2017-10-10
  • Java編程實現(xiàn)獲取當(dāng)前代碼行行號的方法示例

    Java編程實現(xiàn)獲取當(dāng)前代碼行行號的方法示例

    這篇文章主要介紹了Java編程實現(xiàn)獲取當(dāng)前代碼行行號的方法,結(jié)合實例形式分析了java基于StackTraceElement對象實現(xiàn)獲取代碼行號的相關(guān)操作技巧,需要的朋友可以參考下
    2017-08-08
  • 數(shù)據(jù)庫阿里連接池 druid配置詳解

    數(shù)據(jù)庫阿里連接池 druid配置詳解

    本篇文章主要介紹了數(shù)據(jù)庫阿里連接池 druid配置詳解,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-05-05

最新評論

巴马| 明星| 永城市| 余干县| 勃利县| 金川县| 交口县| 慈溪市| 宁化县| 二手房| 桂东县| 黔江区| 云阳县| 梅州市| 河南省| 桐城市| 尼木县| 石渠县| 永济市| 浑源县| 灵武市| 迁西县| 淳化县| 新乡市| 溧水县| 阿巴嘎旗| 黎城县| 大化| 乌兰浩特市| 德化县| 岑巩县| 穆棱市| 沂源县| 桃园市| 威远县| 临洮县| 利津县| 罗田县| 怀集县| 改则县| 北宁市|