拦截器
概述
1、拦截器需要实现 HandlerInterceptor 接口,或继承 HandlerlnterceptorAdapter 类(已弃用)
2、作用:SpringMVC 中的拦截器用于拦截控制器方法的执行
3、示例
@Component
public class FirstInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("FirstInterceptor -> preHandle");
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("FirstInterceptor -> postHandle");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("FirstInterceptor -> afterCompletion");
}
}
SpringMVC 配置文件
1、对 DispatcherServlet 处理的所有的请求进行拦截
(1)方式一:需要使用注解注入拦截器
<mvc:interceptors>
<!-- bean为拦截器的对象名 -->
<ref bean="firstInterceptor"></ref>
</mvc:interceptors>
(2)方式二:xml 注入拦截器
<mvc:interceptors>
<!-- class为拦截器的全类名 -->
<bean class="Interceptor的全类名"></bean>
</mvc:interceptors>
2、对 DispatcherServlet 处理的指定请求进行拦截
<mvc:interceptors>
<mvc:interceptor>
<!-- mvc:mapping:设置需要拦截的请求,/**:拦截所有请求,/*:只能拦截 / 的下一层目录 -->
<mvc:mapping path="/**"/>
<!-- mvc:exclude-mapping:设置需要排除的请求,即不需要拦截的请求 -->
<mvc:exclude-mapping path="/"/>
<!-- 通过ref或bean标签设置拦截器 -->
<ref bean="firstInterceptor"></ref>
<bean class="Interceptor的全类名"></bean>
</mvc:interceptor>
</mvc:interceptors>通过,通过
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 {
}
}
1、preHandle:控制器方法执行之前,执行 preHandle(),其 boolean 类型的返回值表示是否拦截或放行,返回 true 为放行,即调用控制器方法;返回 false 表示拦截,即不调用控制器方法
2、postHandle:控制器方法执行之后,执行 postHandle()
3、afterComplation:处理完视图和模型数据,渲染视图完毕之后,执行 afterComplation()
多个拦截器的执行顺序
1、若每个拦截器的 preHandle() 都返回 true
(1)此时多个拦截器的执行顺序和拦截器在 SpringMVC 的配置文件的配置顺序有关
(2)preHandle() 按照配置的顺序执行,而 postHandle()、afterComplation() 会按照配置的反序执行
2、若某个拦截器的 preHandle() 返回 false
(1)返回 false 的拦截器(包括)之前的拦截器的 preHandle() 都会执行,postHandle() 都不执行
(2)返回 false 的拦截器(不包括)之前的拦截器的 afterComplation() 都会执行
执行顺序(源码)
1、DispatcherServlet 类
(1)doDispatch 方法
//mappedHandler,执行量,包含拦截器集合、控制器方法
if (!mappedHandler.applyPreHandle(processedRequest, response)) {
//若applyPreHandle返回true,则继续执行之后方法;若applyPreHandle返回false,则return
return;
}
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
mappedHandler.applyPostHandle(processedRequest, response, mv);
(2)processDispatchResult 方法
mappedHandler.triggerAfterCompletion(request, response, null);
2、HandlerExecutionChain 类
boolean applyPreHandle(HttpServletRequest request, HttpServletResponse response) throws Exception {
//preHandle()按顺序执行,第一个拦截器为SpringMVC内置拦截器
for (int i = 0; i < this.interceptorList.size(); i++) {
HandlerInterceptor interceptor = this.interceptorList.get(i);
if (!interceptor.preHandle(request, response, this.handler)) {
//某个拦截器返回false,则跳过postHandle(),直接执行afterCompletion()
triggerAfterCompletion(request, response, null);
//该方法返回false
return false;
}
//若某个拦截器返回false,则interceptorIndex为返回false拦截器的索引-1
this.interceptorIndex = i;
}
//所有拦截器返回true,则该方法返回false
return true;
}
void applyPostHandle(HttpServletRequest request, HttpServletResponse response, @Nullable ModelAndView mv) throws Exception {
//postHandle()反序执行
for (int i = this.interceptorList.size() - 1; i >= 0; i--) {
HandlerInterceptor interceptor = this.interceptorList.get(i);
interceptor.postHandle(request, response, this.handler, mv);
}
}
void triggerAfterCompletion(HttpServletRequest request, HttpServletResponse response, @Nullable Exception ex) {
//applyPreHandle中的interceptorIndex,决定执行起始的拦截器afterCompletion
for (int i = this.interceptorIndex; i >= 0; i--) {
HandlerInterceptor interceptor = this.interceptorList.get(i);
try {
interceptor.afterCompletion(request, response, this.handler, ex);
}
catch (Throwable ex2) {
logger.error("HandlerInterceptor.afterCompletion threw exception", ex2);
}
}
}
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 没有源码,如何修改代码逻辑?
· PowerShell开发游戏 · 打蜜蜂
· 在鹅厂做java开发是什么体验
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战