SpringMVC中使⽤Interceptor顺序等
SpringMVC 中的Interceptor 也是相当重要和相当有⽤的,它的主要作⽤是拦截⽤户的请求并进⾏相应的处理。⽐如通过它来进⾏权限验证,或者是来判断⽤户是否登陆,或者是像12306 那样⼦判断当前时间是否是购票时间。
⼀、定义Interceptor实现类
SpringMVC 中的Interceptor 拦截请求是通过HandlerInterceptor 来实现的。在SpringMVC 中定义⼀个Interceptor ⾮常简单,主要有两种⽅式,第⼀种⽅式是要定义的Interceptor类要实现了Spring 的HandlerInterceptor 接⼝,或者是这个类继承实现了HandlerInterceptor 接⼝的类,⽐如Spring 已经提供的实现了HandlerInterceptor 接⼝的抽象类HandlerInterceptorAdapter ;第⼆种⽅式是实现Spring的WebRequestInterceptor接⼝,或者是继承实现了WebRequestInterceptor的类。
(⼀)实现HandlerInterceptor接⼝
HandlerInterceptor 接⼝中定义了三个⽅法,我们就是通过这三个⽅法来对⽤户的请求进⾏拦截处理的。
(1 )preHandle (HttpServletRequest request, HttpServletResponse response, Object handle) ⽅法,顾名思义,该⽅法将在请求处理之前进⾏调⽤。SpringMVC 中的Interceptor 是链式的调⽤的,在⼀个应
⽤中或者说是在⼀个请求中可以同时存在多个Interceptor 。每个Interceptor 的调⽤会依据它的声明顺序依次执⾏,⽽且最先执⾏的都是Interceptor 中的preHandle ⽅法,所以可以在这个⽅法中进⾏⼀些前置初始化操作或者是对当前请求的⼀个预处理,也可以在这个⽅法中进⾏⼀些判断来决定请求是否要继续进⾏下去。该⽅法的返回值是布尔值Boolean类型的,当它返回为false 时,表⽰请求结束,后续的Interceptor 和Controller 都不会再执⾏;当返回值为true 时就会继续调⽤下⼀个Interceptor 的preHandle ⽅法,如果已经是最后⼀个Interceptor 的时候就会是调⽤当前请求的Controller ⽅法。
(2 )postHandle (HttpServletRequest request, HttpServletResponse response, Object handle, ModelAndView modelAndView) ⽅法,由preHandle ⽅法的解释我们知道这个⽅法包括后⾯要说到的afterCompletion ⽅法都只能是在当前所属的Interceptor 的preHandle ⽅法的返回值为true 时才能被调⽤。postHandle ⽅法,顾名思义就是在当前请求进⾏处理之后,也就是Controller ⽅法调⽤之后执⾏,但是它会在DispatcherServlet 进⾏视图返回渲染之前被调⽤,所以我们可以在这个⽅法中对
Controller 处理之后的ModelAndView 对象进⾏操作。postHandle ⽅法被调⽤的⽅向跟preHandle 是相反的,也就是说先声明的Interceptor 的postHandle ⽅法反⽽会后执⾏,这和Struts2 ⾥⾯的Interceptor 的执⾏过程有点类型。Struts2 ⾥⾯的Interceptor 的执⾏过程也是链式的,只是在Struts2 ⾥⾯需要⼿动调⽤ActionInvocation 的invoke ⽅法来触发对下⼀个Interceptor 或者是Action 的调⽤,然后每⼀个Interceptor 中在invoke ⽅法调⽤之前的内容都是按照声明顺序执⾏的,⽽invoke ⽅法之后
的内容就是反向的。
(3 )afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handle, Exception ex) ⽅法,该⽅法也是需要当前对应的Interceptor 的preHandle ⽅法的返回值为true 时才会执⾏。顾名思义,该⽅法将在整个请求结束之后,也就是在DispatcherServlet 渲染了对应的视图之后执⾏。这个⽅法的主要作⽤是⽤于进⾏资源清理⼯作的。
下⾯是⼀个简单的代码说明:
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
public class SpringMVCInterceptor implements HandlerInterceptor {
/**
* preHandle⽅法是进⾏处理器拦截⽤的,顾名思义,该⽅法将在Controller处理之前进⾏调⽤,SpringMVC中的Interceptor是链式的,可以同时存在
* 多个Interceptor,然后SpringMVC会根据声明的前后顺序⼀个接⼀个的执⾏,⽽且所有的Interceptor中的preHandle⽅法都会在
* Controller⽅法调⽤之前调⽤。SpringMVC的这种Interceptor链式结构也是可以进⾏中断的,这种中断⽅式是令preHandle的返
* 回值为false,当preHandle的返回值为false的时候整个请求就结束了。
*/
@Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response, Object handler) throws Exception {
// TODO Auto-generated method stub
return false;
}
/**
* 这个⽅法只会在当前这个Interceptor的preHandle⽅法返回值为true的时候才会执⾏。postHandle是进⾏处理器拦截⽤的,它的执⾏时间是在处理器进⾏处理之
* 后,也就是在Controller的⽅法调⽤之后执⾏,但是它会在DispatcherServlet进⾏视图的渲染之前执⾏,也就是说在这个⽅法中你可以对ModelAndView进⾏操
* 作。这个⽅法的链式结构跟正常访问的⽅向是相反的,也就是说先声明的Interceptor该⽅法反⽽会后调⽤,这跟Struts2⾥⾯的的执⾏过程有点像,
* 只是Struts2⾥⾯的intercept⽅法中要⼿动的调⽤ActionInvocation的invoke⽅法,Struts2中调⽤ActionInvocation的invoke⽅法就是调⽤下⼀个Interceptor
* 或者是调⽤action,然后要在Interceptor之前调⽤的内容都写在调⽤invoke之前,要在Interceptor之后调⽤的内容都写在调⽤invoke⽅法之后。
*/
@Override
public void postHandle(HttpServletRequest request,
HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
// TODO Auto-generated method stub
}
/**
* 该⽅法也是需要当前对应的Interceptor的preHandle⽅法的返回值为true时才会执⾏。该⽅法将在整个请求完成之后,也就是DispatcherServlet渲染了视图执⾏,
* 这个⽅法的主要作⽤是⽤于清理资源的,当然这个⽅法也只能在当前这个Interceptor的preHandle⽅法的返回值为true时才会执⾏。
*/
@Override
public void afterCompletion(HttpServletRequest request,
HttpServletResponse response, Object handler, Exception ex)
throws Exception {
// TODO Auto-generated method stub
}
}
(⼆)实现WebRequestInterceptor 接⼝
WebRequestInterceptor 中也定义了三个⽅法,我们也是通过这三个⽅法来实现拦截的。这三个⽅法都传递了同⼀个参数
WebRequest ,那么这个WebRequest 是什么呢?这个WebRequest 是Spring 定义的⼀个接⼝,它⾥⾯的⽅法定义都基本跟HttpServletRequest ⼀样,在WebRequestInterceptor 中对WebRequest 进⾏的所有操作都将同步到HttpServletRequest 中,然后在当前请求中⼀直传递。
(1 )preHandle(WebRequest request) ⽅法。该⽅法将在请求处理之前进⾏调⽤,也就是说会在Controller ⽅法调⽤之前被调⽤。这个⽅法跟HandlerInterceptor 中的preHandle 是不同的,主要区别在于该⽅法的返回值是void ,也就是没有返回值,所以我们⼀般主要⽤它来进⾏资源的准备⼯作,⽐如我们在使⽤Hibernate 的时候可以在这个⽅法中准备⼀个Hibernate 的Session 对象,然后利⽤WebRequest 的setAttribute(name, value, scope)把它放到WebRequest 的属性中。这⾥可以说说这个setAttribute ⽅法的第三个参数scope ,该参数是⼀个Integer类型的。在WebRequest 的⽗层接⼝RequestAttributes 中对它定义了三个常量:
SCOPE_REQUEST :它的值是0 ,代表只有在request 中可以访问。
SCOPE_SESSION :它的值是1 ,如果环境允许的话它代表的是⼀个局部的隔离的session,否则就代表普通的session,并且在该session范围内可以访问。
SCOPE_GLOBAL_SESSION :它的值是2 ,如果环境允许的话,它代表的是⼀个全局共享的session,否则就代表普通的session,并且在该session 范围内可以访问。
(2 )postHandle(WebRequest request, ModelMap model) ⽅法。该⽅法将在请求处理之后,也就是在Controller ⽅法调⽤之后被调⽤,但是会在视图返回被渲染之前被调⽤,所以可以在这个⽅法⾥⾯通过改变数据模型ModelMap 来改变数据的展⽰。该⽅法有两个参数,WebRequest 对象是⽤于传递整个请求数据的,⽐如在preHandle 中准备的数据都可以通过WebRequest 来传递和访问;ModelMap 就是Controller 处理之后返回的Model 对象,我们可以通过改变它的属性来改变返回的Model 模型。
(3 )afterCompletion(WebRequest request, Exception ex) ⽅法。该⽅法会在整个请求处理完成,也就是在视图返回并被渲染之后执⾏。所以在该⽅法中可以进⾏资源的释放操作。⽽WebRequest 参数就可以把我们在preHandle 中准备的资源传递到这⾥进⾏释放。Exception 参数表⽰的是当前请求的异常对象,如果在Controller中抛出的异常已经被Spring 的异常处理器给处理了的话,那么这个异常对象就是是null 。
下⾯是⼀个简单的代码说明:
import org.springframework.ui.ModelMap;
import org.t.request.WebRequest;
import org.t.request.WebRequestInterceptor;
public class AllInterceptor implements WebRequestInterceptor {
/**
* 在请求处理之前执⾏,该⽅法主要是⽤于准备资源数据的,然后可以把它们当做请求属性放到WebRequest中
*/
@Override
public void preHandle(WebRequest request) throws Exception {
// TODO Auto-generated method stub
System.out.println("");
request.setAttribute("request", "request", WebRequest.SCOPE_REQUEST);//这个是放到request范围内的,所以只能在当前请求中的request中获取到
request.setAttribute("session", "session", WebRequest.SCOPE_SESSION);//这个是放到session范围
内的,如果环境允许的话它只能在局部的隔离的会话中访问,否则就是在普通的当前会话中可以访问
request.setAttribute("globalSession", "globalSession", WebRequest.SCOPE_GLOBAL_SESSION);//如果环境允许的话,它能在全局共享的会话中访问,否则就是在普通的当前会话中访问
}
/**
* 该⽅法将在Controller执⾏之后,返回视图之前执⾏,ModelMap表⽰请求Controller处理之后返回的Model对象,所以可以在
* 这个⽅法中修改ModelMap的属性,从⽽达到改变返回的模型的效果。
*/
@Override
public void postHandle(WebRequest request, ModelMap map) throws Exception {
// TODO Auto-generated method stub
for (String key:map.keySet())
System.out.println(key + "-------------------------");;
map.put("name3", "value3");
map.put("name1", "name1");
}
/**
* 该⽅法将在整个请求完成之后,也就是说在视图渲染之后进⾏调⽤,主要⽤于进⾏⼀些资源的释放
*/
@Override
public void afterCompletion(WebRequest request, Exception exception)
throws Exception {
/
/ TODO Auto-generated method stub
System.out.println(exception + "-=-=--=--=-=-=-=-=-=-=-=-==-=--=-=-=-=");
}
}
⼆、把定义的类加到SpringMVC的拦截体系中
1.在SpringMVC的配置⽂件中加上⽀持MVC的schema
xmlns:mvc="/schema/mvc"
xsi:schemaLocation=" /schema/mvc
       /schema/mvc/spring-mvc-3.0.xsd"
