拦截器

概述

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);
        }
    }
}
posted @   半条咸鱼  阅读(127)  评论(0编辑  收藏  举报
(评论功能已被禁用)
相关博文:
阅读排行:
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 没有源码,如何修改代码逻辑?
· PowerShell开发游戏 · 打蜜蜂
· 在鹅厂做java开发是什么体验
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
点击右上角即可分享
微信分享提示