一、自定义拦截器
假如我们在访问有些网页的时候可能会提示无权访问,因为我们的访问请求会被拦截器拦截到,并给我们显示无权访问的提示页面。下面我们使用SpringMVC来演示一下自定义拦截器的使用。
Spring MVC可以使用拦截器对请求进行拦截处理,用户可以自定义拦截器来实现特定的功能,自定义的拦截器必须实现HandlerInterceptor接口。
1.首先我们先编写如下拦截器类,具体代码如下:
public class FirstInterceptor implements HandlerInterceptor {
/**
* 该方法在目标方法之前被调用。
* 若返回值为true,则继续调用后续的拦截器和目标方法;
* 若返回值为false,则不会再调用后续的拦截器和目标方法
*
* 可以考虑做权限。日志,事务等。
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
System.out.println("FirstInterceptor:preHandle");
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");
}
}
- preHandle():这个方法在业务处理器处理请求之前被调用,在该方法中对用户请求 request 进行处理。如果程序员决定该拦截器对请求进行拦截处理后还要调用其他的拦截器,或者是业务处理器去进行处理,则返回true;如果程序员决定不需要再调用其他的组件去处理请求,则返回false。
- postHandle():这个方法在业务处理器处理完请求后,但是DispatcherServlet 向客户端返回响应前被调用,在该方法中对用户请求request进行处理。
- afterCompletion():这个方法在 DispatcherServlet 完全处理完请求后被调用,可以在该方法中进行一些资源清理的操作。
2.然后在MVC配置文件中配置自定义的拦截器,具体如下所示:
<!-- 配置自定义拦截器 -->
<mvc:interceptors>
<!-- 拦截所有,即该控制器里的所有目标方法都会被拦截 -->
<bean class="com.shoto.springmvc.interceptors.FirstInterceptor"></bean>
</mvc:interceptors>
3.编写控制器类的目标方法,代码如下:
@RequestMapping("/testInterceptor")
public String testInterceptor() {
System.out.println("目标方法testInterceptor执行啦。。。");
return "success";
}
4.在页面进行请求响应之后,其运行结果如下所示:
FirstInterceptor:preHandle
目标方法testInterceptor执行啦。。。
FirstInterceptor:postHandle
FirstInterceptor:afterCompletion
根据如上运行结果和对源码进行debug可以知道,单个拦截器方法执行顺序如下图所示:
二、拦截器配置
上述我们在MVC配置文件中配置自定义的拦截器时,是配置了拦截所有控制器类中的所有目标方法,当然我们也可以拦截指定目标方法或不拦截指定的目标方法。如下示:
<mvc:interceptors>
<!-- 拦截所有目标方法 -->
<!-- <bean class="com.shoto.springmvc.interceptors.FirstInterceptor"></bean> -->
<!-- 拦截指定的目标方法,其他方法则不拦截 -->
<mvc:interceptor>
<mvc:mapping path="/testInterceptor"/>
<bean class="com.shoto.springmvc.interceptors.FirstInterceptor"></bean>
</mvc:interceptor>
<!-- 不拦截指定的目标方法,其他的都拦截 -->
<!-- <mvc:interceptor>
拦截所有的请求,这个必须写在前面,也就是写在【不拦截】的上面
<mvc:mapping path="/**"/>
<mvc:exclude-mapping path="/testInterceptor"/>
<bean class="com.shoto.springmvc.interceptors.FirstInterceptor"></bean>
</mvc:interceptor> -->
</mvc:interceptors>
三、多个拦截器方法执行顺序
基于上述示例,在创建一个拦截器SecondInterceptor,具体同FirstInterceptor拦截器相似,只是输出语句不同。
运行请求响应测试之后,输出结果如下所示:
FirstInterceptor:preHandle
SecondInterceptor:preHandle
目标方法testInterceptor执行啦。。。
SecondInterceptor:postHandle
FirstInterceptor:postHandle
SecondInterceptor:afterCompletion
FirstInterceptor:afterCompletion
两个拦截器的运行流程如下图所示(preHandle的返回值都为true的情形):
注意:拦截器在MVC配置文件的配置顺序决定了那个拦截器先执行。
当SecondInterceptor的preHandle返回false时,其执行流程如下图所示:
测试输出结果如下所示:
FirstInterceptor:preHandle
SecondInterceptor:preHandle
FirstInterceptor:afterCompletion
从运行结果和执行流程我们也可以知道,当preHandle返回true时,其所对应的afterCompletion一定也会执行,其可以用于释放资源等。