SpringMVC-拦截器


过滤器—>DispatcherServlet---->Controller方法

拦截器对Controller方法 进行拦截

filter是servlet之前拦截,interceptor是触发请求方法拦截

拦截器中的3个抽象方法

控制器方法,也叫处理器方法,Handerle

preHanderle 就是在控制器方法前执行

postHanderle控制器方法后执行

afterComplerion 渲染视图后执行
image-20220407185535342

使用案例

//extends HandlerInterceptorAdapter 也可以 官方说过时了
@Component
public class FirstInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("FirstInterceptor--->preHandle");
        //HandlerInterceptor.super.preHandle(request, response, handler) 默认的这个应该是true;
        //返回f 是拦截
        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");
    }
}

2
@Component
public class SecondInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("SecondInterceptor--->preHandle");
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("SecondInterceptor--->postHandle");

    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("SecondInterceptor--->afterCompletion");
    }
}

2.配置(注册)拦截器

方法一:

<mvc:interceptors>
    <!--当前的拦截器就配置完成了-->
    <bean class="com.dong.mvc.Interceptor.FirstInterceptor"></bean>
</mvc:interceptors>

方法二:扫描这个bean,然后在类上加上@Component,然后再写下面的配置。

<mvc:interceptors>
        <!--当前的拦截器就配置完成了-->
        <ref bean="firstInterceptor"></ref>
    </mvc:interceptors>
  • 方法一和二会对所有的前端控制器处理的请求进行拦截

方法三:

这个就可以自定义拦截的访问路径

        <mvc:interceptor>
            <mvc:mapping path="/**"/>
            <mvc:exclude-mapping path="/"/>
 <!-- 当前拦截所有前端控制器处理的请求 除了主页面/ -->
            <bean class="com.dong.mvc.Interceptor.FirstInterceptor"></bean>
        </mvc:interceptor>
    </mvc:interceptors>
 <mvc:mapping path="/*"/> 这个/* 表示拦截web目录下一层的请求,不会拦截访问下下层的请求,/** 才是所有的请求

和dispatcherServlet里的规则不一样

public class FirstInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("FirstInterceptor--->preHandle");
        //HandlerInterceptor.super.preHandle(request, response, handler) 默认的这个应该是true;
        //返回f 是拦截
        return true;
    }

多个时的执行顺序

两个拦截器时:

<bean class="com.dong.mvc.Interceptor.FirstInterceptor"></bean>
<bean class="com.dong.mvc.Interceptor.SecondInterceptor"></bean>

顺序:输出结果:

FirstInterceptor—>preHandle
SecondInterceptor—>preHandle
SecondInterceptor—>postHandle
FirstInterceptor—>postHandle
SecondInterceptor—>afterCompletion
FirstInterceptor—>afterCompletion

  • preHandle:配置的顺序

  • afterCompletion,postHandle:配置的反序

源码分析:

boolean applyPreHandle(HttpServletRequest request, HttpServletResponse response) throws Exception {
   for (int i = 0; i < this.interceptorList.size(); i++) {
      HandlerInterceptor interceptor = this.interceptorList.get(i);
      if (!interceptor.preHandle(request, response, this.handler)) {
         triggerAfterCompletion(request, response, null);
         return false;
      }
      this.interceptorIndex = i;
   }
   return true;
}

interceptorList是根据配置文件中的顺序加进去的拦截器

所以PreHandle这里是顺序执行的

interceptorindex可以理解为最后一个成功的拦截器

void applyPostHandle(HttpServletRequest request, HttpServletResponse response, @Nullable ModelAndView mv)
      throws Exception {

   for (int i = this.interceptorList.size() - 1; i >= 0; i--) {
      HandlerInterceptor interceptor = this.interceptorList.get(i);
      interceptor.postHandle(request, response, this.handler, mv);
   }
}

i-- 反序执行的postHandle

void triggerAfterCompletion(HttpServletRequest request, HttpServletResponse response, @Nullable Exception ex) {
   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);
      }
   }
}

interceptorIndex 代表的是interceptor的preHandle返回true的最后一个

也就是 已经放行了的拦截器会执行afterCompletion,而applyPostHandle是不管放行了没有都会执行的

通过第一段的源码 我们应该发现 一旦有一个拦截后所有的PostHandle都不执行,而afterCompletion会执行前面已经放行了的对应的afterCompletion

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值