SpringBoot 攔截器妙用你真的了解嗎
HandlerInterceptor 詳解
HandlerInterceptor 允許定制 handler 處理器執(zhí)行鏈的工作流接口。我們可以自定義攔截器用于攔截 handlers 處理器(你可以理解為 controller 層的接口),從而可以添加一些共同的重復(fù)性的處理行為(例如接口鑒權(quán),接口日志記錄,性能監(jiān)控等),而不用修改每一個 handler 的實現(xiàn)。
注意,此基于 SpringBoot 2.3.12.RELEASE 版本講解。
HandlerInterceptor 接口只有三個默認(rèn)空實現(xiàn)方法,在低版本中這三個方法不是默認(rèn)方法,而是抽象方法。
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 {
}
}
這三個方法的執(zhí)行順序圖如下:

preHandle
preHandle 前置處理,攔截一個處理器(handler)的執(zhí)行,preHandle 方法會在 HandlerMapping 確定一個適當(dāng)?shù)奶幚砥鲗ο笾?,但?HandlerAdapter 調(diào)用處理器之前被調(diào)用??梢院唵卫斫鉃?controller 接口被調(diào)用之前執(zhí)行。
Intercepter 是鏈?zhǔn)降模褪且粋€接著一個執(zhí)行。如果此方法返回 true,則會執(zhí)行下一個攔截器或者直接執(zhí)行處理器。如果此方法返回 false 或者拋出異常則終止執(zhí)行鏈,也不再調(diào)用處理器。
注意,此方法如果不返回 true,那么 postHandle 和 afterCompletion 不會被執(zhí)行。
那這個方法有什么用呢?其實可以做一些接口被調(diào)用前的預(yù)處理,例如用戶權(quán)限校驗。
package com.chenpi;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.lang.Nullable;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
/**
* @Description 用戶權(quán)限驗證攔截
* @Author 陳皮
* @Date 2021/6/27
* @Version 1.0
*/
@Component
public class UserPermissionInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response,
Object handler) {
if (handler instanceof HandlerMethod) {
HandlerMethod handlerMethod = (HandlerMethod) handler;
// 獲取用戶權(quán)限校驗注解
UserAuthenticate userAuthenticate =
handlerMethod.getMethod().getAnnotation(UserAuthenticate.class);
if (null == userAuthenticate) {
userAuthenticate = handlerMethod.getMethod().getDeclaringClass()
.getAnnotation(UserAuthenticate.class);
}
if (userAuthenticate != null && userAuthenticate.permission()) {
// 驗證用戶信息
UserContext userContext = userContextManager.getUserContext(request);
if (null == userContext) {
return false;
}
}
}
return true;
}
}
postHandle
postHandle 后置處理,會在 HandlerAdapter 調(diào)用處理器之后,但在 DispatcherServlet 渲染視圖之前被調(diào)用??梢栽诖藢?ModelAndView 做一些額外的處理??梢院唵卫斫鉃?controller 接口被調(diào)用之后執(zhí)行。
注意,此方法在執(zhí)行鏈中的執(zhí)行順序是倒著執(zhí)行的,即先聲明的攔截器后執(zhí)行。
afterCompletion
afterCompletion 完成之后,在請求處理完之后被執(zhí)行,也就是渲染完視圖之后。一般用于做一些資源的清理工作,配合 preHandle 計算接口執(zhí)行時間等。
注意,和 postHandle 一樣,此方法在執(zhí)行鏈中的執(zhí)行順序也是倒著執(zhí)行的,即先聲明的攔截器后執(zhí)行。
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response,
Object handler, @Nullable Exception ex) {
// 請求完后,清除當(dāng)前線程的用戶信息
UserContextHolder.removeUserContext();
}
注冊攔截器
注意,我們自定義的攔截器要通過 WebMvcConfigurer 的實現(xiàn)類進(jìn)行注冊,才能生效。
package com.yzj.ehr.common.config;
import com.yzj.ehr.common.context.UserContextResolver;
import org.springframework.stereotype.Component;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import com.yzj.ehr.common.interceptor.UserPermissionInterceptor;
/**
* @Description 注冊攔截器
* @Author 陳皮
* @Date 2021/6/27
* @Version 1.0
*/
@Component
public class WebAppConfigurer implements WebMvcConfigurer {
private UserPermissionInterceptor userPermissionInterceptor;
public WebAppConfigurer(final UserPermissionInterceptor userPermissionInterceptor) {
this.userPermissionInterceptor = userPermissionInterceptor;
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
// 匹配所有接口,排除/base/test接口
registry.addInterceptor(userPermissionInterceptor).addPathPatterns("/**")
.excludePathPatterns("/base/test");
}
}
到此這篇關(guān)于SpringBoot 攔截器妙用你真的了解嗎的文章就介紹到這了,更多相關(guān)SpringBoot 攔截器內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
SpringBoot進(jìn)行參數(shù)校驗的方法詳解
在日常的接口開發(fā)中,為了防止非法參數(shù)對業(yè)務(wù)造成影響,經(jīng)常需要對接口的參數(shù)進(jìn)行校驗。本文通過示例詳細(xì)講解了SpringBoot如何進(jìn)行參數(shù)校驗的,感興趣的可以學(xué)習(xí)一下2022-04-04
springboot mybatis里localdatetime序列化問題的解決
這篇文章主要介紹了springboot mybatis里localdatetime序列化問題,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-10-10
Spring Cloud實戰(zhàn)技巧之使用隨機(jī)端口
這篇文章主要給大家介紹了關(guān)于Spring Cloud實戰(zhàn)技巧之使用隨機(jī)端口的相關(guān)資料,文中介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面跟著小編一起來學(xué)習(xí)學(xué)習(xí)吧。2017-06-06
Mybatis結(jié)果集映射與生命周期詳細(xì)介紹
結(jié)果集映射指的是將數(shù)據(jù)表中的字段與實體類中的屬性關(guān)聯(lián)起來,這樣 MyBatis 就可以根據(jù)查詢到的數(shù)據(jù)來填充實體對象的屬性,幫助我們完成賦值操作2022-10-10

