spring mvc中的拦截器interceptor

一个拦截器

拦截器(interceptor)是spring mvc中提供的一种类似filter过滤器的技术,只不过拦截器只能拦截controller的请求,而filter可以过滤所有请求,其他内容大体上两者是近似的。

定一个类实现HandlerInterceptor接口,这样就创建了一个拦截器,该接口中有三个方法:

  • preHandle(request, response, Object handler):
    该方法在controller中的方法执行之前执行。其返回值为 boolean,若为 true,则紧接着会执行controller方法,且会将afterCompletion()方法压栈进入入到一个专门的方法栈中等待执行。
  • postHandle(request, response, Object handler, modelAndView):
    该方法在controller方法执行之后执行。controller方法若最终未被执行,则该方法不会执行。由于该方法是在controller方法执行完后执行,且该方法参数中包含 ModelAndView,所以该方法可以修改controller方法的处理结果数据,且可以修改跳转方向。
  • afterCompletion(request, response, Object handler, Exception ex):
    当 preHandle()方法返回 true 时,会将该方法放到专门的方法栈中,等到对请求进行响应的所有
    工作完成之后才执行该方法。即该方法是在中央调度器渲染(数据填充)了响应页面之后执行的,此时对 ModelAndView 再操作也对响应无济于事。 有点像java里面的finally语句块。

自定义一个拦截器:

package com.monkey1024.interceptor;

import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class MyInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

        System.out.println("拦截器中的preHandle方法");
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("拦截器中的postHandle方法");
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("拦截器中的afterCompletion方法");
    }
}

在springmvc.xml文件中注册拦截器,/** 表示对所有controller拦截:

 <!--注册拦截器-->
<mvc:interceptors>
    <mvc:interceptor>
        <mvc:mapping path="/**"/>
        <bean class="com.monkey1024.interceptor.MyInterceptor"/>
    </mvc:interceptor>
</mvc:interceptors>

创建一个controller:

@RequestMapping("test")
public ModelAndView test() {
    ModelAndView mv = new ModelAndView();

    System.out.println("test方法");
    mv.setViewName("result");

    return mv;
}

当有请求被该方法处理的时候,可以看到控制台中打印下面内容:

过滤器
拦截器中的preHandle方法
test方法
拦截器中的postHandle方法
拦截器中的afterCompletion方法

整体的流程如图所示,这里的handler实际上是在DispatcherServlet和Controller之间调用的一个东西,实际上DispatcherServlet是通过handler找到处理当前请求的Controller中的方法,然后再去调用该方法的,更多内容咱们在深入部分再做详解。

Interceptor

多个拦截器

再定义一个拦截器:

public class MyInterceptor2 implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

        System.out.println("拦截器2中的preHandle方法");
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("拦截器2中的postHandle方法");
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("拦截器2中的afterCompletion方法");
    }
}

在springmvc.xml配置文件中注册上面的拦截器:

    <mvc:interceptor>
        <mvc:mapping path="/**"/>
        <bean class="com.monkey1024.interceptor.MyInterceptor2"/>
    </mvc:interceptor>    

当有请求访问controller时,在控制台会打印出下面内容:

拦截器中的preHandle方法
拦截器2中的preHandle方法
test方法
拦截器2中的postHandle方法
拦截器中的postHandle方法
拦截器2中的afterCompletion方法
拦截器中的afterCompletion方法

当有多个拦截器时,会形成拦截器链。拦截器链的执行顺序,与其注册顺序一致。

Interceptor2