HandlerInterceptor翻译过来就是spring拦截器,它在某些功能应用上特别有用:
1. 用户是否登陆以及用户权限管理 (见http://www.ideawu.net/ideablog/category4/article174.html)
2. 根据用户的选择来决定是用HTML还是用Excel来作为View (该应用后面会讲解)
3. blackboard building block的应用:在每一个controller之前都要生成context,在render view之后都要release context
HandlerInterceptor接口有几个重要的方法:
preHandleAction(ActionRequest request, ActionResponse response, Object handler):
该方法会在Controller的方法执行前会被调用,可以使用这个方法来中断或者继续执行链的处理,当返回true
时,处理执行链会继续,当返回false
时,则不会去执行Controller的方法。(验证用户是否登陆就是使用preHandleAction方法的最好例子)
afterActionCompletion(ActionRequest request, ActionResponse response, Object handler, Exception ex)
preHandleRender(RenderRequest request, RenderResponse response, Object handler)
postHandleRender(RenderRequest request, RenderResponse response, Object handler, ModelAndView modelAndView)
postHandleRender方法,因为它有ModelAndView 传进来,那么我们就可以在render view之前往view中添加额外的model对象,或者对view的去处进行修改(例如下面的“用HTML还是用Excel来作为View ”例子就是对view进行了更改)
afterRenderCompletion(RenderRequest request, RenderResponse response, Object handler, Exception ex)
该方法会在render view完成后执行,也可以说在请求过程(request processing)完成之后执行。该方法可以用来清理资源(例如象blackboard building block release context)
总结一下HandlerInterceptor的流程:
- (
DispatcherServlet
maps a request to particular handler and assembles a handler execution chain consisting of the handler that is to be invoked and all of theHandlerInterceptor
instances that apply to the request.) preHandleAction(..)
is called; if the invocation of this method returnstrue
then this workflow continues- The target handler handles the action phase of the request (via
HandlerAdapter.handleAction(..)
) afterActionCompletion(..)
preHandleRender(..)
is called; if the invocation of this method returnstrue
then this workflow continues- The target handler handles the render phase of the request (via
HandlerAdapter.handleRender(..)
) postHandleRender(..)
afterRenderCompletion(..)
自己写的拦截器可以不直接实现HandlerInterceptor,而是扩展实现了HandlerInterceptor接口的具体类HandlerInterceptorAdapter,这样的话我们不需要把上面5个方法都实现,而只需要override我们需要的方法就可以了!
使用拦截器来实现“用HTML还是用Excel来作为View ”功能的例子(只列出关键代码):
search.html:
Search for:
<input type="text" name="query"><br>
Output in:
format" value="xls"/>Excel or
format" value="html"/>Html<br>
<input type="submit"/>
SearchController.java:
protected ModelAndView handleRequestInternal(
HttpServletRequest req, HttpServletResponse response {
String query = RequestUtils.getRequiredStringParameter("query");
List shows; // retrieve shows matching the query
<span style="background-color: rgb(192, 192, 192);"> ModelAndView mav = new ModelAndView("listshows", "shows", shows);</span>
return mav;
}
OutputFormatModificationInterceptor.java:
public class OutputFormatModificationInterceptor
<span style="color:#0000ff;">extends HandlerInterceptorAdapter</span> {
private String parameter;
private String defaultSuffix = "";
private Properties suffices;
// setters and getters omitted
public void <span style="color:#0000ff;">postHandler</span>(
HttpServletRequest request, HttpServletResponse response,
Object handler, <span style="color:#0000ff;">ModelAndView mav</span>) throws Exception {
String format = request.getParameter("format");
String suffix = suffices.getProperty(format);
// modify view name if exists
if (suffix != null) {
<span style="color:#ff0000;">mav.setViewName(mav.getViewName() + suffix);</span> <span style="color:#0000ff;"><strong>//修改view达到使用不同的output格式的目的</strong></span>
} else {
mav.setViewName(mav.getViewName() + defaultSuffix);
}
}<a target=_blank name="1145" style="color: rgb(51, 102, 153);"></a><a target=_blank name="beginpage." style="color: rgb(51, 102, 153);"></a>
configure xml file:
<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping">
<property name="interceptors">
<list>
<ref bean="formatInterceptor"/>
</list>
</property>
</bean>
<bean id="formatInterceptor" class="org.springframework.prospring.web.OutputFormatModificationInterceptor">
<property name="suffices">
<props>
<entry key="xls">-xls</entry>
<entry key="html">-html</entry>
</props>
</property>
<property name="parameter"><value>format</value></property>
<property name="defaultSuffix"><value>-html</value></property>
</bean>
<bean name="/listShows.action" class="org.springframework.prospring.web.controller.ListShowsController">
...
</bean>
那么在blackboard building block里可以使用下面的代码:
public class
BbContextInterceptor
extends
HandlerInterceptorAdapter {
public boolean
preHandle(HttpServletRequest request,
HttpServletResponse response, Object handler)
throws
Exception {
Context ctx = BbServiceManager.getContextManager().setContext(request);
request.setAttribute(requestAttributeKeyForBbContext, ctx);
//check user is login or not is admin or not. if not, return false
return true
;
}
public void
afterCompletion(HttpServletRequest request,
HttpServletResponse response, Object handler, Exception ex)
throws
Exception {
request.removeAttribute(requestAttributeKeyForBbContext);
BbServiceManager.getContextManager().purgeContext();
}
}