在Spring Portlet MVC中,我们可以用PortletModeHandlerMapping来将Portlet模式绑定到对应的Handler上,并且再这里可以声明拦截器,示例代码如下:

  1. <bean id="portletModeHandlerMapping" class="org.springframework.web.portlet.handler.PortletModeHandlerMapping"> 
  2.         <property name="portletModeMap"> 
  3.             <map> 
  4.                 <entry key="view"> 
  5.                     <bean class="xx.xx.xx.envprovisioning.handlers.EnvProvisionFlowHandler" /> 
  6.                 entry> 
  7.             map> 
  8.         property> 
  9.         <property name="interceptors">   
  10.             <list>   
  11.                 <ref bean="envprovisionhandlerinterceptor"/> 
  12.             list>   
  13.         property> 
  14.     bean> 

我们结合框架代码来具体看下这个类是如何工作的。

从最基本的看,它是事先了spring mvc portlet的HandlerMapping 接口,这个接口主要定义了getHandler()方法:

 

  1. public interface HandlerMapping { 
  2.  
  3.     HandlerExecutionChain getHandler(PortletRequest request) throws Exception; 
  4.  

这个接口的getHandler()方法可以返回对于某种PortletRequest(RenderRequest,ActionRequest,ResourceRequest)的对应的处理方法,并且返回一个HandlerExecutionChain对象,我们可以根据自己的需要注册多个Handler(对应不同类型的PortletRequest)

而在PortletModeHandlerMapping的父类AbstractHandlerMapping中给出了getHandler()的默认实现:

  1. public final HandlerExecutionChain getHandler(PortletRequest request) throws Exception {  
  2.         Object handler = getHandlerInternal(request);  
  3.         if (handler == null) {  
  4.             handler = getDefaultHandler();  
  5.         }  
  6.         if (handler == null) {  
  7.             return null;  
  8.         }  
  9.         // Bean name or resolved handler?  
  10.         if (handler instanceof String) {  
  11.             String handlerName = (String) handler;  
  12.             handler = getApplicationContext().getBean(handlerName);  
  13.         }  
  14.         return getHandlerExecutionChain(handler, request);  
  15.     } 

 从这里可以看出它会先调用getHandlerInternal(request), 这个方法是定义在AbstractMapBaseHandlerMapping类中,它用来从handlerMap中提取key(比如"view")等,然后,获取Value(Handler的类名) 。

然后在第10-14行,通过这个Handler的名字,来在Spring Application中建立起对应这个handler对应的bean,并且将控制权返回给执行Handler的执行链。

 

而我们研究的PortletModelHandlerMapping类则主要用于从xml文件中读取参数,设置拦截器等等。在PortletModeHandlerMapping对应的bean,(也就是我们定义在xml文件的Spring Application Context上下文定义的portletModeHandlerMapping)初始化时候,它会调用PortletModeHandlerMapping的initApplicationContext()方法,如下:

  1. public void initApplicationContext() throws BeansException {  
  2.         super.initApplicationContext();  
  3.         registerHandlersByMode(this.portletModeMap);  
  4.     } 

它回去调用父类的initApplicationContext()然后调用registerHandlerByMode(),我们分别看:

 

对于initApplicationContext(),它会初始化拦截器的设定,也就是对应我们一开始的xml定义中的interceptors属性,它会分别初始化并且使用这些拦截器:

  1. protected void initApplicationContext() throws BeansException {  
  2.         extendInterceptors(this.interceptors);  
  3.         initInterceptors();  
  4.     } 

 

而对于registerHandlerByMode(this.portletModeMap),则会先读取xml bean定义文件中的portletModeMap属性,然后对于其中定义的每一对元素,来根据其中的PortletMode来注册/实例化对应的Handler ,这个我们已经在上文中讨论过了。

 

现在我们对这个过程已经一目了然了