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的流程:

  1. (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 the HandlerInterceptor instances that apply to the request.)
  2. preHandleAction(..) is called; if the invocation of this method returns true then this workflow continues
  3. The target handler handles the action phase of the request (via HandlerAdapter.handleAction(..))
  4. afterActionCompletion(..)
  5. preHandleRender(..) is called; if the invocation of this method returns true then this workflow continues
  6. The target handler handles the render phase of the request (via HandlerAdapter.handleRender(..))
  7. postHandleRender(..)
  8. 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();
 
 
    }
 
 
}