SpringBoot拦截器的配置使用介绍
作者:刘婉晴
1. 配置拦截器
具体步骤:
编写一自定义拦截器类实现接口 HandlerInterceptor
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 { } }
将拦截器注册到容器中,实现 WebMvcConfigurer 中的 addInteraptor,然后将自定义拦截器注册到拦截器中
指定拦截器规则 —— 拦截所有 '/**'
,静态资源也会被拦截
解决静态资源同时被拦截问题:
- 在
addPathPatterns
中精确指定精确需要拦截资源 - 在
excludePathPatterns
中指定排除静态资源
可在 application.properties 文件中指定静态资源统一前缀,方便排除静态资源
spring.mvc.static-path-pattern=/static/**
2. 一个小 Demo
实现未登录用户不能访问除登录页外其他页面的小Demo
1. 自定义拦截器类—LoginInterceptor
自定义登录拦截器,实现检测到用户未登录,则拦截用户对其他资源的访问,并返回到登录页面
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 { // 目标方法执行之前 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); // 转发到当前请求 return false; } // 目标方法执行之后 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("/**") //所有请求都被拦截,静态资源也被拦截 .excludePathPatterns("/","/login","/css/**","/fonts/**","/images/**","/js/**"); // 放行的请求 } }
3. 原理分析
1. 根据当前请求,找到HandlerExecutionChainand,即得到可以处理请求的 Handler,以及 Handler 的所有拦截器
处理器执行链 :
2. 先顺序执行所有拦截器的preHandle
方法
- 如果返回为true执行下一个拦截器的
preHandle
; - 若为 false,直接倒叙执行所有已经执行了的拦截器的
afterCompletion
方法
Step into:
if (!mappedHandler.applyPreHandle(processedRequest, response)) { return; }
拦截器方法执行 源码分析:
HandlerExecutionChain.class
—— 顺序执行所有拦截器的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; } }
—— 倒叙执行所有已经执行了的拦截器的 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,直接跳出不执行目标方法
4. 所有拦截器都返回 true,执行目标方法
5. 目标方法执行后,倒叙执行所有拦截器的 postHandle 方法
6. 前面的步骤有任何异常都会直接触发 afterCompletion 方法
7. 页面成果渲染完成之后,也会倒叙触发 afterCompletion 方法
图解:
到此这篇关于SpringBoot拦截器的配置使用介绍的文章就介绍到这了,更多相关SpringBoot拦截器内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!