在第一部分中,我们介绍了JSF portlet运行的基础知识,包括工程创建、三个基本的XML配置文件和一些通用的JSF Portlet开发人员经常遇到的问题和解答。现在,我会讲解如何通过RichFaces组件库使用AJAX来增强你的JSF portlet。
开发工具:
为了与本文保持一致,请下载最新版本的Maven(我使用2.0.9)。
安装Maven 2.0.9或更高版本
设置Maven系统环境变量
范例中使用的服务器和二进制执行文件:
JBoss Portal 2.7 Beta1
JBoss Portlet Bridge Beta3
在本文第一部分中,我曾解释过Maven archetypes的用法,以及你想要
<context-param> <param-name>org.richfaces.LoadStyleStrategy</param-name> <param-value>NONE</param-value> </context-param> <context-param> <param-name>org.richfaces.LoadScriptStrategy</param-name> <param-value>NONE</param-value> </context-param> <context-param> <param-name>org.ajax4jsf.RESOURCE_URI_PREFIX</param-name> <param-value>rfRes</param-value> </context-param> <filter> <display-name>Ajax4jsf Filter</display-name> <filter-name>ajax4jsf</filter-name> <filter-class>org.ajax4jsf.Filter</filter-class> </filter> <filter-mapping> <filter-name>ajax4jsf</filter-name> <servlet-name>FacesServlet</servlet-name> <dispatcher>FORWARD</dispatcher> <dispatcher>REQUEST</dispatcher> <dispatcher>INCLUDE</dispatcher> </filter-mapping>
搭建的工程是如何自动部署到运行着JBoss Portal的JBoss应用服务器上的。为了便于使用,第二部分的前几节与第一部分是相同的。唯一的修改是工程名字——所有的Maven命令保持不变。一旦你的RichFaces创建成功,你会获得一个实引用和测试环境来尝试下面的代码示例。
现在让我们生成RichFaces工程、检查源代码和快速学习一下配置。最后,我们将运行demo,并研究一些真实世界的开发任务。
启动一个终端并运行以下命令:
mvn archetype:generate -DarchetypeGroupId=org.jboss.portletbridge.archetypes -DarchetypeArtifactId=richfaces-basic -DarchetypeVersion=1.0.0.B3 -DgroupId=org.my.project -DartifactId=richfacesproject -DarchetypeRepository=http://repository.jboss.org/maven2/ -Dversion=1.0.0.B3
打开工程所在目录,如果你使用以上命令,目录名应该是“richfacesproject”。简单浏览一下目录的文件结构,你会看到Maven文件夹下本示例的源代码。现在你可以启动你喜欢的IDE并导入Maven工程了。
使用RichFaces库的任何组件前,必须对XML文件做一下小改动。这些设置只是对第一部分中原来的配置的一些扩展,所以我在这里只提及针对JBoss Portlet Bridge的JSF相关的配置。下面的设置请根据您个人的需要选择。为了使本文的重点集中于AJAX portlet开发,我只会简单介绍一下这些选项如何影响你的portlet。更多信息请查看RichFaces文档的相关章节。
web.xml
--------------
本文件可以控制用于显示RichFaces的脚本和CSS样式表。对于JBoss Portal,我们可以关闭样式表和脚本的加载,这样它们在portal页面头部只会加载一次:
<context-param> <param-name>org.richfaces.LoadStyleStrategy</param-name> <param-value>NONE</param-value> </context-param> <context-param> <param-name>org.richfaces.LoadScriptStrategy</param-name> <param-value>NONE</param-value> </context-param> <context-param> <param-name>org.ajax4jsf.RESOURCE_URI_PREFIX</param-name> <param-value>rfRes</param-value> </context-param> <filter> <display-name>Ajax4jsf Filter</display-name> <filter-name>ajax4jsf</filter-name> <filter-class>org.ajax4jsf.Filter</filter-class> </filter> <filter-mapping> <filter-name>ajax4jsf</filter-name> <servlet-name>FacesServlet</servlet-name> <dispatcher>FORWARD</dispatcher> <dispatcher>REQUEST</dispatcher> <dispatcher>INCLUDE</dispatcher> </filter-mapping>
jboss-portlet.xml
--------------
在这里你可以指定在portal页面头部会加载哪些内容。正如你所看到的,“rfRes”在web.xml中被设为 RESOURCE_URI_PREFIX。下一步是插入servlet_path/RESOURCE_URI_PREFIX来访问通过classpath 获取的RichFaces资源。
还需要配置三个文件以正确显示和使用RichFaces组件包:
<portlet> <portlet-name>ajaxPortlet</portlet-name> <header-content> <script src="/faces/rfRes/org/ajax4jsf/framework.pack.js" type="text/javascript"></script> <script src="/faces/rfRes/org/richfaces/ui.pack.js" type="text/javascript"></script> <link rel="stylesheet" type="text/css" href="/faces/rfRes/org/richfaces/skin.xcss"/> </header-content> </portlet>
现在我们启动服务器并通过两个简单的命令部署你的RichFaces portlet。在开始之前,我想指出在JBoss Portal安装上,本文和第一部分的区别。在上一期文章中,我们是部署到可以运行轻量级的Portlet Container 2.0示例的JBoss应用服务器上。上期文章发表以后,JBoss Portal 2.7 beta版发布。它融合了JBoss Portal旧的JSR-168实现和新的Portlet 2.0实现,使我们能够在标准的JBoss Portal工程中同时运行1.0和2.0 portlets。所以请不要对你应该使用哪个版本感到困惑。只要记住JBoss Portal 2.7包含了我们需要的一切内容,而2.6.x版本是支持JSR-168 (portlet 1.0)的稳定版本即可。
更多关于部署本demo portlet到JBoss Portal各种版本(beta或稳定版)的信息,请阅读这里。
第一步:下载并启动服务器
从 http://downloads.sourceforge.net/jboss/jboss-portal-2.7.0.B1-bundled.zip下载集成了JBoss Portal 2.7 Beta1的JBoss应用服务器。然后将下列命令中的path_to_bundle_zip以JBoss Portal 2.7的绝对路径替换并运行:
mvn install cargo:start -Plocal-portal -DJBOSS_ZIP_HOME=/path_to_bundle_zip/jboss- portal-2.7.0.B1-bundled.zip -DJBOSS_HOME_DIR=jboss-portal-2.7.0.B1- bundled/jboss-portal-2.7.0.B1
该命令有点长,不过可以让你打包任何兼容的JBoss App Server和JBoss Portal版本。
如果你看到下列输出,则可以进行下一步了:
第二步:部署demo应用
现在打开另一个终端窗口,进入“richfacesproject
”根目录,运行下列命令:
mvn cargo:deploy -Plocal-portal -DJBOSS_ZIP_HOME=/path_to_bundle_zip/jboss- portal-2.7.0.B1-bundled.zip -DJBOSS_HOME_DIR=jboss-portal-2.7.0.B1-bundled/jboss- portal-2.7.0.B1
不要忘记把“path_to_bundle_zip”替换成正确的路径。
现在你可以通过 http://localhost:8080/portal/portal/default/RichFacesEchoPortlet访问RichFaces demo portlet了。
当通过portlet进行AJAX请求时,必须明白portlet和servlet在session之间的区别。例如,当用户在portlet内部使用 AJAX请求时,这是通过原始的HTTP session实现的,请求无法访问存储在portal session中的对象。针对这个问题,我们实现了一种方法来允许我们访问Portal session属性。它们通过窗口ID来区别作用域,例如,如果Portlet在session中存储值“YourObject”,那么就可以通过 “javax.portlet.p.XYZ?YourObject”来访问,其中XYZ是窗口ID。
你可以通过以下命令从UI中获取windowID或者scopeID:
#{facesContext.externalContext.sessionMap['org.jboss.portletbridge.WINDOW_ID_RETRIVER'].windowID} #{facesContext.externalContext.sessionMap['org.jboss.portletbridge.WINDOW_ID_RETRIVER'].scopeId}
正如你看到的,facesContext.externalContext.sessionMap
指向的是portlet作用域内的session对象。为什么你会需要使用到这些值呢?下面列举到了一些你可能会遇到的情况:
整个RichFaces库都可以通过一个运行的demo看到,源代码可以在这里下载。如果你对组件配置不确定或者你认为无法在portal环境中运行,那么本工程对你非常有帮助。这个demo中唯一缺少的组件是文件上传组件。该组件计划在九月初的下一个porlet bridge版本中提供。
在论坛上发表反馈是十分有用和受欢迎的。如果想要了解JBoss Portlet Bridge项目的更多信息,请访问项目网站, 文档库或者wiki。
查看英文原文:Developing Portlets using JSF, Ajax, and Seam (Part 2 of 3)。
相关阅读:应用JSF、Ajax和Seam开发Portlets(1/3)。
志愿参与InfoQ中文站内容建设,请邮件至[email protected]。也欢迎大家到InfoQ中文站用户讨论组参与我们的线上讨论。