下⾯是我的声明⽰例:
这样在SpringMVC的配置⽂件中就可以使⽤mvc标签了,mvc标签中有⼀个mvc:interceptors是⽤于声明SpringMVC的的。
(⼆)使⽤mvc:interceptors标签来声明需要加⼊到SpringMVC链中的
<mvc:interceptors>
<!-- 使⽤bean定义⼀个Interceptor,直接定义在mvc:interceptors根下⾯的Interceptor将拦截所有的请求 -->
<bean class="com.host.app.web.interceptor.AllInterceptor"/>
<mvc:interceptor>
<mvc:mapping path="/test/number.do"/>
<!-- 定义在mvc:interceptor下⾯的表⽰是对特定的请求才进⾏拦截的 -->
<bean class="com.host.app.web.interceptor.LoginInterceptor"/>
springmvc常用标签
</mvc:interceptor>
</mvc:interceptors>
由上⾯的⽰例可以看出可以利⽤mvc:interceptors标签声明⼀系列的,然后它们就可以形成⼀个链,的执⾏顺序是按声明的先后顺序执⾏的,先声明的中的preHandle⽅法会先执⾏,然⽽它的postHandle⽅法和afterCompletion⽅法却会后执⾏。
在mvc:interceptors标签下声明interceptor主要有两种⽅式:
(1)直接定义⼀个Interceptor实现类的bean对象。使⽤这种⽅式声明的Interceptor将会对所有的请求进⾏拦截。
(2)使⽤mvc:interceptor标签进⾏声明。使⽤这种⽅式进⾏声明的Interceptor可以通过mvc:mapping⼦标签来定义需要进⾏拦截的请求路径。
经过上述两步之后,定义的就会发⽣作⽤对特定的请求进⾏拦截了。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。