资源描述
IBM WebSphere Portal 开 发 者 教 程 - - WPS6.0项 目 实 践 郑文平 著
概述
Spring 框架包含了一个 MVC 层,提供了构建 Web 应用程序的功能。 Spring MVC 支持多种视图技术,例如 JSP、Velocity、Tiles、iText 和 POI。同时,相对于 Struts,JSF 等其它 Web 层框架,使用 Spring MVC 框架可以更充分地发挥 Spring 框架本身提供的组件装配和 AOP 的威力。
针对 JSR-168 Portlet,Spring 同样提供了一套类似的 MVC 框架。Portlet 工作流程和 Servlet 的主要差异在于,Portlet 的请求处理有两个独特的阶段:动作(Action)阶段和呈现(Render)阶段。动作阶段会有"后台"数据改变或动作的代码,这些代码只会执行一次。显示阶段会产生用户每次刷新时看到的显示内容。在单个请求的整个处理过程中,动作阶段只会被执行一次,而显示阶段可能会被执行多次。这就要求在改变系统持久状态的活动和产生显示内容的活动之间,有一个清晰的分层,Spring Portlet MVC 框架很好地体现了这一点。
相对于 Servlet 的作用域,JSR-168 Portlet 的 session 分为两种,一种是作用于整个页面并被页面上所有 Portlet 共享的 globalsession,它实质上就是 Servlet 的 session;另一种仅仅作用于单个 portlet 应用程序。针对 Web 开发,Spring 2.x 不仅新增了 request,session 两种 beanscope,而且专门针对 JSR-168 Portlet 新增了 globalSession 和 session 两种 bean scope。
本文通过开发、运行环境的搭建,以及相应的示例程序开发,向读者展示如何基于 Spring 2.x 构建 JSR-168 Portlet 应用,以及开发中需要注意到的 Spring 2.x Portlet MVC 框架特性。
在示例应用程序的开发和部署中用到了下列产品:
· JDK 1.5 或者更高版本
· Apache Tomcat 6.x
· Apache Pluto 1.1.4
· Apache Maven 2.x
· Eclipse Europa(Eclipse V3.3) for JavaEE Developers
· SpringFramework 2.x
回页首
JSR-168 Portlet 运行环境的搭建
SpringFramework 2.x 构建于 JDK 1.5 平台,所以我们最好使用一个支持 JDK 1.5 的 Portlet 容器实现,Apache Pluto 1.1.4 满足了这个需求,它可以用来测试我们编写的 Portlet 是否与 Portlet 规范相一致。
Apache Pluto 是 JSR-168 的参考实现,是实现了 Portlet API 的 Portlet 容器,充当 Portlet 的运行时环境,与 Web 应用服务器的 Servlet 容器的运行时环境支持 Servlet 的情形非常相似。在本文中,我们将使用 Apache Pluto 测试我们的 Portlet 应用程序。
Apache 官方提供的绑定于 Tomcat 5.x 的版本不能很好地支持 EclipseIDE 下的开发调试,所以我们需要使用 Pluto 1.1.4 的源代码从头构建一个 Portlet 容器环境。以下操作均在 WindowsXP SP2 操作系统下进行。
1. 安装 JDK 1.5 并设定环境变量
该步骤一般读者都比较熟悉,不再拗述。
2. 安装 Maven 2
Pluto 源代码使用 Maven 2 进行项目管理和构建,我们必须首先安装该工具。
从 http://maven.apache.org/ 上寻找 Maven 2 的最新版本压缩包,下载并解压,将 bin 目录加到系统的 PATH 环境变量中。笔者所使用版本为 2.0.8,安装路径为 D:\apache-maven-2.0.8,目录结构如下。
D:\APACHE-MAVEN-2.0.8
├─bin
├─boot
├─conf
└─lib
将 bin 目录加到系统环境变量 PATH 中。
3. 安装 Tomcat 6
从 http://tomcat.apache.org/ 上寻找 Tomcat 6 的最新版本压缩包,下载并解压。笔者所使用版本为 6.0.14,安装路径为 D:\apache-tomcat-6.0.14,目录结构如下:
D:\APACHE-TOMCAT-6.0.14
├─bin
├─conf
├─lib
├─logs
├─temp
├─webapps
└─work
4. 下载 Apache Pluto 1.1.4 源码
从 下载源码压缩包并解压,笔者解压到 D:\pluto-1.1.4,目录结构如下:
D:\PLUTO-1.1.4
├─maven-pluto-plugin
├─pluto-ant-tasks
├─pluto-container
├─pluto-descriptor-api
├─pluto-descriptor-impl
├─pluto-portal
├─pluto-portal-driver
├─pluto-portal-driver-impl
├─pluto-site
├─pluto-site-skin
├─pluto-taglib
├─pluto-testsuite
└─pluto-util
5. 使用 Maven 2 构建 Pluto 1.1.4
编辑 D:\apache-maven-2.0.8\conf 目录下的 settings.xml 文件,增加 <pluginGroups> 元素:
<settings>
...
<pluginGroups>
<pluginGroup>org.apache.pluto</pluginGroup>
</pluginGroups>
...
</settings>
命令行模式下进入 D:\pluto-1.1.4 目录,执行以下命令:
D:\>cd pluto-1.1.4
D:\pluto-1.1.4>mvn install
D:\pluto-1.1.4>mvn pluto:install -DinstallDir=D:/apache-tomcat-6.0.14
如果您的 Tomcat 安装路径中存在空格,则需要用双引号把路径引起来:
mvn pluto:install -DinstallDir="C:\Program Files\Apache Software Foundation\Tomcat 6.0"
至此,pluto 1.1.4 的相关文件就被安装到 Tomcat 相应目录下。
编辑 D:/apache-tomcat-6.0.14/conf/tomcat-users.xml 文件,添加角色 pluto,并在该角色下新增一个用户,以下为示例文件:
<?xml version="1.0" encoding="UTF-8"?>
<tomcat-users>
<role rolename="role1"/>
<role rolename="pluto"/>
<role rolename="tomcat"/>
<role rolename="manager"/>
<user password="pluto" roles="pluto,manager" username="pluto"/>
<user password="tomcat" roles="role1" username="role1"/>
<user password="tomcat" roles="tomcat,role1" username="both"/>
<user password="tomcat" roles="tomcat,pluto,manager" username="tomcat"/>
</tomcat-users>
6. 验证安装
运行 D:/apache-tomcat-6.0.14/bin/startup.sh,启动 Tomcat 服务器。浏览器访问 URL http://localhost:8080/pluto/portal,如 图 1 所示:
图 1. Pluto 登录界面
输入添加到 pluto 角色的用户名和密码,进入 Pluto 的 Portal 页面:
图 2. Pluto Portal 界面
至此,JSR-168 Portlet 运行环境 Apache Pluto 搭建成功。
回页首
使用 Eclipse Europa 建立开发环境
首先,需要从 Eclipse 官方网站 http://www.eclipse.org 下载 EclipseEuropa,针对不同的开发需求,有几种包可供下载。我们进行的是 J2EEWeb 开发,所以注意要下载 Eclipse IDE for Java EE Developers。
启动 Eclipse,对 Eclipse 进行配置:
执行菜单项目 Window -> Preferences,打开 Preferences 对话框,选择 Server-> InstalledRuntimes 项,如 图 3 所示:
图 3. Preferences 对话框
点击 Add 按钮,将 Tomcat 6 添加为运行时,如 图 4、图 5 所示:
图 4. 选择运行时类型
图 5. 设定 Tomcat 安装路径
单击 Finish 结束配置,单击 OK 关闭 Preferences 对话框。
在 Eclipse 的 Servers 视图中单击鼠标右键,选择 New -> Server。如 图 6 所示:
图 6. 新建服务器
在弹出的窗口中选择目标运行服务器 Apache Tomcat 6.0 Server,运行时呈现 ApacheTomcat V6.0,如 图 7 所示,点击 Finish。
图 7. 选择目标运行服务器
在 Servers 视图中双击刚刚新建的 Tomcat 服务器,打开服务器配置页面,如 图 8 所示:
图 8. Tomcat 服务器配置页面
在 Server Locations 中选择 Use Tomcat Installation, DeployPath 选择 D:\apache-tomcat-6.0.14\webapps,如 图 9 所示。至此开发环境设置完毕。
必须设定 DeployPath 为 Tomcat 安装目录下的 webapps 目录,否则使用 Eclipse 启动 Tomcat 后,Pluto 不能加载进来。
图 9. Tomcat 服务器配置
回页首
获取 Spring 2.x
读者还可以选择从官方站点下载安装 Spring 针对 Eclipse 的 IDE 插件,以更好地支持 Spring 的开发,在本文中,该插件不是必须的。
从 http://www.springframework.org 上获取 Spring 2.x 的最新版本,笔者下载为 SpringFramework 2.5.1,建议下载 spring-framework-2.5.1-with-dependencies.zip,这样就不需要另外寻找其它所依赖 Jar 包。将压缩包解压。
回页首
Spring Portlet MVC 框架简介
这个框架是围绕着分发器 DispatcherPortlet 设计的,分发器把请求转发给处理器。和 Web 框架的 DispatcherServlet 一样,这个框架还有可配置的处理器映射和视图解析,同时也支持文件上传。
MVC 分层结构
Spring Portlet MVC 框架存在控制器(Controller)和视图(View):
1. 控制器 C
缺省的处理器是一个非常简单的 Controller 接口,它提供了两个方法来处理 Portlet 请求的两个阶段:动作请求和显示请求:
o void handleActionRequest(request,response) //动作阶段处理动作请求
o ModelAndView handleRenderRequest(request,response) //显示阶段应该处理显示请求,并返回合适的模型和视图
这个框架包含了许多相同的控制器实现层次,比如,AbstractController,SimpleFormController等。它在数据绑定、命令对象使用、 模型处理和视图解析等方面和 Servlet 框架相同。
2. 视图 V
这个框架利用了一个特殊的桥 Servlet ViewRendererServlet 来使用 Servlet 框架里的视图显示功能,这样,Portlet 请求就被转化为 Servlet 请求,Portlet 视图能够以通常的 Servlet 底层代码来显示。这意味着,在 Portlet 里仍能使用当前所有的显示方法,如 JSP、Velocity 等。
Web 作用范围的 Bean
Spring Portlet MVC 支持 Web Bean,这些 Bean 的生命周期存在于当前的 HTTP 请求或 HTTP Session(一般的和全局的)里,容器的 WebApplicationContext 提供。
相对于 Spring 1.x,Spring 2.x 新增了以下针对于 Web Bean 的作用域:
· 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,可以将抛出的异常对应到一个视图名。
回页首
创建基于 Spring 2.x 的 Portlet 应用
下面,我们开始创建一个示例程序来进行演示,该示例的主要功能是:
· 在 View 模式下显示一个表单,要求用户输入地址数据,点击提交按钮呈现新页面,该页面显示刚提交的数据内容。
· Edit 模式下显示资源不可用,提供返回 View 模式的超链接。
· Help 模式下显示资源不可用,提供返回 View 模式的超链接。
其中,后两者体现了 Spring Portlet MVC 对异常的处理能力。
为了帮助读者理解,本文提供了完整的样例代码下载,包含该部分的所有代码。
在本文中,使用 Spring 2.x 开发 Portlet 应用需要经历以下步骤:
1. 使用 Eclipse 创建 Java EE Web 项目
2. 编辑 context.xml 文件
3. 编辑 web.xml 文件
4. 编辑 portlet.xml 文件
5. 生成 Java 类、JSP 文件以及相关 Spring 配置文件
6. 部署 Portlet 应用程序
回页首
一、使用 Eclipse 创建 Java EE Web 项目
新建项目,项目类型选择Web -> Dynamic Web Project,如 图 10 所示:
图 10. 新建动态 Web 项目
接下来,设置项目属性,项目名称 springportal, 目标运行时 Apache Tomcat V6.0,保留默认设置,点击 Finish,如 图 11 所示:
图 11. 设置项目属性
生成项目结构如 图 12:
Apache Pluto 官方提供的 bundle 版本使用的 Tomcat 版本是 5.5,其目录结构和 Tomcat 6 有所差异,使用 Eclipse 开发时,IDE 不能自动将 pluto 所需的所有 Jar 文件加载到工程的 lib 里,从而使所建 Web 工程的 CLASSPATH 缺失所需类。这就是我们使用 Pluto 源码从头构建 Pluto Portlet 容器的原因。
图 12. 项目结构
从解压后的 spring 文件夹中寻找 jstl.jar、standard.jar、spring.jar、spring-webmvc.jar、spring-webmvc-portlet.jar 拷贝到 WEB-INF/lib 目录下。
回页首
二、编辑 context.xml 文件
在 META-INF 下新建 context.xml 文件,内容如下:
<Context path="springportal" docBase="springportal" crossContext="true" />
该文件为 Tomcat的 特有配置文件,根据 Pluto 的要求,该 Web 工程的上下文应该可以被其它 JavaEE 程序访问,所以 crossContext 参数设置为 true。
回页首
三、编辑 web.xml 文件
编辑 web.xml 文件,如下:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="
xmlns:web="
xsi:schemaLocation="
id="WebApp_ID" version="2.5">
<display-name>springportal</display-name>
<!-- 设定Spring的根上下文 -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/applicationContext.xml</param-value>
</context-param>
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
<!-- 设定ViewRendererServlet -->
<servlet>
<servlet-name>ViewRendererServlet</servlet-name>
<servlet-class>
org.springframework.web.servlet.ViewRendererServlet
</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>ViewRendererServlet</servlet-name>
<url-pattern>/WEB-INF/servlet/view</url-pattern>
</servlet-mapping>
<!-- 设定加载一个Portlet的Servlet, 该配置为Pluto所需-->
<servlet>
<servlet-name>SpringTestPortlet1</servlet-name>
<servlet-class>
org.apache.pluto.core.PortletServlet
</servlet-class>
<init-param>
<param-name>portlet-name</param-name>
<param-value>SpringTestPortlet1</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>SpringTestPortlet1</servlet-name>
<url-pattern>/PlutoInvoker/SpringTestPortlet1</url-pattern>
</servlet-mapping>
</web-app>
读者可自行查询 Pluto 的参考手册,但是,官方提供的文档不仅不够完善,而且存在错误的描述,希望读者在参考 Pluto 文档的时候能够多加注意。
注意代码段粗体字后面的部分,该部分配置为 Pluto 所需。通过该配置 Pluto 将每个 Portlet 映射为一个 Servlet,通过 Servlet 将 Portlet 呈现并发布出去。为了让 Pluto 管理界面查找到 Portlet,必须使 Servlet 在使用管理界面之前实例化,所以我们配置了 load-on-startup 参数。该参数仅仅是一个建议,不是必需的。如果读者通过更改 Pluto 的页面布局配置文件包含 Portlet,则不需要配置该参数。
回页首
四、编辑 portlet.xml 文件
在 WEB-INF 目录下新建 portlet.xml:
<?xml version="1.0" encoding="UTF-8"?>
<portlet-app
xmlns="
version="1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
<portlet>
<portlet-name>SpringTestPortlet1</portlet-name>
<display-name>SpringTestPortlet1</display-name>
<portlet-class>
org.springframework.web.portlet.DispatcherPortlet
</portlet-class>
<init-param>
<name>contextConfigLocation</name>
<value>/WEB-INF/springtest-portlet1.xml</value>
</init-param>
<supports>
<mime-type>text/html</mime-type>
<portlet-mode>view</portlet-mode>
<portlet-mode>edit</portlet-mode>
<portlet-mode>help</portlet-mode>
</supports>
<portlet-info>
<title>SpringTestPortlet1</title>
</portlet-info>
</portlet>
</portlet-app>
该配置文件定义了一个名为 SpringTestPortlet1 的 portlet,支持 view、edit、help 三种模式,并且 Sprin
展开阅读全文