?
Dieses Dokument verwendet PHP-Handbuch für chinesische Websites Freigeben
通過處理器映射,可以把進來的portlet請求對應(yīng)到合適的處理器上。已經(jīng)有一些
現(xiàn)成的處理器映射可以使用,比如PortletModeHandlerMapping
。
但還是讓我們先看一下HandlerMapping
的一般概念。
注意,我們這里有意使用“處理器”來代替“控制器”。
DispatcherPortlet
是設(shè)計用來和多種方式一起處理請求的,
而不僅僅是和Spring Portlet MVC自己的控制器。處理器是任意可以處理Portlet請求的對象。
控制器當然缺省是一種處理器。要將DispatcherPortlet
和一些其他的框架一起使用,只需要實現(xiàn)相應(yīng)的HandlerAdapter
就可以了。
HandlerMapping
提供的基本功能是提供一個
HandlerExecutionChain
,后者必須包含匹配進來請求的
的處理器,也可能包含需要應(yīng)用到請求的處理器攔截器的列表。當一個請求進來時,
DispatcherPortlet
會把它交給處理器射映,讓它來檢查
請求并得到合適的HandlerExecutionChain
。然后
DispatcherPortlet
會執(zhí)行處理器以及chain里的攔截器。這些
概念和Spring Web MVC中的完全一致。
可配置的處理器映射非常強大,它可以包含攔截器(在實際的處理前、后進行預(yù)處理或后處理
或兩者都執(zhí)行)??梢酝ㄟ^自定義一個HandlerMapping
來加入許多功能。
想像一下,一個自定義的處理器映射,它不僅可以根據(jù)指定的portlet模式來選擇處理器,
也可以根據(jù)請求相聯(lián)系的session里的指定狀態(tài)來選擇。
在Spring Web MVC里,處理器映射通常是基于URL的。因為在Portlet里確實沒有URL, 必須使用其它的機制來控制映射。最常見的兩個是portlet模式和請求參數(shù), 但在portlet請求里的任何對象都可以用在自定義的處理器映射中。
余下的章節(jié)會介紹在Spring Portlet MVC里最常見的三種處理器射映,
它們都繼承AbstractHandlerMapping
并且共享以下的屬性:
interceptors
: 需要使用的攔截器列表。
HandlerInterceptor
在
第?16.5.4?節(jié) “增加 HandlerInterceptor
s”有討論。
defaultHandler
: 在找不到匹配的處理器時,缺省的處理器。
order
: Spring會按照order屬性值
(見org.springframework.core.Ordered
接口)
對context里的所有處理器映射進行排序,并且應(yīng)用第一個匹配的處理器。
lazyInitHandlers
: 用來Lazy初始化單例
處理器(prototype處理器是始終lazy初始化的)。缺省值是false。這個屬性是在這三個具體處理器里直接實現(xiàn)。
這是一個簡單的處理器映射,它是基于當前的portlet模式(比如:'view', 'edit', 'help')。如下:
<bean id="portletModeHandlerMapping" class="org.springframework.web.portlet.handler.PortletModeHandlerMapping"> <property name="portletModeMap"> <map> <entry key="view" value-ref="viewHandler"/> <entry key="edit" value-ref="editHandler"/> <entry key="help" value-ref="helpHandler"/> </map> </property> </bean>
如果需要在不改變portlet模式的情況下而在多個控制器間切換, 最簡單的方法是把一個請求參數(shù)作為key來控制映射。
ParameterHandlerMapping
使用一個特定的請求參數(shù)來控制映射。
這個參數(shù)的缺省名是'action'
,可以通過'parameterName'
屬性來改變。
這個映射的bean設(shè)置會是這樣:
<bean id="parameterHandlerMapping" class="org.springframework.web.portlet.handler.ParameterHandlerMapping”> <property name="parameterMap"> <map> <entry key="add" value-ref="addItemHandler"/> <entry key="edit" value-ref="editItemHandler"/> <entry key="delete" value-ref="deleteItemHandler"/> </map> </property> </bean>
最強大的內(nèi)置處理映射
PortletModeParameterHandlerMapping
結(jié)合了前兩者的功能,
能夠在每種portlet模式下進行不同的切換。
同樣,參數(shù)的缺省名是“action”,但可以通過 parameterName
來修改。
缺省情況下,同樣的參數(shù)值不能在兩個不同的portlet模式下使用,
因為如果portlet自己改變了portlet模式,那么請求在映射中將不在有效。
把 allowDupParameters
屬性設(shè)為true可以改變這種行為,但這種做法是不推薦的。
這個映射的bean設(shè)置會是這樣:
<bean id="portletModeParameterHandlerMapping" class="org.springframework.web.portlet.handler.PortletModeParameterHandlerMapping"> <property name="portletModeParameterMap"> <map> <entry key="view"> <!-- 'view' portlet mode --> <map> <entry key="add" value-ref="addItemHandler"/> <entry key="edit" value-ref="editItemHandler"/> <entry key="delete" value-ref="deleteItemHandler"/> </map> </entry> <entry key="edit"> <!-- 'edit' portlet mode --> <map> <entry key="prefs" value-ref="prefsHandler"/> <entry key="resetPrefs" value-ref="resetPrefsHandler"/> </map> </entry> </map> </property> </bean>
這個映射可以在處理鏈中放在
PortletModeHandlerMapping
前面,它可以為每個模式以及全局提供缺省的映射。
Spring的處理器映射機制里有處理器攔截器的概念,在希望對于特定的請求 應(yīng)用不同的功能時,它是非常有用。比如,檢查用戶名(principal)。同樣,Spring Portlet MVC以Web MVC相同的方式實現(xiàn)了這些概念。
在處理器映射里的攔截器必須實現(xiàn)org.springframework.web.portlet
里的HandlerInterceptor
接口。
和servlet的版本一樣,這個接口定義了三個方法:一個在實際的處理器執(zhí)行前被調(diào)用
(preHandle
),一個在執(zhí)行后被調(diào)用(postHandle
)
還有一個是在請求完全結(jié)束時被調(diào)用(afterCompletion
)。
這三個方法應(yīng)該可以為各種前置和后置處理提供足夠的靈活。
preHandle
返回一個布爾值??梢允褂眠@個方法來中斷或者繼續(xù)執(zhí)行鏈的處理。
當返回true
時,處理執(zhí)行鏈會繼續(xù),當返回false
時,
DispatcherPortlet
假設(shè)這個攔截器已經(jīng)處理請求(比如,顯示了合適的視圖)并且不需要繼續(xù)執(zhí)行其它的
攔截器和在執(zhí)行鏈中實際的處理器。
postHandle
只會在RenderRequest
中被調(diào)用。ActionRequest
和RenderRequest
都會調(diào)用preHandle
和afterCompletion
方法。
如果希望只在其中的一種請求中執(zhí)行你的代碼,務(wù)必在處理前檢查請求的類型。
和servlet包類似,portlet包里也有一個 HandlerInterceptor
的具體實現(xiàn) HandlerInterceptorAdapter
。這個類所有方法都是空的,
所以可以繼承它,實現(xiàn)一個或兩個你所需要的方法。
Portlet包也帶一個名為ParameterMappingInterceptor
的具體攔截器,它可以和ParameterHandlerMapping
以及PortletModeParameterHandlerMapping
一起使用。
這個攔截器可以把用來控制映射的參數(shù)從ActionRequest
帶到隨后的RenderRequest
,這能夠確保
RenderRequest
映射到和
ActionRequest
相同的處理器。這些都是在
preHandle
方法里完成的,所以在你的處理器里仍然可以改變決定
RenderRequest
映射的參數(shù)值。
注意這個攔截器會調(diào)用ActionResponse
的setRenderParameter
方法,這意味著在使用它的時候,
不能在處理器里調(diào)用sendRedirect
。如果確實需要重定向,
可以手工地把映射參數(shù)向前傳,或者另寫一個攔截器來處理。