SpringBoot攔截器的配置使用介紹
1. 配置攔截器
具體步驟:
編寫一自定義攔截器類實現(xiàn)接口 HandlerInterceptor
HandlerInterceptor 接口: 可在三處進(jìn)行攔截——目標(biāo)方法執(zhí)行之前、目標(biāo)方法執(zhí)行完成、頁面渲染以后攔截
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 {
}
}將攔截器注冊到容器中,實現(xiàn) WebMvcConfigurer 中的 addInteraptor,然后將自定義攔截器注冊到攔截器中
指定攔截器規(guī)則 —— 攔截所有 '/**' ,靜態(tài)資源也會被攔截
解決靜態(tài)資源同時被攔截問題:
- 在
addPathPatterns中精確指定精確需要攔截資源 - 在
excludePathPatterns中指定排除靜態(tài)資源
可在 application.properties 文件中指定靜態(tài)資源統(tǒng)一前綴,方便排除靜態(tài)資源
spring.mvc.static-path-pattern=/static/**
2. 一個小 Demo
實現(xiàn)未登錄用戶不能訪問除登錄頁外其他頁面的小Demo
1. 自定義攔截器類—LoginInterceptor
自定義登錄攔截器,實現(xiàn)檢測到用戶未登錄,則攔截用戶對其他資源的訪問,并返回到登錄頁面
package com.wanqing.admin.interceptor;
import lombok.extern.slf4j.Slf4j;
import org.apache.catalina.Session;
import org.springframework.lang.Nullable;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
/*
登錄檢查
*/
@Slf4j // lombok 提供的功能
public class LoginInterceptor implements HandlerInterceptor {
// 目標(biāo)方法執(zhí)行之前
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
log.info("攔截的路徑是{}", request.getRequestURI());
// 登錄檢查邏輯
HttpSession session = request.getSession();
Object loginUser = session.getAttribute("loginUser");
if(loginUser != null){
return true; // 放行
}
// 攔截住,重定向到登錄頁面
request.setAttribute("msg", "未登錄不允許訪問");
request.getRequestDispatcher("/").forward(request, response); // 轉(zhuǎn)發(fā)到當(dāng)前請求
return false;
}
// 目標(biāo)方法執(zhí)行之后
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception {
}
// 頁面渲染完成之后
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception {
}
}2. 將攔截器注冊到容器中
通過下列方法,將攔截器注冊到容器中,并配置好要攔截的路徑和要放行的路徑。本次 demo 中若未登錄則所有路徑都攔截,只放行登錄頁面
package com.wanqing.admin.config;
import com.wanqing.admin.interceptor.LoginInterceptor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class AdminWebConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
// 在攔截器的注冊中心里,添加 Login 攔截器
registry.addInterceptor(new LoginInterceptor())
.addPathPatterns("/**") //所有請求都被攔截,靜態(tài)資源也被攔截
.excludePathPatterns("/","/login","/css/**","/fonts/**","/images/**","/js/**"); // 放行的請求
}
}3. 原理分析
1. 根據(jù)當(dāng)前請求,找到HandlerExecutionChainand,即得到可以處理請求的 Handler,以及 Handler 的所有攔截器
處理器執(zhí)行鏈 :

2. 先順序執(zhí)行所有攔截器的preHandle方法
- 如果返回為true執(zhí)行下一個攔截器的
preHandle; - 若為 false,直接倒敘執(zhí)行所有已經(jīng)執(zhí)行了的攔截器的
afterCompletion方法
Step into:
if (!mappedHandler.applyPreHandle(processedRequest, response)) {
return;
}攔截器方法執(zhí)行 源碼分析:
HandlerExecutionChain.class
—— 順序執(zhí)行所有攔截器的preHandle方法
for(int i = 0; i < this.interceptorList.size(); this.interceptorIndex = i++) {
HandlerInterceptor interceptor = (HandlerInterceptor)this.interceptorList.get(i);
if (!interceptor.preHandle(request, response, this.handler)) {
this.triggerAfterCompletion(request, response, (Exception)null);
return false;
}
}
—— 倒敘執(zhí)行所有已經(jīng)執(zhí)行了的攔截器的 afterCompletion 方法
void triggerAfterCompletion(HttpServletRequest request, HttpServletResponse response, @Nullable Exception ex) {
for(int i = this.interceptorIndex; i >= 0; --i) {
HandlerInterceptor interceptor = (HandlerInterceptor)this.interceptorList.get(i);
try {
interceptor.afterCompletion(request, response, this.handler, ex);
} catch (Throwable var7) {
logger.error("HandlerInterceptor.afterCompletion threw exception", var7);
}
}
}3. 如果任何一個攔截器返回 false,直接跳出不執(zhí)行目標(biāo)方法
4. 所有攔截器都返回 true,執(zhí)行目標(biāo)方法
5. 目標(biāo)方法執(zhí)行后,倒敘執(zhí)行所有攔截器的 postHandle 方法
6. 前面的步驟有任何異常都會直接觸發(fā) afterCompletion 方法
7. 頁面成果渲染完成之后,也會倒敘觸發(fā) afterCompletion 方法
圖解:

到此這篇關(guān)于SpringBoot攔截器的配置使用介紹的文章就介紹到這了,更多相關(guān)SpringBoot攔截器內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
JAVA序列化Serializable及Externalizable區(qū)別詳解
這篇文章主要介紹了JAVA序列化Serializable及Externalizable區(qū)別詳解,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2020-07-07
MyBatis 如何配置多個別名 typeAliasesPackage
一分鐘掌握J(rèn)ava?ElasticJob分布式定時任務(wù)

