一个拦截器
拦截器(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中的方法,然后再去调用该方法的,更多内容咱们在深入部分再做详解。
多个拦截器
再定义一个拦截器:
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方法
当有多个拦截器时,会形成拦截器链。拦截器链的执行顺序,与其注册顺序一致。