1.HandlerExecutionChain是一个执行链,当用户的请求到达DispatcherServlet的时候,DispatcherServlet会到HandlerMapping中查找对应的Handler,找到后返回的就是这个:HandlerExecutionChain,里面包含了:

1) 正确的Handler对象

2) Handler的拦截器集合,这里的拦截器对象是:HandlerInterceptor

2.拦截器接口HandlerInterceptor

springmvc拦截器基本使用-LMLPHP

springmvc拦截器基本使用-LMLPHP

其中定义了三个方法:

preHandle:预处理回调方法,在Handler执行前执行,第三个参数为处理器(Controller 实现);

返回值:true 表示继续流程(如调用下一个拦截器或处理器);

false表示流程中断(如登录检查失败),不会继续调用其他的拦截器或处理器;

postHandle :后处理回调方法,实现处理器的后处理(但在渲染视图之前)

afterCompletion: :整个请求处理完毕回调方法,即在视图渲染完毕时回调

当然,这个接口还有一个适配器类:HandlerInterceptorAdapter,对三个方法进行了空实现。我们可以有选择的重写想要实现的方法。

3.拦截器的执行顺序

3.1正常执行顺序

springmvc拦截器基本使用-LMLPHP

3.2异常中断执行顺序

springmvc拦截器基本使用-LMLPHP

4.自定义拦截器

拦截器1:

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView; public class MyInterceptor1 implements HandlerInterceptor { @Override
public void afterCompletion(HttpServletRequest arg0,HttpServletResponse arg1, Object arg2, Exception arg3)
throws Exception {
System.out.println("**********我是拦截器1的后置处理方法。"); } @Override
public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1,
Object arg2, ModelAndView mv) throws Exception {
System.out.println("**********我是拦截器1的前置处理方法。"+mv.getViewName());
} @Override
public boolean preHandle(HttpServletRequest arg0, HttpServletResponse arg1,
Object arg2) throws Exception {
System.out.println("**********我是拦截器1的前置处理方法。");
return true;
} }

拦截器2:

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView; public class MyInterceptor2 implements HandlerInterceptor { @Override
public void afterCompletion(HttpServletRequest arg0,HttpServletResponse arg1, Object arg2, Exception arg3)
throws Exception {
System.out.println("**********我是拦截器2的后置处理方法。"); } @Override
public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1,
Object arg2, ModelAndView mv) throws Exception {
System.out.println("**********我是拦截器2的处理方法。"+mv.getViewName()); } @Override
public boolean preHandle(HttpServletRequest arg0, HttpServletResponse arg1,
Object arg2) throws Exception {
System.out.println("**********我是拦截器2的前置处理方法。");
return true;
} }

编写控制类:

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView; @Controller
@RequestMapping("model/")
public class InterceptorController { @RequestMapping("show")
public ModelAndView show1(){ ModelAndView mv = new ModelAndView("hello"); mv.addObject("msg", "拦截器");
System.out.println("拦截器执行了");
return mv;
}
}

配置自定义拦截器:

<!--配置拦截器的方式-->
<mvc:interceptors>
<!--方式1:直接在这里配置<bean>对所有的Controller都拦截-->
<bean class="cn.pojo.Myinterceptor1">
<!--方式2:通过mvc:interceptor来配置,同时可以指定要拦截的路径:--> <mvc:interceptor>
<!--指定要拦截的路径,这里可以写固定路径,也可以使用Ant风格通配符,/**代表任意层数,任意路径-->
<mvc:mapping path="/**"/>
<bean class="cn.pojo.Myinterceptor2">
</mvc:interceptor> </mvc:interceptors>

结果:

前置方法执行到拦截器2时,返回false,那么Controller和所有拦截器的后置方法以及视图解析都不会执行了。直接执行了前面返回true的拦截器(也就是拦截器1)的完成后方法。

总结:

l 拦截器的前置方法顺序执行,如果返回true,继续。返回false,流程终止,执行前面所有返回true的拦截器的完成方法

l 拦截器的后置方法倒序执行,在Controller执行结束后,视图解析前执行。

l 拦截器完成后方法倒序执行,在视图解析后执行。无论前面是否出错或返回false,已经执行过的拦截器的完成方法都会被执行,类似于finally

05-20 03:31