写点什么

应用 JSF、Ajax 和 Seam 开发 Portlets(1/3)

  • 2008-11-13
  • 本文字数:4087 字

    阅读完需:约 13 分钟

如果你刚开始考虑应用 portal 解决方案,或者想了解把一个新的或现有的 JSF 应用整合进一个 portal 环境有多容易,那么本文绝对值得你仔细研读。

在过去几年中,portals 无论是在企业还是在增强的 portlet 2.0( JSR 286 )规范中都得到了长足发展。新 2.0 版本的 portlets 在聚合不同的应用,并将其呈现在同一个页面的不同窗口方面赋于开发人员很大的自由。此外,它还提供了认证功能,成熟的个性化特性和更好的处理 AJAX 的现成方法。

JSR 301 portlet 桥接规范(portlet bridge specification)的出现,使我们具备了运行 JSF 应用的标准方式,不论 portlets 版本是 1.0 还是 2.0。portlet 桥(bridge)可以支配 portal 的 Action/Render 范式适当地处理 JSF 的生命周期。本教程将主要向你展示配置与开发 JSF portlet 是多么容易的一件事情,同时还会介绍新的 JBoss Portlet Container 2.0 及其一些很酷的新特性。

本文是由三部分组成的系列文章的第一篇。该系列文章从基本的 JSF portlet 和 portal 知识一直讲到 portlet 环境中的 AJAX 和 Seam 的高级用法。

现在准备开始吧!

项目安装

开发工具:

要想成功实践文中的范例就要下载最新版本的 Maven(我用的是 2.0.9 版本)。
安装 Maven 2.0.9+
设置 Maven 二进制版本的环境变量

例子中用到的服务器和二进制版本:

JBoss Portal’s Portlet Container 2.0
JBoss Portlet Bridge Beta3

目前,JBoss Portlet Bridge 是 JSR 301 规范的唯一实现,它允许你运行 JSF、RichFaces 和 Seam 的任意组合。你项目的 Maven 配置可安排下载打包在一起的 JBoss AS 和 JBoss Portlet Container 2.0,如果你想分别下载它们,可以在此处找到这些文件。否则,就给Maven 几分钟让它去自行下载适当的文件。

注意——在当前的2.6.5.SP1 版本的JBoss Portal 中同样可以运行这个portlet ,我在本文中使用了JBoss Portlet Container 2.0,但是桥(bridge)在两者中都能工作。你可通过此处了解令其可在任意版本的JBoss Portal 中运行的配置方法。

下述 Maven 原型(Maven archetype)是创建项目的一种简易方式,可以快速建立并运行一个启始项目(或者模板项目)。一旦你运行了这些命令,就可获得实践本文示例所需的一切文件。

打开一个终端窗口并运行如下指令:

复制代码
mvn archetype:generate -DarchetypeGroupId=org.jboss.portletbridge.archetypes
-DarchetypeArtifactId=1.2-basic
-DarchetypeVersion=1.0.0.B3 -DgroupId=org.whatever.project -DartifactId=myprojectname
-DarchetypeRepository=http://repository.jboss.org/maven2/ -Dversion=1.0.0.B3

现在,找到你的新建项目所在文件目录(如果你使用的跟上面的例子一样,那么目录名就应该是 “myprojectname”),浏览其中刚刚创建的所有文件,你将会看到一个基本 Maven 文件结构,其中带有适用于本文范例的源码。现在你就可以打开最喜欢的 IDE 环境,引入这个 Maven 项目了。

Portlet 桥配置要求

从现在开始的开发过程更像是在 Servlet 世界中开发 JSF 应用,不同之处在于:处理类似单点登录这样的问题;诸如命名空间(namespacing)这样的需要 portletContext 和访问变量的问题;以及 portlet 中像“Help”和“Edit”这样的窗口模式问题。我不想在本文讲述过多 portlet 的细节,但我会提供进行基本开发的必要信息。如果你想了解更多 portlets 的信息,请参考 JSR 168 JSR 286 规范说明。

JBoss Portlet Bridge 比较酷的一点在于它不是一个 portlet,它只是 portlet 和 JSF 之间的媒介。而你的 JSF 应用则是个 portlet,不过除了 WEB-INF 目录下 3 到 4 个额外的 xml 文件和关于 bridge 的 Jar 包外,它的其余部分与你的 Servlet 版本的应用毫无二致。下面几个配置文件是主要区别:

portlet.xml

复制代码
<portlet>
...v <portlet-class>
javax.portlet.faces.GenericFacesPortlet
</portlet-class>
<init-param>
<name>javax.portlet.faces.defaultViewId.view</name>
<value>/home.xhtml</value>
</init-param>
<init-param>
<name>javax.portlet.faces.defaultViewId.edit</name>
<value>/jsf/edit.xhtml</value>
</init-param>
<init-param>
<name>javax.portlet.faces.defaultViewId.help</name>
<value>/jsf/help.xhtml</value>
</init-param>
...
</portlet>

