在Spring Portlet MVC中,我们可以用PortletModeHandlerMapping来将Portlet模式绑定到对应的Handler上,并且再这里可以声明拦截器,示例代码如下:
- <bean id="portletModeHandlerMapping" class="org.springframework.web.portlet.handler.PortletModeHandlerMapping">
- <property name="portletModeMap">
- <map>
- <entry key="view">
- <bean class="xx.xx.xx.envprovisioning.handlers.EnvProvisionFlowHandler" />
- entry>
- map>
- property>
- <property name="interceptors">
- <list>
- <ref bean="envprovisionhandlerinterceptor"/>
- list>
- property>
- bean>
我们结合框架代码来具体看下这个类是如何工作的。
从最基本的看,它是事先了spring mvc portlet的HandlerMapping 接口,这个接口主要定义了getHandler()方法:
- public interface HandlerMapping {
- HandlerExecutionChain getHandler(PortletRequest request) throws Exception;
- }
这个接口的getHandler()方法可以返回对于某种PortletRequest(RenderRequest,ActionRequest,ResourceRequest)的对应的处理方法,并且返回一个HandlerExecutionChain对象,我们可以根据自己的需要注册多个Handler(对应不同类型的PortletRequest)
而在PortletModeHandlerMapping的父类AbstractHandlerMapping中给出了getHandler()的默认实现:
- public final HandlerExecutionChain getHandler(PortletRequest request) throws Exception {
- Object handler = getHandlerInternal(request);
- if (handler == null) {
- handler = getDefaultHandler();
- }
- if (handler == null) {
- return null;
- }
- // Bean name or resolved handler?
- if (handler instanceof String) {
- String handlerName = (String) handler;
- handler = getApplicationContext().getBean(handlerName);
- }
- return getHandlerExecutionChain(handler, request);
- }
从这里可以看出它会先调用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()方法,如下:
- public void initApplicationContext() throws BeansException {
- super.initApplicationContext();
- registerHandlersByMode(this.portletModeMap);
- }
它回去调用父类的initApplicationContext()然后调用registerHandlerByMode(),我们分别看:
对于initApplicationContext(),它会初始化拦截器的设定,也就是对应我们一开始的xml定义中的interceptors属性,它会分别初始化并且使用这些拦截器:
- protected void initApplicationContext() throws BeansException {
- extendInterceptors(this.interceptors);
- initInterceptors();
- }
而对于registerHandlerByMode(this.portletModeMap),则会先读取xml bean定义文件中的portletModeMap属性,然后对于其中定义的每一对元素,来根据其中的PortletMode来注册/实例化对应的Handler ,这个我们已经在上文中讨论过了。
现在我们对这个过程已经一目了然了