?
Dokumen ini menggunakan Manual laman web PHP Cina Lepaskan
Portlet MVC里的控制器和Web MVC的很相似,在兩者之間移植代碼很簡單。
Portlet MVC控制器構(gòu)架的基礎(chǔ)是
org.springframework.web.portlet.mvc.Controller
接口,如下所示。
public interface Controller { ModelAndView handleRenderRequest(RenderRequest request, RenderResponse response) throws Exception; void handleActionRequest(ActionRequest request, ActionResponse response) throws Exception; }
如你所見,Portlet
Controller
接口需要兩個方法來處理Portlet
請求的兩個階段:動作請求和顯示請求。動作階段應(yīng)該能夠處理動作請求,顯示階段應(yīng)該
能夠處理顯示請求,并返回合適的模型和視圖。
盡管Controller
接口是抽象的,但Spring Portlet MVC
提供了很多包含了各種各樣你需要的功能的控制器-它們中的大多數(shù)和Spring Web MVC里的控制器很類似。
Controller
接口只定義每個控制器需要的通用的功能
- 處理動作請求,處理顯示請求,返回模型和視圖。
當然,僅一個Controller
是不夠的。為了提供基本的功能,所有的Spring Portlet
Controller
從
AbstractController
繼承,后者可以訪問Spring
的ApplicationContext
和控制緩存。
表?16.3.?AbstractController
提供的功能
參數(shù) | 解釋 |
---|---|
requireSession |
表明當前的
Controller 是否需要session。
所有的控制器都能使用這個功能。如果這樣的控制器收到請求時,
session不存在,用戶會收到
SessionRequiredException 異常。 |
synchronizeSession |
如果需要控制器在處理用戶session時保持同步,使用
這個參數(shù)。更具體來說,擴展的控制器會覆蓋handleRenderRequestInternal(..)
和handleActionRequestInternal(..) 方法,如果指定了這個參數(shù),
這兩個方法會在處理用戶session時保持同步。 |
renderWhenMinimized |
如果需要在portlet最小化狀態(tài)時,控制器也顯示視圖, 把這個參數(shù)設(shè)為true。這個參數(shù)缺省是false,所以portlet在最小化狀態(tài) 時,不顯示內(nèi)容。 |
cacheSeconds |
在需要控制器覆蓋當前portlet定義的缺省緩存失效時間時,
設(shè)置一個正的整數(shù)。這個參數(shù)缺省是-1 ,
表示不改變?nèi)笔〉木彺?,把它設(shè)為0 ,就是
確保不緩存結(jié)果。 |
requireSession
和
cacheSeconds
屬性是在
AbstractController
的父類
PortletContentGenerator
里聲明的。為了完整性,
把它們列在這里。
在你自己的控制器里繼承AbstractController
時
(不推薦這樣做,因為已經(jīng)有許多現(xiàn)成的控制器,它們可能有你需要的功能),僅需要覆蓋
handleActionRequestInternal(ActionRequest,
ActionResponse)
方法或
handleRenderRequestInternal(RenderRequest,
RenderResponse)
方法(或兩者都覆蓋),實現(xiàn)邏輯,
并返回 ModelAndView
對象(如果是
handleRenderRequestInternal
方法)。
handleActionRequestInternal(..)
和
handleRenderRequestInternal(..)
方法的缺省實現(xiàn)都會
拋出PortletException
,這和JSR-168規(guī)范API里的
GenericPortlet
的行為是一致的。所以只要覆蓋你的控制器
需要處理的方法。
下面簡短的例子包含了一個類和一個在web應(yīng)用context里的聲明。
package samples; import javax.portlet.RenderRequest; import javax.portlet.RenderResponse; import org.springframework.web.portlet.mvc.AbstractController; import org.springframework.web.portlet.ModelAndView; public class SampleController extends AbstractController { public ModelAndView handleRenderRequestInternal( RenderRequest request, RenderResponse response) throws Exception { ModelAndView mav = new ModelAndView("foo"); mav.addObject("message", "Hello World!"); return mav; } } <bean id="sampleController" class="samples.SampleController"> <property name="cacheSeconds" value="120"/> </bean>
為了使得一個簡單的控制器工作,你只需要類似上面的類和在web應(yīng)用context里的聲明, 并且再設(shè)置一下處理器映射(見 第?16.5?節(jié) “處理器映射”)。
盡管你能夠繼承AbstractController
,
Spring Portlet MVC提供了不少具體的實現(xiàn),它們提供了許多在簡單MVC應(yīng)用里常用的功能。
ParameterizableViewController
基本上
和上面的例子類似,除了你能指定web應(yīng)用context返回的視圖的名字。(不需要寫死視圖名稱)。
PortletModeNameViewController
把當前的
Portlet的狀態(tài)作為視圖名,如果Portlet在View模式
(比如:PortletMode.VIEW
),這個“View”就是視圖名。
Spring Portlet MVC提供了和Spring Web MVC完全一致的
command controllers層次結(jié)構(gòu),提供方法來與數(shù)據(jù)對象交互
并且動態(tài)地把參數(shù)從PortletRequest
綁定到數(shù)據(jù)對象上。數(shù)據(jù)對象不需要實現(xiàn)框架相關(guān)的接口,因而你可以
直接操作這些持久化對象。下面讓我們查看Command控制器提供的功能,來了解它們的使用:
AbstractCommandController
- Command控制器,可以用來創(chuàng)建自己的控制器,它能夠?qū)⒄埱罄锏膮?shù)
綁定到指定的數(shù)據(jù)對象。這個類不提供表單功能,但它提供驗證功能,并且
可以在控制器里指定如何處理帶有請求參數(shù)的Command對象。
AbstractFormController
-
提供表單提交支持的抽象控制器。你能夠?qū)Ρ韱芜M行建模,通過從控制器
里得到的Command對象來填充表單。在用戶提交表單后,
AbstractFormController
會綁定字段、進行驗證,
然后把對象返回給控制器來做下一步的動作。支持的功能有:無效表單提交(重新
提交)、驗正和通常的表單流程。你需要實現(xiàn)方法來決定表單的顯示和成功時使用的
視圖。如果你需要表單,但不想在應(yīng)用context里指定用戶看到的視圖,使用這個
控制器。
SimpleFormController
-
一個具體的AbstractFormController
,
對使用對應(yīng)的command對象生成表單提供了更多的支持。
SimpleFormController
可以讓你在用戶成功地提交
表單或其它狀態(tài)時,指定command對象,表單的視圖名以及頁面對應(yīng)的視圖名。
AbstractWizardFormController
–
具體的AbstractFormController
,它提交了向?qū)降慕涌? 來編輯跨多個頁面的command對象。支持多種用戶動作:完成、取消或者頁面變化,所有這些
都可以簡便地在視圖的請求參數(shù)里指定。
這些command控制器是非常強大的,為了有效地使用,需要對它們的原理有 細致的理解。在你開始使用它們前,務(wù)必仔細閱讀它們層次結(jié)構(gòu)的javadoc以及示例。
除了開發(fā)新的控制器,我們可以重用現(xiàn)有的portlet并且在
DispatcherPortlet
把請求映射指向它們。通過PortletWrappingController
,你能實例化一個
現(xiàn)有的Portlet
來作
Controller
,如下所示:
<bean id="wrappingController" class="org.springframework.web.portlet.mvc.PortletWrappingController"> <property name="portletClass" value="sample.MyPortlet"/> <property name="portletName" value="my-portlet"/> <property name="initParameters"> <value> config=/WEB-INF/my-portlet-config.xml </value> </property> </bean>
這會很有價值,因為可以使用攔截器來對送向這些portlet的請求進行預(yù)處理和后處理。
而且也很方便,因為JSR-168沒有提供對過濾機制的支持。比如,可以在一個MyFaces
JSR Portlet外面加上Hibernate的
OpenSessionInViewInterceptor
。