Spring攔截器之HandlerInterceptor使用方式
概述
有時候我們需要進(jìn)行一些預(yù)處理和后處理,或者是攔截請求,在請求前后后做一些處理
使用Spring MVC框架,那么建議使用HandlerInterceptor,它可以類似于普通bean直接注冊到Spring容器中被管理
HandlerInterceptor的三個抽象方法
public interface HandlerInterceptor {
default boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
return true;
}
default void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception {
}
default void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception {
}
}preHandle
在執(zhí)行Handler之前(執(zhí)行業(yè)務(wù)邏輯之前),根據(jù)攔截器鏈順序執(zhí)行
- 每個
Interceptor的調(diào)用會依據(jù)它的聲明順序依次執(zhí)行,而且最先執(zhí)行的都是Interceptor 中的preHandle 方法 - 所以可以在這個方法中進(jìn)行一些前置初始化操作或者是對當(dāng)前請求的一個預(yù)處理
- 也可以在這個方法中進(jìn)行一些判斷來決定請求是否要繼續(xù)進(jìn)行下去
該方法的返回值是布爾值Boolean 類型的,
- 當(dāng)它返回為false 時,表示請求結(jié)束,后續(xù)的Interceptor 和Controller 都不會再執(zhí)行;
- 當(dāng)返回值為true 時就會繼續(xù)調(diào)用下一個Interceptor 的preHandle 方法,如果已經(jīng)是最后一個Interceptor 的時候就會是調(diào)用當(dāng)前請求的Controller 方法。
postHandle
在執(zhí)行Handler成功(執(zhí)行業(yè)務(wù)邏輯成功)之后,根據(jù)攔截器鏈倒序執(zhí)行,如果前面的流程中拋出異常或者請求被攔截則不會執(zhí)行!
- 在當(dāng)前所屬的Interceptor 的preHandle 方法的返回值為true 時才能被調(diào)用
- 在當(dāng)前請求進(jìn)行處理之后,也就是Controller 方法調(diào)用之后執(zhí)行,但是它會在DispatcherServlet 進(jìn)行視圖返回渲染之前被調(diào)用,
- 所以我們可以在這個方法中對Controller 處理之后的ModelAndView 對象進(jìn)行操作
- postHandle 方法被調(diào)用的方向跟preHandle 是相反的,也就是說先聲明的Interceptor 的postHandle 方法反而會后執(zhí)行
afterCompletion
在請求處理完畢之后執(zhí)行,無論是否有響應(yīng)視圖,無論有沒有通過preHandle,無論有沒有拋出異常。
只會對此前放行成功(preHandle返回true)的攔截器進(jìn)行倒序調(diào)用。
- 在當(dāng)前所屬的Interceptor 的preHandle 方法的返回值為true 時才能被調(diào)用
- 該方法將在整個請求結(jié)束之后,也就是在DispatcherServlet 渲染了對應(yīng)的視圖之后執(zhí)行。
- 這個方法的主要作用是用于進(jìn)行資源清理工作的
使用
構(gòu)建攔截器(HandlerInterceptor )
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import com.gildata.gup.domain.User;
import com.gildata.gup.domain.UserEncryptReset;
import com.gildata.gup.repository.UserEncryptResetRepository;
@Component // 不可少
public class xxxStateInterceptor implements HandlerInterceptor { // 必須實現(xiàn)HandlerInterceptor接口
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
// TODO Auto-generated method stub
// ....
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
// TODO Auto-generated method stub
return;
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
throws Exception {
// TODO Auto-generated method stub
}
}注冊攔截器(WebMvcConfigurerAdapter )
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import com.gildata.gup.interceptor.PasswordStateInterceptor;
@Configuration // 配置
public class WebConfigfilter extends WebMvcConfigurerAdapter{
@Autowired
private XxxStateInterceptor xxxStateInterceptor ; // 實例化攔截器
@Override
public void addInterceptors(InterceptorRegistry registry) {
// super.addInterceptors(registry);
// 注冊自定義的攔截器passwordStateInterceptor
registry.addInterceptor(xxxStateInterceptor)
.addPathPatterns("/api/*") //匹配要過濾的路徑
.excludePathPatterns("/api/changeUser/*") //匹配不過濾的路徑。/api/changeUser后面的所有接口不能攔截
.excludePathPatterns("/api/getAge", "/api/getName") // /api/getAge也不能攔截,/api/getName這個接口的請求不能攔截
}
}兩個常用方法:
.addPathPatterns():增加url的攔截路徑,“/**”意思是所有請求都要攔截;.excludePathPatterns():排除url的攔截路徑,如:“/api/getAge”, “/api/getName”:意為這兩個接口不做攔截;
注意
springBoot2.0以上 WebMvcConfigurerAdapter 方法過時,有兩種替代方案:
- 繼承 WebMvcConfigurationSupport 類;
- 實現(xiàn) WebMvcConfigurer 接口;
但是,繼承WebMvcConfigurationSupport會讓Spring-boot對mvc的自動配置失效,所以 建議用實現(xiàn)WebMvcConfigurer接口的方式 。
所以上面的注冊攔截器更改為:
@Configuration // 配置
public class WebConfigfilter implements WebMvcConfigurer{
@Autowired
private XxxStateInterceptor xxxStateInterceptor ; // 實例化攔截器
@Override
public void addInterceptors(InterceptorRegistry registry) {
// super.addInterceptors(registry);
// 注冊自定義的攔截器passwordStateInterceptor
registry.addInterceptor(xxxStateInterceptor)
.addPathPatterns("/api/*") //匹配要過濾的路徑
.excludePathPatterns("/api/changeUser/*") //匹配不過濾的路徑。/api/changeUser后面的所有接口不能攔截
.excludePathPatterns("/api/getAge", "/api/getName") // /api/getAge也不能攔截,/api/getName這個接口的請求不能攔截
}
}總結(jié)
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
基于JWT的spring boot權(quán)限驗證技術(shù)實現(xiàn)教程
這篇文章主要給大家介紹了關(guān)于基于JWT的spring boot權(quán)限驗證技術(shù)實現(xiàn)的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-11-11
使用Java 壓縮文件打包tar.gz 包的詳細(xì)教程
本文帶領(lǐng)大家學(xué)習(xí)如何使用Java 壓縮文件打包tar.gz 包,主要通過 Apache compress 工具打包,通過示例代碼給大家介紹的非常詳細(xì),感興趣的朋友跟隨小編一起看看吧2021-05-05
springboot+angular4前后端分離 跨域問題解決詳解
這篇文章主要介紹了springboot+angular4前后端分離 跨域問題解決詳解,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2019-09-09
Mybatis-Plus可能導(dǎo)致死鎖的問題分析及解決辦法
這篇文章給大家主要介紹了Mybatis-Plus可能導(dǎo)致死鎖的問題分析及解決辦法,文中通過代碼示例給大家介紹的非常詳細(xì),具有一定的參考價值,需要的朋友可以參考下2023-12-12
Spring Boot整合MyBatis-Plus實現(xiàn)CRUD操作的示例代碼
本文主要介紹了Spring Boot整合MyBatis-Plus實現(xiàn)CRUD操作,可以快速實現(xiàn)數(shù)據(jù)庫的增刪改查操作,文中通過示例代碼介紹的非常詳細(xì),需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2025-04-04
Java模擬棧和隊列數(shù)據(jù)結(jié)構(gòu)的基本示例講解
這篇文章主要介紹了Java模擬棧和隊列數(shù)據(jù)結(jié)構(gòu)的基本示例,棧的后進(jìn)先出和隊列的先進(jìn)先出是數(shù)據(jù)結(jié)構(gòu)中最基礎(chǔ)的知識,本文則又對Java實現(xiàn)棧和隊列結(jié)構(gòu)的方法進(jìn)行了細(xì)分,需要的朋友可以參考下2016-04-04
java8學(xué)習(xí)教程之lambda表達(dá)式的使用方法
Java8最值得學(xué)習(xí)的特性就是Lambda表達(dá)式,下面這篇文章主要給大家介紹了關(guān)于java8學(xué)習(xí)教程之lambda表達(dá)式使用的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧。2017-09-09