web.xml

复制代码
<context-param>
<param-name>org.ajax4jsf.VIEW_HANDLERS</param-name>
<param-value>
org.jboss.portletbridge.application.FaceletPortletViewHandler
</param-value>
</context-param>
<context-param>
<param-name>javax.portlet.faces.renderPolicy</param-name>
<param-value>
ALWAYS_DELEGATE
</param-value>
</context-param>

faces-config.xml

复制代码
<application>
<view-handler>
org.jboss.portletbridge.application.PortletViewHandler
</view-handler>
<state-manager>org.jboss.portletbridge.application.PortletStateManager</state-manager>
</application> <application></application>

由于上述设置已经应用在你刚刚设定的 Maven 原型中,因此现在我们就可以编译项目,并在 JBoss Portal 上部署它了。

运行 demo 程序

编译新项目,并通过如下两个步骤完成部署:

步骤 1:mvn install cargo:start -Premote-portal -Dpc20

这行命令将会花上几分钟去下载打在一起的 server+portal 包,所以在进行下一步骤之前,请耐心等待直至看到如下内容:

* 注意——在 server 启动前你还会看到一个 PortletException ,这很正常,而且它也是 Portlet Container 2.0 示例 FailDuringInitPortlet 的一部分。

接下来打开另外一个终端窗口,找到 JSF portlet 项目的根目录,并运行:

步骤 2:mvn cargo:deploy -Premote-portal -Dpc20

命令行参数通知 cargo 你正在运行的 portal 版本和 JBoss+Portal 包所在位置。这个例子同样可以运行于遵从 JSR 168 的最新版本 JBoss Portal 2.6.5.SP1 中。如果想了解更多 Maven 命令及相关信息,你可以参考 JBoss Portlet Bridge 文档。要查看已部署的 JSF portlet 情况可访问如下链接: http://localhost:8080/simple-portal/demo/jsr-301.jsp

JSF Portlet 开发

现在让我们来了解将 portlet 和 JSF 联系在一起的技术。

把你的 portlet 视作一个普通的 Web 应用

当把你的应用视作 servlet 端的 Web 应用时,portlet 桥是透明的。作为 portlet 开发人员,一种很好的做法是偶尔仔细检查一下你的应用以确保正在进行的开发没有扩大的趋势,因为它将运行在一个 portal 环境中。要查看此 demo 应用,或者任何已部署的带有桥的应用,可以访问 http://localhost:8080/JSFRIPortlet/home.jsf

命名空间

在 portal 环境中桥可以处理 JSF 的命名空间组合。当你需要在 JSF/xhtml 标记中使用元素 id 时,正常情况下在显示的标记中你所看到的是类似‘form1:myBtn’的代码,而如今在桥命名空间中你所看到的将是象:
jbpns_2fdefault_2fNews_2fStories_2fStoryTemplateWindow12snpbj:_viewRoot:form1:myBtn 这样的标记。

要克服这一点,你可以在你的 Facelets 页中应用下面的表达式,来为你的 javascript 代码预先设定命名空间:
document.getElementById('#{facesContext.externalContext.response.namespace}the_rest_of_JSF_ID');

请注意,因为使用了 portletResponse,所以一旦你试图在 servlet 应用端查看这个页面的时候就会得到一个异常。为避免这种情况的发生,你需要在你的后台 Bean(backing bean)中检查响应的类型,并为 UI 分配一个新的、“安全的”命名空间变量。

preserveActionParams

当你的 web.xml 文件中 preserveActionParams 值被设置为 TRUE 时,桥必须负责维护在 portlet 动作请求期间指派的任意参数,它们被保存在“桥请求域(bridge request scope)”中。当这个属性没有出现或者值为 FALSE 时,只在 portlet 请求作用域维护动作的请求参数。

复制代码
<init-param>
<param-name>javax.portlet.faces.preserveActionParams</param-name>
<param-value>true</param-value>
<init-param>

在你的 Facelets 页面中应用类似 #{request.yourParam}这样的代码可以利用这一设置。

排除桥请求域中的属性

当你的应用在每一次请求上都要使用请求属性而你又不想在扩展的桥请求作用域中管理特殊的属性时,你就必须在你的 faces-config.xml 文件中使用如下的配置了。下面你会看到任何命名空间为 foo.bar 的属性或者是以 foo.baz(通配符)打头的属性都会被从桥请求作用域中排除,这些属性只能用在每一次请求当中:

复制代码
<application>
<application-extension>
<bridge:excluded-attributes>
<bridge:excluded-attribute>foo.bar</bridge:excluded-attribute>
<bridge:excluded-attribute>foo.baz.*</bridge:excluded-attribute>
</bridge:excluded-attributes>
</application-extension>
</application>

