Springboot?過(guò)濾器、攔截器、全局異常處理的方案處理小結(jié)
Springboot 過(guò)濾器、攔截器、全局異常處理
一 過(guò)濾器(Filter)
過(guò)濾器是JavaWeb
三大組件(Servlet,F(xiàn)ilter,Listener)之一。
Filter
可以把對(duì)資源的請(qǐng)求攔截下來(lái),從而實(shí)現(xiàn)一些功能。
注意:過(guò)濾器一般用于一些通用的操作,比如登錄校驗(yàn),統(tǒng)一編碼處理,敏感字符處理等。
1.定義過(guò)濾器
1.創(chuàng)建一個(gè)類,實(shí)現(xiàn) javax.servlet.Filter
接口,并且實(shí)現(xiàn)其方法。
2.配置過(guò)濾器
在類上增加 @WebFilter
注解,配置攔截資源的路徑,并且在引導(dǎo)類上增加@ServletComponentScan
開啟Servlet
的組件支持。
注意:Filter 是JavaWeb的組件,并非Spring組件,所以還需要在引導(dǎo)類上使用
@ServletComponentScan
開啟對(duì)Filter組件的支持
@WebFilter public class CustomFilter implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException { // 初始化方法,Web服務(wù)啟動(dòng)創(chuàng)建Filter時(shí)調(diào)用一次??梢圆挥弥貙? Filter.super.init(filterConfig); } @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws ServletException, IOException { // 攔截到請(qǐng)求時(shí),調(diào)用該方法。是攔截器的核心 filterChain.doFilter(servletRequest,servletResponse); } @Override public void destroy() { // 銷毀方法,服務(wù)器關(guān)閉時(shí)調(diào)用一次,可以不重寫 Filter.super.destroy(); } }
攔截器Filter的核心方法是 doFilter()
,處理相關(guān)邏輯的代碼幾乎都寫在此處。
可以通過(guò)@WebFilter
注解的屬性urlPatterns
,來(lái)配置需要進(jìn)行過(guò)濾的資源信息。
示例:使用 urlPatterns = "/*"
配置過(guò)濾所有請(qǐng)求
@WebFilter(urlPatterns = "/*") public class CustomFilter implements Filter { @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws ServletException, IOException { //放行對(duì)資源的請(qǐng)求 filterChain.doFilter(servletRequest,servletResponse); } }
3.OncePerRequestFilter
在實(shí)際使用中推薦使用OncePerRequestFilter
,它是Spring框架提供的一個(gè)抽象類,用于確保過(guò)濾器只在每個(gè)請(qǐng)求中被調(diào)用一次。它繼承自
GenericFilterBean
類,并在 doFilter
方法中添加了對(duì)請(qǐng)求是否已被過(guò)濾的判斷邏輯。
OncePerRequestFilter
和 Filter
的根本區(qū)別在于 OncePerRequestFilter
提供了一個(gè)確保過(guò)濾器只在每個(gè)請(qǐng)求中被調(diào)用一次的機(jī)制,而 Filter
接
口本身并沒有提供這樣的機(jī)制。
@Configuration public class JwtAuthenticationFilter extends OncePerRequestFilter { @Override protected void doFilterInternal(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, FilterChain filterChain) throws ServletException, IOException { filterChain.doFilter(httpServletRequest, httpServletResponse); } } }
而且使用OncePerRequestFilter
的實(shí)現(xiàn)類,并不需要在項(xiàng)目的啟動(dòng)類上增加@ServletComponentScan
注解。
二 攔截器(Interceptor)
1.攔截器概述
攔截器是一種動(dòng)態(tài)攔截方法調(diào)用的機(jī)制,與過(guò)濾器類似。是Spring框架中提供的,用來(lái)動(dòng)態(tài)攔截控制器方法的執(zhí)行。
它的主要作用是攔截請(qǐng)求,在指定的方法前后調(diào)用,根據(jù)業(yè)務(wù)需要執(zhí)行預(yù)先設(shè)定的代碼。
2.定義攔截器(Interceptor)
定義一個(gè)攔截器,繼承HandlerInterceper
,并實(shí)現(xiàn)其方法。
HandlerInterceptor
中的方法都提供了默認(rèn)實(shí)現(xiàn),可根據(jù)業(yè)務(wù)需求來(lái)決定重寫哪些方法。
注意要為攔截器添加@Component
注解,將其交給IOC容器管理。
@Component public class CustomInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { //在目標(biāo)資源方法執(zhí)行前執(zhí)行,返回true放行,false 不放行 return true; } @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { //在目標(biāo)資源方法之后執(zhí)行 HandlerInterceptor.super.postHandle(request, response, handler, modelAndView); } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { //在整體請(qǐng)求完成之后調(diào)用 HandlerInterceptor.super.afterCompletion(request, response, handler, ex); } }
@Component
注解是Spring框架中用于表示一個(gè)類為Spring組件的通用注解,通過(guò)添加@Component
注解,可以告訴Spring容器在項(xiàng)目初始化時(shí)將該類實(shí)例化為一個(gè)Bean
,并由Spring容器管理。HandlerInterceptor
是SpringMVC框架中的攔截器接口,用于攔截請(qǐng)求的處理過(guò)程并進(jìn)行響應(yīng)的處理??梢酝ㄟ^(guò)實(shí)現(xiàn)HandlerInterceptor
類來(lái)自定義攔截器,實(shí)現(xiàn)更靈活的業(yè)務(wù)控制。
3.注冊(cè)攔截器
自定義的攔截器,需要進(jìn)行注冊(cè)。可實(shí)現(xiàn)WebMvcConfigurer
接口,實(shí)現(xiàn) addInterceptors
方法,為其添加新的攔截器。
@Configuration public class SpringWebConfigurer implements WebMvcConfigurer { //方式1:如果在定義攔截器的時(shí)候已經(jīng)添加了@Component注解,則直接使用注入的方式,將攔截器對(duì)象注冊(cè)到InterceptorRegistry對(duì)象中 @Resource private CustomInterceptor customInterceptor; @Override public void addInterceptors(InterceptorRegistry registry) { // 使用 addPathPatterns 添加攔截路徑,支持?jǐn)?shù)組 // /**表示攔截所有資源,屬于 AntPathMatcher(螞蟻路徑匹配器)語(yǔ)法 //方式1:使用注入的對(duì)象 registry.addInterceptor(customInterceptor).addPathPatterns("/**"); //方式2:也可以直接創(chuàng)建對(duì)象,添加到InterceptorRegistry對(duì)象中 registry.addInterceptor(new CustomInterceptor()).addPathPatterns("/**"); } }
InterceptorRegistry
是Spring框架中專門用來(lái)管理攔截器的集合類。通過(guò)InterceptorRegistry
對(duì)象,可以添加攔截器。并且指定它們的執(zhí)行順序。WebMvcConfigurer
是Spring框架中用于配置Mvc特性的接口,通過(guò)實(shí)現(xiàn)WebMvcConfigurer
接口,可以對(duì)SpringMVC進(jìn)行自定義配置,包括添加攔截器,資源處理器,視圖解析器等。@Configuration
注解是Spring框架中用于表示配置類的注解,通過(guò)添加@Configuration
注解,可以告訴Spring容器,該類是一個(gè)配置類,其中包含了一些配置信息,例如 Bean的定義,Bean之間的依賴關(guān)系,組件掃描等。addPathPatterns
方法用來(lái)配置需要攔截
的資源路徑。excludePathPatterns
方法用來(lái)配置不需要攔截
的資源路徑。
4.AntPathMatcher
Ant風(fēng)格的路徑模式匹配,AntPathMatcher支持以下通配符:
?
匹配一個(gè)字符*
匹配0個(gè)或多個(gè)字符**
匹配0個(gè)或多個(gè)目錄
5.攔截路徑
攔截路徑的簡(jiǎn)單示意:
6.過(guò)濾器和攔截器的執(zhí)行流程
當(dāng)過(guò)濾器與攔截器同時(shí)存在時(shí),它們的執(zhí)行流程如下:
dispatcherServlet
的說(shuō)明:
dispatcherServlet
是SpringMVC框架中的一個(gè)關(guān)鍵組件,用于所有進(jìn)入應(yīng)用程序的請(qǐng)求并將其分派到相應(yīng)的處理程序(Controller)進(jìn)行處理.dispatcherServlet
是一個(gè)Servlet,負(fù)責(zé)接收HTTP請(qǐng)求并根據(jù)請(qǐng)求的URL,將請(qǐng)求分發(fā)給合適的Controller。dispatcherServlet
可以通過(guò)配置來(lái)定制各種行為,包括URL映射,視圖解析,異常處理等。是整個(gè)SpringMVC框架的核心,負(fù)責(zé)協(xié)調(diào)各個(gè)組件的工作,實(shí)現(xiàn)請(qǐng)求的處理和響應(yīng)的生成。
執(zhí)行流程說(shuō)明:
- 瀏覽器發(fā)送請(qǐng)求,先到過(guò)濾器(Filter)
- 過(guò)濾器(Filter)放行之后,HTTP請(qǐng)求經(jīng)過(guò)dispatcherServlet的派發(fā)到達(dá)攔截器(Interceptor)
- 攔截器(Interceptor)放行之后,請(qǐng)求才會(huì)真正進(jìn)入處理程序(Controller)
- 處理程序(Controller)生成響應(yīng)結(jié)果,將結(jié)果返回到攔截器(Interceptor)
- 攔截器(Interceptor)最后再將結(jié)果返回過(guò)濾器(Filter),最后響應(yīng)給瀏覽器
7.過(guò)濾器和攔截器的區(qū)別
- 接口規(guī)范不同:過(guò)濾器需要實(shí)現(xiàn)Filter接口;而攔截器需要實(shí)現(xiàn)HandlerInterceptor接口,并且需要注冊(cè)到
InterceptorRegistry
集合中。 - 攔截范圍不同:過(guò)濾器會(huì)攔截所有的請(qǐng)求資源;而攔截器只會(huì)攔截
Spring環(huán)境
中的資源。
三 全局異常處理
定義一個(gè)類并且使用 @RestControllerAdvice
注解,則表明我們定義了一個(gè)全局異常處理類。
然后創(chuàng)建方法來(lái)捕獲異常,并且通過(guò)@ExceptionHandler
注解來(lái)表明要捕獲的異常類型。并且將該異常的對(duì)象作為形參傳入方法中。
@RestControllerAdvice public class GlobalExceptionHandler { @ExceptionHandler(RuntimeException.class) public Result runtimeException(RuntimeException runtimeException) { return Result.err(runtimeException.getMessage()); } }
注意:Result
是一個(gè)自定義的統(tǒng)一響應(yīng)格式類,其中包含了響應(yīng)代碼,響應(yīng)消息,和響應(yīng)數(shù)據(jù)。并且定義了幾個(gè)常用的靜態(tài)方法。
以上示例中,為保證返回格式統(tǒng)一,所以使用了Result
作為返回類型。
- @RestControllerAdvice:@RestControllerAdvice 用于定義一個(gè)全局的異常處理類,它結(jié)合了 @ControllerAdvice 和 @ResponseBody 兩個(gè)注解的功能。在 Spring Boot 應(yīng)用中,我們可以使用 @RestControllerAdvice 注解來(lái)統(tǒng)一處理異常,返回統(tǒng)一的錯(cuò)誤信息給前端。
- @ExceptionHandler:@ExceptionHandler 用于在 Spring MVC 控制器類中定義方法來(lái)處理特定類型的異常。當(dāng)控制器中的方法拋出指定類型的異常時(shí),@ExceptionHandler 注解的方法會(huì)被調(diào)用來(lái)處理該異常,從而提供定制化的異常處理邏輯
到此這篇關(guān)于Springboot 過(guò)濾器、攔截器、全局異常處理的文章就介紹到這了,更多相關(guān)Springboot 過(guò)濾器、攔截器、全局異常內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- SpringBoot全局異常處理機(jī)制和配置攔截器方式
- SpringBoot結(jié)果封裝和異常攔截的實(shí)現(xiàn)示例
- SpringBoot切面攔截@PathVariable參數(shù)及拋出異常的全局處理方式
- SpringBoot搭建全局異常攔截
- springboot攔截器過(guò)濾token,并返回結(jié)果及異常處理操作
- SpringBoot @ControllerAdvice 攔截異常并統(tǒng)一處理
- Spring boot項(xiàng)目中異常攔截設(shè)計(jì)和處理詳解
- Spring Boot統(tǒng)一異常攔截實(shí)踐指南(最新推薦)
相關(guān)文章
Mybatis Mapper XML文件-插入,更新,刪除詳解(insert, updat
這篇文章主要介紹了MyBatis的Mapper XML文件中用于插入、更新和刪除數(shù)據(jù)的語(yǔ)句,包括這些語(yǔ)句的屬性和子元素的使用方法2025-02-02Mybatis的parameterType造成線程阻塞問題分析
這篇文章主要詳細(xì)分析了Mybatis的parameterType造成線程阻塞問題,文中有詳細(xì)的解決方法,及相關(guān)的代碼示例,具有一定的參考價(jià)值,感興趣的朋友可以借鑒閱讀2023-06-06springboot如何連接兩個(gè)數(shù)據(jù)庫(kù)(多個(gè))
這篇文章主要介紹了springboot如何連接兩個(gè)數(shù)據(jù)庫(kù)(多個(gè)),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-01-01Java?file類中renameTo方法操作實(shí)例
renameTo()方法是File類的一部分,renameTo()函數(shù)用于將文件的抽象路徑名重命名為給定的路徑名??,下面這篇文章主要給大家介紹了關(guān)于Java?file類中renameTo方法操作的相關(guān)資料,需要的朋友可以參考下2022-11-11Java網(wǎng)絡(luò)通信中ServerSocket的設(shè)計(jì)優(yōu)化方案
今天小編就為大家分享一篇關(guān)于Java網(wǎng)絡(luò)通信中ServerSocket的設(shè)計(jì)優(yōu)化方案,小編覺得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧2019-04-04