詳解攔截器和過濾器

目錄

  • 代碼演示
    • 過濾器Demo
    • 攔截器Demo
  • 過濾器
    • 自定義攔截器
    • 配置攔截器
    • 過濾器執行原理
    • 多個過濾器的執行順序
  • 攔截器
    • 自定義攔截器
    • 注冊攔截器
      • 1)注冊攔截器
      • 2)配置攔截的路徑
      • 3)配置不攔截的路徑
    • 多個攔截器的執行順序
  • 過濾器和攔截器的區別

代碼演示

我們這里先上代碼,看看攔截器和過濾器在代碼實現上的區別。

過濾器Demo

1、定義一個類,實現接口Filter

public class FilterDemo implements Filter {
}

2、實現Filter接口的方法

public class FilterDemo implements Filter {public static int i = 0;@Overridepublic void init(FilterConfig filterConfig) throws ServletException {System.out.println("執行init方法");}@Overridepublic void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {System.out.println("執行doFilter方法 + " + i++);filterChain.doFilter(servletRequest,servletResponse);}@Overridepublic void destroy() {System.out.println("執行destroy方法");}
}

3、配置攔截路徑

1)通過web.xml文件配置

<filter><filter-name>FilterDemo</filter-name><filter-class>com.example.springboot_demo.filter.FilterDemo</filter-class>
</filter><filter-mapping><filter-name>FilterDemo</filter-name><!-- 攔截路徑 --><url-pattern>/*</url-pattern>
</filter-mapping>

2)、注解
@WebFilter("/*")

攔截器Demo

1、定義一個類實現HandlerInterceptor 并實現此接口的方法

public class InterceptorDemo implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {System.out.println("執行preHandle方法");return true;}@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {System.out.println("執行postHandle方法");}@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {System.out.println("執行afterCompletion方法");}
}

2、創建一個配置類,實現WebMvcConfigurer

@Configuration
public class MyConfig implements WebMvcConfigurer {}

3、實現WebMvcConfigurer addInterceptors方法

@Configuration
public class MyConfig implements WebMvcConfigurer {@Overridepublic void addInterceptors(InterceptorRegistry registry) {}
}

4、將自定義的攔截器進行注冊,并配置攔截路徑和放行路徑

@Configuration
public class MyConfig implements WebMvcConfigurer {@Overridepublic void addInterceptors(InterceptorRegistry registry) {// 注冊自定義的攔截器InterceptorRegistration interceptorRegistration = registry.addInterceptor(new InterceptorDemo());// 定義攔截所有路徑interceptorRegistration.addPathPatterns("/**");// 定義排查/user/下的所有路徑interceptorRegistration.excludePathPatterns("/user/**");}
}

這就是過濾器和攔截器的代碼實現,展示了它們在代碼層面的不同。后面將會進行詳細解釋。

過濾器

過濾器是Servlet的高級特性之一,就是Web服務器在處理請求的時候會經過每一過濾器再處理請求。
在這里插入圖片描述

自定義攔截器

自定義攔截器其實就是實現Filter接口,然后實現他的方法。

那它的方法都有什么作用呢?
1)init方法
public void init(FilterConfig filterConfig)

  • 在Web容器啟動初始化過濾器時被調用,它在 Filter 的整個生命周期只會被調用一次。
  • 注意:這個方法必須執行成功,否則過濾器會不起作用。

2)doFilter方法
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)

  • 容器中的每一次請求都會調用該方法
  • 一次請求會調用兩次,進Web容器時調用一次,出Web容器時調用一次
  • 要使用filterChain.doFilter(servletRequest, servletResponse);來調用下一個過濾器,否則這個請求就到此結束了。

3)destroy方法
public void destroy()

  • 當容器銷毀 過濾器實例時調用該方法,一般在方法中銷毀或關閉資源
  • 在過濾器 Filter 的整個生命周期也只會被調用一次
public class FilterDemo implements Filter {@Overridepublic void init(FilterConfig filterConfig) throws ServletException {System.out.println("執行init方法");}@Overridepublic void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {System.out.println("執行doFilter方法");filterChain.doFilter(servletRequest,servletResponse);}@Overridepublic void destroy() {System.out.println("執行destroy方法");}
}

配置攔截器

1)通過web.xml文件配置

<filter><filter-name>FilterDemo</filter-name><filter-class>com.example.springboot_demo.filter.FilterDemo</filter-class>
</filter>
  • <filter-name>用于為過濾器指定一個名字,該元素的內容不能為空。
  • <filter-class>元素用于指定過濾器的完整的限定類名。
  • <init-param>元素用于為過濾器指定初始化參數,它的子元素<param-name>指定參數的名字,<param-value>指定參數的值。在過濾器中,可以使用FilterConfig接口對象來訪問初始化參數。
<filter-mapping><filter-name>FilterDemo</filter-name><!-- 攔截路徑 --><url-pattern>/*</url-pattern>
</filter-mapping>
  • <filter-mapping>元素用于設置一個Filter 所負責攔截的資源。
  • <filter-name>子元素用于設置filter的注冊名稱。該值必須是在<filter>元素中聲明過的過濾器的名字。
  • <url-pattern>設置 filter 所攔截的請求路徑(過濾器關聯的URL樣式)

2)、注解
@WebFilter(filterName = "FilterDemo",urlPatterns = "/*")

  • 理解了web.xml方式,注解方式看起來就一目了然了

過濾器執行原理

過濾器執行主要是通過函數回調的方式。
在我們自定義的過濾器中都會實現一個 doFilter()方法,這個方法有一個FilterChain 參數,而實際上它是一個回調接口。
在這里插入圖片描述
所以,如果我們寫這樣的過濾器

public class FilterDemo implements Filter {@Overridepublic void init(FilterConfig filterConfig) throws ServletException {System.out.println("執行init方法");}@Overridepublic void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {System.out.println("準備放行");//執行這一句,說明放行(讓下一個過濾器執行,或者執行目標資源)chain.doFilter(req, resp);System.out.println("放行完成");}@Overridepublic void destroy() {System.out.println("執行destroy方法");}
}

程序在執行到chain.doFilter(req,resp)時會執行下一個過濾器或目標資源,然后執行完成回到此方法繼續往下執行。

多個過濾器的執行順序

過濾器之間的執行順序看在web.xml文件中mapping的先后順序的,如果放在前面就先執行,放在后面就后執行!
如果是通過注解的方式配置,就比較urlPatterns的字符串優先級

攔截器

攔截器是SpringMVC自己的功能,雖然看起來和過濾器一樣,但是底層使用的是面向切面編程AOP

自定義攔截器

前面我們直到自定義攔截器要實現HandlerInterceptor接口,然后再實現它的方法。

那這幾個方法都有什么作用呢?
1)preHandle方法
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler);

  • 再請求處理之前執行(Controller方法調用之前)
  • 返回值是boolean類型,返回false表示攔截,不會讓此請求訪問Controller,返回true則可繼續執行

2)postHandle方法
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView);

  • 在請求結束之后(Controller請求返回),在ModelAndView渲染之前調用
  • 主要就是用來對ModelAndView對象進行操作

3)afterCompletion方法
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex);

  • 在整個請求結束之后調用
  • 主要是用于資源清理工作
public class InterceptorDemo implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {System.out.println("執行preHandle方法");return true;}@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {System.out.println("執行postHandle方法");}@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {System.out.println("執行afterCompletion方法");}
}

注冊攔截器

創建一個實現WebMvcConfigurer的攔截器,然后將自定義的攔截器注冊到其中。可以注冊多個攔截器。

實現方法addInterceptors,通過參數InterceptorRegistry registry來進行一系列配置

@Configuration
public class MyConfig implements WebMvcConfigurer {@Overridepublic void addInterceptors(InterceptorRegistry registry) {// 注冊自定義的攔截器InterceptorRegistration interceptorRegistration = registry.addInterceptor(new InterceptorDemo());// 定義攔截所有路徑interceptorRegistration.addPathPatterns("/**");// 定義排查/user/下的所有路徑interceptorRegistration.excludePathPatterns("/user/**");// 確定執行順序interceptorRegistration.order(1);}
}

1)注冊攔截器

InterceptorRegistration interceptorRegistration = registry.addInterceptor(new InterceptorDemo());
將自定義的攔截器對象傳入其中即可,如果要注冊多個攔截器,調用多次這個方法即可。

2)配置攔截的路徑

interceptorRegistration.addPathPatterns("/**");

如果需要攔截多個路徑,可以多次傳入一個字符串,也可以傳入一個List集合。
在這里插入圖片描述

3)配置不攔截的路徑

interceptorRegistration.excludePathPatterns("/user/**");

這個和addPathPatterns一樣,可以傳入字符串,也可以傳入List
在這里插入圖片描述

多個攔截器的執行順序

在這里插入圖片描述

多個攔截器可通過order()方法來確定執行順序,order()傳入一個數字,數字越小則越先執行。

過濾器和攔截器的區別

  • 適用范圍不同:Filter是Servlet容器規定的,只能使用在servlet容器中,而攔截器的使用范圍就大得多
  • 使用的資源不同:攔截器是屬于spring的一個組件,因此可以使用spring的所有對象,如service對象,數據源,事務控制等,而過濾器就不行
  • 深度不同:Filter還在servlet前后起作用。而攔截器能夠深入到方法前后,異常拋出前后,因此攔截器具有更大的彈性,所有在spring框架中應該優先使用攔截器
    在這里插入圖片描述

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

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

相關文章

HarmonyOS教育類APP項目實戰系列課結課考試答案(1-10講)80分就合格

王丹輝&#xff08;第一講&#xff09;&#xff1a;HarmonyOS教育類APP項目實戰開課及低代碼初體驗 結課考試 及格分80/ 滿分100 評價 判斷題 1. DevEco Studio不能同時支持HarmonyOS和OpenHarmony應用/服務開發 正確(True)錯誤(False) 回答正確 2. DevEco Studio…

C#基礎知識(一)

一、C#程序結構 《1》命名空間的聲明&#xff08;namespace declaration&#xff09; 《2》一個class 《3》class方法 《4》class屬性 《5》一個main方法 《6》語句&#xff08;statements&#xff09;&表達式&#xff08;Expressions&#xff09; 《7》注釋 注&#xff1a…

【設計模式】橋接模式

橋接&#xff08;Bridge&#xff09;是用于把抽象化與實現化解耦&#xff0c;使得二者可以獨立變化。這種類型的設計模式屬于結構型模式&#xff0c;它通過提供抽象化和實現化之間的橋接結構&#xff0c;來實現二者的解耦。 這種模式涉及到一個作為橋接的接口&#xff0c;使得…

C++ 網絡編程項目fastDFS分布式文件系統(二)-redis部分

目錄 1. 數據庫類型 1.1 基本概念 1.2 關系/非關系型數據庫搭配使用 2. Redis 2.1 基本知識點 2.2 redis常用命令 - String類型 - List類型 - Set類型 - SortedSet 類型 - Hash類型 Key 相關的命令 2.3 redis配置文件 2.4 redis數據持久化 3 hiredis的使用 1. 數據…

手搓vue3組件_0,打包配置

打包后引入項目是發現報錯: Cannot read properties of null (reading isCE) TypeError: Cannot read properties of null (reading isCE)這個是由于vue版本沖突問題, 這里我引入了自己打包的ui組件庫,但是ui組件庫中打包進入了自己的vue,那么在此時使用時,如果你引入的自己的組…

原生js發送ajax請求---ajax請求篇(一)

在原生js中我們使用的是XMLHttpRequest對象來發送ajax請求 主要步驟就是&#xff1a; 1.創建XMLHTTPRequest對象 2.使用open方法設置和服務器的交互信息 3.設置發送的數據&#xff0c;開始和服務器端交互 4.注冊事件 5.更新界面 &#xff08;1&#xff09; get方式 //步驟一…

使用python對圖像加噪聲

加上雨點噪聲 import cv2 import numpy as npdef get_noise(img, value10):#生成噪聲圖像>>> 輸入&#xff1a; img圖像value 大小控制雨滴的多少 >>> 返回圖像大小的模糊噪聲圖像noise np.random.uniform(0, 256, img.shape[0:2])# 控制噪聲水平&#xff…

誰能講清楚Spark之與MapReduce的對比

我們已經知道Spark是如何設計和實現數據處理流程的,這里我們 再深入思考一下,為什么Spark能夠替代MapReduce成為主流的大數據處理框架呢?對比MapReduce,Spark究竟有哪些優勢? 一 優勢 1 通用性: 基于函數式編程思想,MapReduce將數據類型抽象為,k,v格式,并將數據處理…

Spring Boot單元測試使用MockBean注解向Service注入Mock對象

1. 背景介紹 我們在測試時有一個Service&#xff0c;我們需要測試Service&#xff0c;但Service內部依賴ServiceA、ServiceB&#xff0c;此時我們希望Mock ServiceA&#xff0c;ServiceB 注入真實對象。 class Service {private ServiceA A;private ServiceB B;public int me…

OPENCV C++(十二)模板匹配

正常模板匹配函數 matchTemplate(img, templatee, resultMat, 0);//模板匹配 這里0代表的是方法&#xff0c;一般默認為0就ok img是輸入圖像 templatee是模板 resultmat是輸出 1、cv::TM_SQDIFF&#xff1a;該方法使用平方差進行匹配&#xff0c;因此最佳的匹配結果在結果為…

Excel(1):表頭或列頭凍結

1.需求 對于較大的excel&#xff0c;通常需要固定一部分內容&#xff0c;另一份內容為可翻動。 2.解決方式 在視圖中選擇凍結窗格&#xff0c;需要注意的是&#xff0c;選擇凍結窗格時&#xff0c;窗格的左上方的表格區域是固定不動的&#xff0c;只可以向下或者向右活動。

8.10論文閱讀

文章目錄 The multimodal MRI brain tumor segmentation based on AD-Net摘要本文方法損失函數 實驗結果 max-vit - unet:多軸注意力醫學圖像分割摘要本文方法實驗結果 The multimodal MRI brain tumor segmentation based on AD-Net 摘要 基于磁共振成像(MRI)的多模態膠質瘤…

Redis分布式鎖問題

1、業務單機情況下 問題&#xff1a;并發沒有加鎖導致線程安全問題。 解決方法&#xff1a;加鎖處理&#xff0c;如lock、synchronized 仍有問題&#xff1a;業務分布式情況下&#xff0c;代碼級別加鎖已經無效。需要借助第三方組件&#xff0c;如redis、zookeeper。 2、業務分…

云計算|OpenStack|使用VMware安裝華為云的R006版CNA和VRM---初步使用(二)

前言&#xff1a; 在前面一篇文章云計算|OpenStack|使用VMware安裝華為云的R006版CNA和VRM---初始安裝&#xff08;一&#xff09;_華為cna_晚風_END的博客-CSDN博客 介紹了基于VMware虛擬機里嵌套部署華為云的云計算&#xff0c;不過僅僅是做到了在VRM的web界面添加計算節點…

Kubernetes的默認調度和自定義調度詳解

默認調度和自定義調度詳解 默認調度 默認調度是 Kubernetes 中的內置機制&#xff0c;它使用調度器組件來管理分配容器的節點。調度器依據以下原則選擇合適的節點&#xff1a; 資源需求 &#xff1a;調度器會為每個 Pod 根據其 CPU 和內存需求選擇一個具有足夠資源的節點。親…

Android使用kotlin+協程+room數據庫的簡單應用

前言&#xff1a;一般主線程&#xff08;UI線程&#xff09;中是不能執行創建數據這些操作的&#xff0c;因為等待時間長。所以協程就是為了解決這個問題出現。 第一步&#xff1a;在模塊級的build.gradle中引入 id com.android.application// roomid kotlin-androidid kotlin…

Mysql主從分離

一、前言 某個應用場景中&#xff0c;在操作數據庫這部分&#xff0c;往往是數據庫的讀取往往大于數據庫的寫入&#xff0c;當讀取數據達到數據庫的瓶頸時&#xff0c;性能下滑&#xff0c;影響數據的寫入&#xff0c;導致整個應用的不可用。為了解決這個問題&#xff0c;這時&…

單片機直驅兩相四線步進電機研究

【本文發布于https://blog.csdn.net/Stack_/article/details/132236329&#xff0c;未經允許不得轉載&#xff0c;轉載須注明出處】 雙極性步進電機&#xff08;兩相四線步進電機&#xff09;&#xff0c;原理的東西就先不講太多了&#xff0c;還沒搞清楚&#xff0c;邊查資料邊…

jsoup解析html之table表格

jsoup解析html之table表格 jsoup說明 一款Java 的HTML解析器 jsoup 是一款Java 的HTML解析器&#xff0c;可直接解析某個URL地址、HTML文本內容。它提供了一套非常省力的API&#xff0c;可通過DOM&#xff0c;CSS以及類似于jQuery的操作方法來取出和操作數據。 主要功能 從一…

Python Opencv實踐 - 圖像旋轉

import cv2 as cv import numpy as np import matplotlib.pyplot as pltimg cv.imread("../SampleImages/pomeranian.png", cv.IMREAD_COLOR)#圖像旋轉 #Opencv中的旋轉&#xff0c;首先通過cv.getRotationMatrix2D獲得旋轉矩陣 #cv.getRotationMatrix2D(center,ang…