一、MVC 分层结构:
- 控制器 C
缺省的处理器是一个非常简单的 Controller 接口,它提供了两个方法来处理 Portlet 请求的两个阶段:动作请求和显示请求:
- void handleActionRequest(request,response) //动作阶段处理动作请求
- ModelAndView handleRenderRequest(request,response) //显示阶段应该处理显示请求,并返回合适的模型和视图
这个框架包含了许多相同的控制器实现层次,比如,AbstractController,SimpleFormController等。它在数据绑定、命
令对象使用、 模型处理和视图解析等方面和 Servlet 框架相同。 - 视图 V
这
个框架利用了一个特殊的桥 Servlet ViewRendererServlet 来使用 Servlet
框架里的视图显示功能,这样,Portlet 请求就被转化为 Servlet 请求,Portlet 视图能够以通常的 Servlet
底层代码来显示。这意味着,在 Portlet 里仍能使用当前所有的显示方法,如 JSP、Velocity 等。
二、Web 作用范围的 Bean
Spring Portlet MVC 支持 Web Bean,这些 Bean 的生命周期存在于当前的 HTTP 请求或 HTTP Session(一般的和全局的)里,容器的 WebApplicationContext 提供。
- Request 作用域
注意以下 bean 定义:
<bean id="loginAction" class="test.LoginAction" scope="request"/>
|
针
对每次 HTTP 请求,Spring 容器都会创建一个全新的 loginAction 实例,且该实例仅在当前 HTTP
请求内有效,因此可以根据需要放心的更改所建实例的内部状态,而其他请求中创建的实例,将不会看到这些特定于某个请求的状态变化。当处理请求结束,
request 作用域的 bean 实例将被销毁。
- Session作用域
注意以下 bean 定义:
<bean id="userPreferences" class="test.UserPreferences" scope="session"/>
|
针
对某个 HTTP Session,Spring 容器会创建一个全新的 userPreferences 实例,且仅在当前 HTTP
Session 内有效。与 request 作用域一样,您可以根据需要放心的更改所创建实例的内部状态,而别的 HTTP Session
中创建的实例,将不会看到这些特定于某个 HTTP Session 的状态变化。当 HTTP Session 结束后,在该 HTTP
Session 作用域内的 bean 将被销毁。
在 Portlet 中,这类 Bean 的作用域是单个 portlet 的 session。
- global session 作用域
注意以下 bean 定义:
<bean id="userPreferences" class="test.UserPreferences" scope="globalSession"/>
|
global
session 作用域类似于标准的 HTTP Session 作用域,不过它仅仅在基于 portlet 的 Web
应用中才有意义。Portlet 规范定义了全局 Session 的概念,它被所有构成某个 portlet web 应用的所有 portlet
所共享。在 global session 作用域中定义的 bean 被限定于全局 Portlet Session 的生命周期范围内。
三、DispatcherPortlet
Portlet MVC 是一个请求驱动的框架,它围绕着 Portlet 设计,把请求转发给控制器,提供了便利的 Porltet 应用开发功能。
和一般的 Portlet 一样,需要在 Portlet Web 应用的 portlet.xml 中声明:
<portlet> <portlet-name>test</portlet-name> <portlet-class>org.springframework.web.portlet.DispatcherPortlet</portlet-class> <supports> <mime-type>text/html</mime-type> <portlet-mode>view</portlet-mode> </supports> <portlet-info> <title>Test Portlet</title> </portlet-info> </portlet>
|
在
PortletMVC 框架里,每个 DispatcherPortlet 都有自己的
WebApplicationContext,它不仅接管了所有在根 WebApplicationContext 注册的 Bean,而且还可以在
Portlet 作用范围内对这些 Bean 进行重载,重载后的 Bean 可以定义成对于特定的 Portlet 实例可见。在初始化
DispatcherPortlet 时,框架会在 Web 应用的 WEB-INF 目录下寻找
[portlet-name]-portlet.xml,将其中定义的 Bean 注册到自己的 WebApplicationContext 上。
四、ViewRendererServlet
为
了复用所有 Spring WebMVC 里的视图技术,必须把 PortletRequest/PortletResponse 转换到
HttpServletRequest/HttpServletResponse,然后调用 View 的 render
方法。为此,DispatcherPortlet 使用了一个特殊的 servlet:ViewRendererServlet。
必须在 web.xml 文件里为您的 web 应用声明一个 ViewRendererServlet 的实例:
<servlet>
<servlet-name>ViewRendererServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.ViewRendererServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ViewRendererServlet</servlet-name>
<url-pattern>/WEB-INF/servlet/view</url-pattern>
</servlet-mapping>
五、处理器映射
通
过处理器映射,可以把 portlet 请求对应到合适的处理器上。在 Spring WebMVC 里,处理器映射通常是基于 URL 的。但是在
Portlet 里没有 URL,必须使用其它的机制来控制映射。最常见的是根据 portlet 模式和请求参数,但在 portlet
请求里的任何对象都可以用在自定义的处理器映射中。
根据 portlet 模式和请求参数,主要有下列处理器映射可用:
- PortletModeHandlerMapping
基于当前的 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>
|
- ParameterHandlerMapping
在不改变 portlet 模式的情况下在多个控制器间切换,把一个请求参数作为 key 来控制映射。
ParameterHandlerMapping 使用一个特定的请求参数来控制映射。这个参数的缺省名是 'action',可以通过 'parameterName' 属性来改变。
Bean设置如下:
<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>
|
- PortletModeParameterHandlerMapping
PortletModeParameterHandlerMapping 结合了前两者的功能,如下:
<bean id="portletModeParameterHandlerMapping" class="org.springframework.web.portlet.handler.PortletModeParameterHandlerMapping"> <property name="portletModeParameterMap"> <map> <entry key="view"><!-- 'view' portlet模式 --> <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模式 --> <map> <entry key="prefs" value-ref="prefsHandler"/> <entry key="resetPrefs" value-ref="resetPrefsHandler"/> </map> </entry> </map> </property> </bean>
|
六、异常处理
和
Web MVC 一样,Portlet MVC 提供了 HandlerExceptionResolver 来处理异常,PortletMVC
同样也提供了具体的 SimpleMappingExceptionResolver,可以将抛出的异常对应到一个视图名。