Spring为我们提供了:
org.springframework.web.servlet.HandlerInterceptor接口,
org.springframework.web.servlet.handler.HandlerInterceptorAdapter适配器,
实现这个接口或继承此类,可以非常方便的实现自己的拦截器。
有以下三个方法:
Action之前执行:
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler);
生成视图之前执行
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView);
最后执行,可用于释放资源
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
分别实现预处理、后处理(调用了Service并返回ModelAndView,但未进行页面渲染)、返回处理(已经渲染了页面)
在preHandle中,可以进行编码、安全控制等处理;
在postHandle中,有机会修改ModelAndView;
在afterCompletion中,可以根据ex是否为null判断是否发生了异常,进行日志记录。
参数中的Object handler是下一个拦截器。
如何使用拦截器?
自定义一个拦截器,要实现HandlerInterceptor接口:
Java代码
public class MyInteceptor implements HandlerInterceptor { 略。。。 }
Spring MVC并没有总的拦截器,不能对所有的请求进行前后拦截。
Spring MVC的拦截器,是属于HandlerMapping级别的,可以有多个HandlerMapping ,每个HandlerMapping可以有自己的拦截器。
当一个请求按Order值从小到大,顺序执行HandlerMapping接口的实现类时,哪一个先有返回,那就可以结束了,后面的HandlerMapping就不走了,本道工序就完成了。就转到下一道工序了。
拦截器会在什么时候执行呢? 一个请求交给一个HandlerMapping时,这个HandlerMapping先找有没有处理器来处理这个请求,如何找到了,就执行拦截器,执行完拦截后,交给目标处理器。
如果没有找到处理器,那么这个拦截器就不会被执行。
在spring MVC的配置文件中配置有三种方法:
方案一,(近似)总拦截器,拦截所有url
Java代码
<mvc:interceptors> <bean class="com.app.mvc.MyInteceptor" /> </mvc:interceptors>
为什么叫“近似”,前面说了,Spring没有总的拦截器。
<mvc:interceptors/>会为每一个HandlerMapping,注入一个拦截器。总有一个HandlerMapping是可以找到处理器的,最多也只找到一个处理器,所以这个拦截器总会被执行的。起到了总拦截器的作用。
如果是REST风格的URL,静态资源也会被拦截。
方案二, (近似) 总拦截器, 拦截匹配的URL。
Xml代码
<mvc:interceptors > <mvc:interceptor> <mvc:mapping path="/user/*" /> <!-- /user/* --> <bean class="com.mvc.MyInteceptor"></bean> </mvc:interceptor> </mvc:interceptors>
就是比 方案一多了一个URL匹配。
如果是REST风格的URL,静态资源也会被拦截。
方案三,HandlerMappint上的拦截器。
如果是REST风格的URL,静态资源就不会被拦截。因为我们精准的注入了拦截器。
Xml代码
<bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping"> <property name="interceptors"> <list> <bean class="com.mvc.MyInteceptor"></bean> </list> </property> </bean>
如果使用了<mvc:annotation-driven />, 它会自动注册DefaultAnnotationHandlerMapping 与AnnotationMethodHandlerAdapter 这两个bean,所以就没有机会再给它注入interceptors属性,就无法指定拦截器。
当然我们可以通过人工配置上面的两个Bean,不使用 <mvc:annotation-driven />,就可以 给interceptors属性 注入拦截器了。
其实我也不建议使用 <mvc:annotation-driven />,而建议手动写详细的配置文件,来替代 <mvc:annotation-driven />,这就控制力就强了。
如何替换 <mvc:annotation-driven />?他到底做了什么工作?
一句 <mvc:annotation-driven />实际做了以下工作:(不包括添加自己定义的拦截器)
我们了解这些之后,对Spring3 MVC的控制力就更强大了,想改哪就改哪里。
Xml代码
<!-- 注解请求映射 --> <bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping"> <property name="interceptors"> <list> <ref bean="logNDCInteceptor"/> <!-- 日志拦截器,这是你自定义的拦截器 --> <ref bean="myRequestHelperInteceptor"/> <!-- RequestHelper拦截器,这是你自定义的拦截器--> <ref bean="myPermissionsInteceptor"/> <!-- 权限拦截器,这是你自定义的拦截器--> <ref bean="myUserInfoInteceptor"/> <!-- 用户信息拦截器,这是你自定义的拦截器--> </list> </property> </bean> <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter"> <property name="messageConverters"> <list> <ref bean="byteArray_hmc" /> <ref bean="string_hmc" /> <ref bean="resource_hmc" /> <ref bean="source_hmc" /> <ref bean="xmlAwareForm_hmc" /> <ref bean="jaxb2RootElement_hmc" /> <ref bean="jackson_hmc" /> </list> </property> </bean> <bean id="byteArray_hmc" class="org.springframework.http.converter.ByteArrayHttpMessageConverter" /><!-- 处理.. --> <bean id="string_hmc" class="org.springframework.http.converter.StringHttpMessageConverter" /><!-- 处理.. --> <bean id="resource_hmc" class="org.springframework.http.converter.ResourceHttpMessageConverter" /><!-- 处理.. --> <bean id="source_hmc" class="org.springframework.http.converter.xml.SourceHttpMessageConverter" /><!-- 处理.. --> <bean id="xmlAwareForm_hmc" class="org.springframework.http.converter.xml.XmlAwareFormHttpMessageConverter" /><!-- 处理.. --> <bean id="jaxb2RootElement_hmc" class="org.springframework.http.converter.xml.Jaxb2RootElementHttpMessageConverter" /><!-- 处理.. --> <bean id="jackson_hmc" class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter" /><!-- 处理json-->
本文向大家介绍Java死锁_动力节点Java学院整理,包括了Java死锁_动力节点Java学院整理的使用技巧和注意事项,需要的朋友参考一下 死锁是两个甚至多个线程被永久阻塞时的一种运行局面,这种局面的生成伴随着至少两个线程和两个或者多个资源。在这里我已写好一个简单的程序,它将会引起死锁方案然后我们就会明白如何分析它。 Java死锁范例 ThreadDeadlock.java 在上面的程序中同步线程
本文向大家介绍Java多态(动力节点Java学院整理),包括了Java多态(动力节点Java学院整理)的使用技巧和注意事项,需要的朋友参考一下 什么是多态 1. 面向对象的三大特性:封装、继承、多态。从一定角度来看,封装和继承几乎都是为多态而准备的。这是我们最后一个概念,也是最重要的知识点。 2. 多态的定义:指允许不同类的对象对同一消息做出响应。即同一消息可以根据发送对象的不同而采用多种不同的行
本文向大家介绍ztree简介_动力节点Java学院整理,包括了ztree简介_动力节点Java学院整理的使用技巧和注意事项,需要的朋友参考一下 【简介】 zTree 是利用 JQuery 的核心代码,实现一套能完成大部分常用功能的 Tree 插件 zTree是一个依靠jQuery实现的多功能“树插件”。优异的性能、灵活的配置、多种功能的组合是zTree最大优点。 官方文档:http://www.t
本文向大家介绍ThreadLocal简介_动力节点Java学院整理,包括了ThreadLocal简介_动力节点Java学院整理的使用技巧和注意事项,需要的朋友参考一下 ThreadLocal,直译为“线程本地”或“本地线程”,如果你真的这么认为,那就错了!其实,它就是一个容器,用于存放线程的局部变量,我认为应该叫做 ThreadLocalVariable(线程局部变量)才对,真不理解为什么当初 S
本文向大家介绍JNDI简介_动力节点Java学院整理,包括了JNDI简介_动力节点Java学院整理的使用技巧和注意事项,需要的朋友参考一下 一、JNDI是什么? JNDI--Java 命名和目录接口(Java Naming and Directory Interface),是一组在Java应用中访问命名和目录服务的API。 二、JNDI好处 解耦:通过注册、查找JNDI服务,可以直接使用服务,而无
本文向大家介绍tomcat简介_动力节点Java学院整理,包括了tomcat简介_动力节点Java学院整理的使用技巧和注意事项,需要的朋友参考一下 tomcat介绍: web服务器只能完成静态资源的请求; web容器能够进行动态资源的请求; tomcat就是一个最简单的web容器,是apache的jarkata项目的子项目。 tomcat 7.0.X支持Servlet 3.0规范,因此建议使用7