或者你可以使用javax.portlet.faces.annotation.ExcludeFromManagedRequestScopej 注解,对你不想包含在请求中的对象类进行注解,也可以达到同样的效果。

结束语

正如你所看到的,JSR 301 规范不仅使得把已存在的 JSF web 应用建立成 portlet 更加容易,而且还提供给开发人员一种管理和处理 JSF 和 portlets 差异的方式。不过,规范目前仍处于频繁地评审和修订阶段。写这篇文章时最新的公开版本是 Early Draft Review 3,但是在 JSR 301 专家组内部,对此修订版本又已经有很多改进了,对桥比较重大的改进是在下一个 JBoss Portlet Bridge 版本(Beta 4)中将会实现的 portlet 模式导航和状态。

如果想了解更多项目信息和桥支持的兼容版本,或者想要参与社区论坛,请访问我们的项目页面 blog

查看英文原文: Developing Portlets using JSF, Ajax, and Seam (Part 1 of 3)


志愿参与 InfoQ 中文站内容建设,请邮件至 editors@cn.infoq.com 。也欢迎大家到 InfoQ 中文站用户讨论组参与我们的线上讨论。

2008-11-13 00:482549
用户头像

发布了 127 篇内容, 共 43.2 次阅读, 收获喜欢 5 次。

关注

评论

发布
暂无评论
发现更多内容

如何使用 Apache IoTDB 中的 UDF

Apache IoTDB

UDF IoTDB

程序调试利器——GDB使用指南

京东科技开发者

c++ debug gdb 企业号 3 月 PK 榜 程序检测

Apache Flink 1.16 功能解读

Apache Flink

大数据 flink 实时计算

详解基于 Celestia、Eclipse 构建的首个Layer3 链 Nautilus Chain

股市老人

A/B实验避坑指南:为什么不建议开AABB实验

字节跳动数据平台

大数据 云服务 数据产品 AB testing实战

初识VUE响应式原理

京东科技开发者

Vue 系统架构 Proxy 企业号 3 月 PK 榜 响应系统

写入性能:TDengine 最高达到 InfluxDB 的 10.3 倍,TimeScaleDB 的 6.74 倍

TDengine

大数据 tdengine 性能测试 时序数据库 国产数据库

更人性化的无阈值监控不再为无效告警烦恼

观测云

运维 可观测性 监控告警 观测云 可观测性用观测云

敏捷开发工具leangoo时间线视图管理项目

顿顿顿

Scrum 敏捷开发 甘特图 敏捷开发管理 时间线

mac无损音乐播放器软件:Audirvana使用设置技巧

理理

Audirvana

FL Studio编曲2023最新水果中文版本功能介绍

茶色酒

FL Studio 21

详解基于 Celestia、Eclipse 构建的首个Layer3 链 Nautilus Chain

鳄鱼视界

OceanBase 第六期技术征文活动|小鱼还能“更快”吗?你来试试

OceanBase 数据库

数据库 oceanbase

Deploy Workshop|DIY部署环境,让OceanBase跑起来

OceanBase 数据库

数据库 oceanbase

「资源广场」上线|以开发者为中心,打造开放资源共享平台

Jianmu

jenkins CI/CD 镜像仓库 容器镜像 建木

走进RocketMQ(四)高性能网络通信

白裤

Java RocketMQ io RocketMQ网络通信

开源即时通讯IM框架 MobileIMSDK:快速入门

JackJiang

网络编程 即时通讯 IM

k8s 探测方法总结

Geek_f24c45

#k8s

类加载机制

Apache IoTDB

IoTDB

面对“中国式报表”需求, 瓴羊 Quick BI的电子表格优于Tableau?

夏日星河

OceanBase 4.0 解读:全链路追踪要解决什么问题?从一条慢SQL说起

OceanBase 数据库

数据库 oceanbase

详细剖析|袋鼠云数栈前端框架Antd 3.x 升级 4.x 的踩坑之路

袋鼠云数栈

前端‘’

数据基础设施 NFTScan 新增支持 Gnosis 网络

NFT Research

NFT 区块链、

Mac应用程序无法打开提示不明开发者或文件损坏的处理方法

理理

Mac软件打不开

你也能成为“黑客”高手——趣谈Linux Shell编程语言

京东科技开发者

Linux 系统架构 操作系统 开发 企业号 3 月 PK 榜

打造成熟产品矩阵,瓴羊Quick BI数据可视化获认可

小偏执o

详解基于 Celestia、Eclipse 构建的首个Layer3 链 Nautilus Chain

威廉META

云原生应用配置管理的5个最佳实践

HummerCloud

云原生

CDR2023下载安装图文教程coreldraw23

茶色酒

CorelDraw2023

应用JSF、Ajax和Seam开发Portlets(1/3)_Java_Wesley Hales_InfoQ精选文章