SpringMVC 中的 Interceptor 拦截器的主要作用就是拦截用户的 url 请求,并在执行 handler 方法的前中后加入某些特殊请求,类似于 servlet 里面的过滤器.
一、springmvc拦截器的配置与测试
1、在springmvc中,定义拦截器要实现HandlerInterceptor接口,并实现该接口中提供的三个方法
2、需要在springmvc-servlet.xml中注册拦截器组件
1、实现Handler接口
public class LoginIntercepeter implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
System.out.println("拦截器前置方法1。。。");
return true;
}
@Override
public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
System.out.println("拦截器中间方法1。。。");
}
@Override
public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
System.out.println("拦截器后置方法1。。。");
}
}
简单说一下三个方法
1、preHandle方法:进入Handler方法之前执行。可以用于身份认证、身份授权。比如如果认证没有通过表示用户没有登陆,需要此方法拦截不再往下执行(return false),否则就放行(return true)。
2、postHandle方法:进入Handler方法之后,返回ModelAndView之前执行。可以看到该方法中有个modelAndView的形参。应用场景:从modelAndView出发:将公用的模型数据(比如菜单导航之类的)在这里传到视图,也可以在这里同一指定视图。
3、afterCompletion方法:执行Handler完成之后执行。应用场景:统一异常处理,统一日志处理等。
2、注册Handler组件
<!--拦截器-->
<mvc:interceptors>
<mvc:interceptor>
<!--通配符,拦截子节点及孙节点-->
<mvc:mapping path="/login/**"/>
<bean class="com.controller.LoginIntercepeter"></bean>
</mvc:interceptor>
</mvc:interceptors>
简单说一下拦截器组件
1、可以配置多个拦截器,也可以在拦截器中排除指定拦截等
2、拦截器的执行顺序是按照在 springmvc 配置文件中的位置来顺序执行的
3、测试被拦截的控制器
@Controller
@RequestMapping("/login")
public class Login {
@RequestMapping("/req")
public String req(){
System.out.println("req...");
return "FileYes";
}
}
4、在浏览器测试
输入对应地址,得到结果如下
拦截器前置方法1。。。
req...
拦截器中间方法1。。。
拦截器后置方法1。。。
二、多个拦截器测试
使用三个拦截器进行测试,第一次测试全部放行,第二次测试中有一个拦截器不放行
一、全部放行
1、Handler
以下Handler共有三个,全部放行
public class LoginIntercepeter3 implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
System.out.println("拦截器前置3.。。");
return true;
}
@Override
public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
System.out.println("拦截器中间3.。。");
}
@Override
public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
System.out.println("拦截器后置3");
}
}
2、注册组件
<!--拦截器-->
<mvc:interceptors>
<mvc:interceptor>
<!--通配符,拦截子节点及孙节点-->
<mvc:mapping path="/login/**"/>
<bean class="com.controller.LoginIntercepeter"></bean>
</mvc:interceptor>
<mvc:interceptor>
<mvc:mapping path="/login/**"/>
<bean class="com.controller.LoginIntercepeter2"></bean>
</mvc:interceptor>
<mvc:interceptor>
<mvc:mapping path="/login/**"/>
<bean class="com.controller.LoginIntercepeter3"></bean>
</mvc:interceptor>
</mvc:interceptors>
3、测试控制器
@Controller
@RequestMapping("/login")
public class Login {
@RequestMapping("/req")
public String req(){
System.out.println("req...");
return "FileYes";
}
}
4、测试
拦截器前置方法1。。。
拦截器前置2.。。
拦截器前置3.。。
req...
拦截器中间3.。。
拦截器中间2.。。
拦截器中间方法1。。。
拦截器后置3
拦截器后置2.。。
拦截器后置方法1。。。
二、有一个不放行
此时拦截器3中的preHandle方法返回值为false,此时测试
拦截器前置方法1。。。
拦截器前置2.。。
拦截器前置3.。。
拦截器后置2.。。
拦截器后置方法1。。。
根据打印的结果做一个总结:
1. 由于拦截器1和2放行,所以拦截器3的preHandle才能执行。也就是说前面的拦截器放行,后面的拦截器才能执行preHandle。
2. 拦截器3不放行,所以其另外两个方法没有被执行。即如果某个拦截器不放行,那么它的另外两个方法就不会执行。
3. 只要有一个拦截器不放行,所有拦截器的postHandle方法都不会执行,但是只要执行过preHandle并且放行的,就会执行afterCompletion方法。
因为拦截器3没有放行,所以本该返回的页面也没有得到。。。