本文描述了如何使用 RAD V7 上的新特性快速开发一个典型的 J2EE 应用程序。通过本文可以了解 RAD
V7 在使用 Ajax、JSF、Web Service 等技术开发基于 J2EE 的应用所提供的各种新特性以及对开发效率的提升。
在 Java 企业开发领域,Rational Application Developer (以下简称 RAD),提供了从集成了基于
UML 的软件设计工具、Servlet、Portlet、Enterprise JavaBeans(EJB)和 Struts 等
J2EE 开发工具、调试工具,以及软件版本管理工具,使用 RAD 进行软件开发和维护,可以覆盖 J2EE 整个软件生命周期,因此
RAD 无疑是 IBM 企业开发领域的最重要的开发工具之一。最新推出的 RAD 7.0 ,以最新的 Eclipse 3.2 为核心,增加了众多重要的功能。本文讲述了如何使用
RAD 7.0 新特性,快速开发一个典型的 J2EE 应用:在该程序使用一个无状态 Session Bean 获取客户数据,并且使用
RAD 7.0 发布成 Web Service,最后由一个动态 Web 项目作为 Web Service 客户端将客户数据通过
RAD 7.0 所支持的 JSF 功能,通过 Ajax 方式将客户数据列表展示给最终用户。通过阅读本文,您可以了解 RAD V7.0
在 Web Service、App Server、JSF 以及 Ajax 方面所提供的新的特性。通过了解并将这些新特性使用到您的日常工作当中,将极大的提高开发人员在
J2EE 开发方面的效能。
近年来,在企业和 Web 开发领域,发生了影响深远的技术变革。面向服务的架构 (SOA),Web2.0 概念,Ajax,Web
Service、敏捷开发思想等方法学已经得到初步推广和应用。正是在这种背景下 RAD V7 中继续增强了对 Web Service、SOA、Portal
等技术的支持,并在 Faces 应用中增加了对 Ajax 模式的支持。相对于上一个版本,RAD 7.0 主要提供了以下新特性:
- 新的服务器工具提供了对 IBM WebSphere Application Server(WAS) V6.1 的全面集成支持。可以开发、测试、调试和发布面向
WAS V6.1 的应用程序以及对其进行概要分析。
- 增强了对不同数据库在 WAS 6.1 上生成 EJB 调用代码的能力。这些数据库包括:DB2 iSeries 版 V5R4、Informix
Dynamic Server V10.0 、Sybase Adaptive Server Enterprise V15.0
、IBM Cloudscape V10.1(又称为 Derby)
- 增强了 Faces 框架,使得现在通过 JSF 组件开发 Ajax 应用;增强了对标准 JSF 的支持,使得可以设计仅使用标准
JSF 标记和特征的页面。新的“属性”视图和“JSF 验证器”可以识别第三方 JSF 标记。这些工具会尝试在运行时呈示它们的外观。
- 提供了更加简单高效的 Web Service 创建向导,并且在向导中集成了 WSDL 验证;JAX-RPC Java 类分析器已集成到
Web Service(自底向上)向导中;可以使用向导来保护 Web Service,该向导允许您轻松启用完整性、机密性和认证。
- 支持根据 JSR 168 规范来开发、测试和调试 portlet。提供新向导来帮助开发 Portlet。
- 在 XML 工具方面:改进了可视化及详细或简化视图、支持重命名重构、搜索定义引用、新的映射基础结构。
- 在物理数据建模方面,将物理数据模型存储在数据设计项目中,通过数据图、“属性”视图和“数据项目资源管理器”进行编辑。
Customer List 模拟了一个在 J2EE 开发中最常见的业务场景:将一组数据通过远程 EJB 发布提供给外部程序访问,在客户端提供一个可分页的数据列表将数据动态的展示给最终用户。该应用程序的典型结构如下图所示:
图 1. Customer List 应用程序结构
该应用分为两个企业应用程序,从逻辑角度来看,分别属于 Web Service 客户机和服务器。在本文中,Web Service
客户机实际上运行在 J2EE Container 中。在服务端,程序使用一个无状态 Session Bean 从数据库中获取客户数据
(Table: Customers),最终将该 EJB 发布成 Web Service;在客户端,在动态 Web 项目中使用 RAD
导入服务端暴露的 Web Service 接口,并生成 Web Service 服务调用客户端存根代码,同时通过 JSF 技术将客户数据列表展示给最终用户,这里将使用
Ajax 进行页面的局部刷新,以提升客户端响应速度,又提高了客户体验。整个应用中将涉及 Web Service、JSF、Ajax
等 SOA 和 Web 2.0 中的常用技术,体现了目前最新的技术趋势。
首先,我们使用如下 DDL 在数据库中创建 Customers 表:
清单 1. Customers 表DDL语句
Create Table Customers (
CUSTOMER_ID varchar(32) primary key not null, -- 客户编码
CUSTOMER_NAME varchar(50), -- 用户名
AGE int, -- 客户年龄
ADDRESS varchar(250), -- 地址
IDENTIFY_NO varchar(23), -- 身份证号码
TELEPHONE varchar(32), -- 电话号码
MOBILE varchar(12), -- 手机号码
EMAIL varchar(120) -- 电子邮件地址
) |
为了测试程序,我们使用 Insert 语句插入若干条测试数据 (请参考本文所附代码包中的 Init.sql 文件)。
创建 EJB 项目
根据我们设计的结构,也为了简单起见,我们使用一个无状态 Session Bean 来访问数据库。然后,我们会将该 Session
Bean 发布成 Web Service。首先,我们创建一个 EJB 工程 CustomerList,在创建项目的同时 RAD
V7 支持为该 EJB 项目创建一个企业应用,每个企业应用将用于生成可部署的 EAR 发布包。并且在 RAD V7 集成测试环境中,RAD
V7 可以在测试企业应用时自动将企业应用打包成 EAR 并且部署到所支持的 J2EE 服务器中。
图 2. 新建 EJB 项目
在 RAD V7 中引入了项目构面(Project Facets)的概念。项目构面是指 J2EE 项目的特性和需求,将一个“构面”添加到一个项目中,即可使得当前工程具备某种开发能力。例如,本文中新建的
EJB 项目默认具有“Java”、“EJB 模块”功能,用于开发基于 Java 工程的 EJB 应用;由于在开发阶段已经定义好了
EJB 将要运行的服务器环境 WebSphere Application Server V6.1,因此该项目还包括了构面“WebSphere
EJB(扩展)”。每个构面具有对应的版本,由于 RAD V7 默认的 Java 语言版本为 5.0,此处我们将 Java 语言版本修改为
1.4。其实,通过 Java 项目属性中的 Java 编译器选项,也可以对 Java 版本进行修改,但显然使用项目构面对 Java
版本支持进行修改显得更加方便和自然。此外,RAD V7 内置了针对不同项目的配置,可用于各种不同的项目开发需求。
图 3. EJB 项目构面
创建无状态 Session
Bean
接下来我们来创建无状态 Session Bean: CustomerListBean。在项目资源管理器中选中 EJB 项目,在“新建”菜单中选择“创建
EJB”。在“创建企业 Bean”窗口中,选择创建“会话 Bean”,输入 Bean 名称“CustomerList”,缺省包为:com.ibm.rad7.demo.ejb,点击下一页。在“企业
Bean 详细信息”页,RAD 会自动生成一个 Session Bean,由于我们计划将该 EJB 和 Web Service
部署在同一服务器上,选择为 CustomerList 创建一个本地客户机接口。如图所示:
图 4. 无状态 Session Bean 详细信息
点击“完成”按钮后,RAD V7 将生成整个无状态 Session Bean: CustomerList 的完整框架。首先,我们建立包
com.ibm.rad7.demo.business 用于存放数据库访问相关代码,并建立一个和表 Customers 结构相映射的
POJO 类 Customer,该类也将被发布成 Web Service 用于封装业务对象:
清单 2. Customer 类
// class Customer is a POJO class that maps to database table: Customers
public class Customer {
String customerId;
String customerName;
int age;
String address;
String identifyNo;
String telephone;
String mobile;
String email;
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
// 以下 get/set 方法省略
// ……
} |
打开生成的 CustomerListLocal 接口,添加需要发布业务相关的代码。这些利用这些接口即可简历一个分页页面,通过分页的方式来浏览数据:
清单 3. CustomerListLocal 接口
/**
* Local interface for Enterprise Bean: CustomerList
*/
public interface CustomerListLocal extends javax.ejb.EJBLocalObject {
public Customer[] getCustomers() throws Exception;
public Customer[] getCustomers(int index, int length) throws Exception;
public long getCustomerCount() throws Exception;
} |
图5描述了整个 CustomerList 项目中的类结构。上述 CustomerListLocal 本地接口由 CustomerListBean
来实现,最终的实现由 com.ibm.rad7.demo.business.CustomerManager 通过 JDBC 的方式来实现,具体实现方式此处不再赘述,请参考本文附录的相应代码。
图 5. CustomerList 项目类图
(
查看大图 )
在 RAD 7 中创建
Web Service
在项目资源管理器中展开 EJB 项目 CustomerList,选择 部署描述符:CustomerList >
会话 Bean >CustomerList,然后在右键菜单中选择 Web Service > 创建 Web
Service,RAD V7 将为我们打开 Web Service 创建对话框(图 6)。RAD V7 使用了新的 Web
服务创建向导,使得我们可以以更加简单的方式来创建 Web 服务。该向导中包括以下几个部分:
- Web Service 类型:RAD V7 提供了四种不同的选项,使得我们可以用“自顶向下”和“自底向上”两种不同的风格创建
Web 服务。当使用自顶向下方法来创建 Web service 时,首先要通过创建 WSDL 文件来设计 Web service
的实现。可以使用 WSDL 编辑器来完成此任务。完成此任务之后,可以使用 Web service 向导来创建 Web service
和框架 Java 类,可以向这些 Java 类添加必需的代码。自底向上的 Web service 开发涉及到从 Java bean
或企业 bean 创建 Web service。
- 服务实现:用于指定实现 Web Service 所使用的项目或者文件。使用“自顶向下”方式时,服务实现为 WSDL 文件;采用“自底向上”方式时,服务实现为
Java Bean 或者 EJB。拖动对话框左侧的滑块,可以简单的对服务实现程度进行选择。同时,还可以根据项目要求,对系统默认的配置进行修改。
- 客户机类型:用于指定客户机实现的类型以及选项。同样的,RAD V7 提供了方便的选择滑块,以支持选择不同客户机实现级别;同时还可以修改系统默认配置。
- 其他选项:提供是否发布、监视 Web Service 等选项。
图 6. Web Service 创建对话框
值得注意的是,本文所采用的方式正是“自底向上”的创建方式,因为在最常见的企业场景中,由于企业常常拥有大量的遗留系统(Legacy
System),Web Service 通常用于企业应用的整合 (Enterprise Application Integration,
EAI),因此“自底向上”发布 Web Service 符合这一场景的需要,可以直接将一些原有系统的 Java Bean 或者
EJB 接口发布成 Web 服务。而对于遗留系统较少的企业,使用 SOA 的架构思想设计新的企业应用时,由于拥有先期规划和设计的时间,又没有整合遗留系统的压力,这时常常可以使用“自顶向下”的创建方式,首先设计
WSDL ,再将 WSDL 文件发布成 Web Service ,由 RAD V7 来创建实现 Web 服务的框架代码。
测试 Web Service
Web Service 创建完毕后,RAD V7 将生成到 CustomerListBean.wsdl,并且已经启动内置的 WebSphere
Application Server V6.1 并将 Web 服务发布到服务器,然后启动 Web 服务。在“项目资源管理器”中打开
CustomerList > ejbModule > META-INF > wsdl,选中 CustomerListBean.wsdl
在右键菜单中选择 Web Service > 使用 Web Service 资源管理器测试 ,可以打开 Web
Service 资源管理器。
在 Web Service 资源管理器左侧将列出在相应的 WAS Server 上所发布的所有 Web 服务。选择相应的服务,右侧将出现系统生成的默认调用界面。在此处可以输入参数,点击执行后,可以测试
Web 服务调用并返回结果。如图 7、图 8 所示:
图 7. Web Service 资源管理器
图 8. Web Service 调用结果
Web Service 测试完毕以后,继续为 CustomerListBean.wsdl 生成调用客户端项目 CustomerListWebClient,该项目为一个动态
Web 项目,操作步骤这里不再赘述。
处理分页
现在,整个应用结构的服务器部分到此已经构建完毕。我们已经获得了用于访问数据库的 Session Bean、以及基于 Session
Bean 接口所发布的 Web 服务,并且我们也获得了 RAD V7 基于 WSDL 文件所生成的客户端调用代码。现在要构建整个应用的最后一部分:基于
Ajax Faces 的列表页面。由于列表页面具有分页功能,这里先列出和分页相关的客户端代码:
清单 4. 页面数据源接口 PageDataSource
// 页面数据源
public interface PageDataSource {
public long getSize();
public List getData(long fromIndex, long toIndex);
} |
清单 5. 一页数据容器类 SinglePage
// 一页数据容器
public class SinglePage{
public SinglePage(List data, long pageNo, long lastPageNo,
long nextPageNo, long pageCount) {
this.data = data;
this.pageNo = pageNo;
this.lastPageNo = lastPageNo;
this.nextPageNo = nextPageNo;
this.pageCount = pageCount;
}
// 以下 get/set 方法省略
// ……
} |
清单 6. 分页类 PageMaker
// 分页工具类
public class PageMaker {
PageDataSource dataSrc;
int pageSize;
public PageMaker(PageDataSource src, int pageSize) {
this.dataSrc = src;
this.pageSize = pageSize;
}
public SinglePage getPage(long pageNo) {
// 以下代码省略
// ……
}
} |
综合清单4、清单5、清单6不难看出,由其他应用提供数据源(PageDataSource),然后由“分页类”(PageMaker)根据数据源以及每页大小将数据源拆分成一页数据(SinglePage)。从而将分页功能和具体数据的依赖性分离开,并且提供了独立的分页功能。
创建 Faces 页面
选中 Web 服务客户端工程 CustomerListWebClientEAR,在右键菜单中选择菜单 新建 > Web
页面 ,在打开的新建页面对话框中点击“选项”按钮,将打开“新建 Web 页面选项”对话框。在“JavaServer Faces”选项卡中,选中“使用
JavaServer Faces 技术”;在“标记库”选项卡中中添加当前页面所需要使用的相关标记库。如图 9 所示:
图 9. 标记库选项
其中前缀为“hx”的标记库为 IBM 所提供的增强 Faces 组件,其中就包括用于支持 Ajax 所用的 hx:ajaxRequest
组件。回到“新建 Web 页面”对话框输入页面名称 CustomerList 后点击完成即可。创建完成 CustomerList.jsp
后,RAD V7 同时为我们生成了和页面相对应的页面 Java Bean:pagecode.CustomerList,该类为一个
JSF 受管类,并且已经被配置到 faces-config.xml 当中。我们在该类中添加以下代码用于向页面提供业务数据:
清单 7. CustomerList 受管类代码
public class CustomerList extends PageCodeBase {
public SinglePage getCustomerList() throws Exception {
PageMaker pageMaker = new PageMaker(this.getDataSourceFromWS(), 20);
return pageMaker.getPage(getPageNo("PageNo"));
}
public int getPageNo(String name) {
Map params = super.getRequestParam();
String val = (String) params.get(name);
if (val == null)
val = (String) params.get("form1:" + name);
val = (val == null ? "1" : val);
int pageNo = Integer.parseInt(val);
return pageNo;
}
// 以下省略代码若干
// ……
} |
创建基于
Ajax 的客户列表
在 RAD V7 中,几乎任何面板组件的内容都支持使用 Ajax。一个面板定义的是一块 Ajax 的更新区域,在面板所包括的页面区域内,可以使用不同的
Ajax 操作和服务器进行动态数据交互,而不需要刷新整个页面。常见的面板包括了从简单的容器到特性丰富的面板,例如 <h:panelGroup>
和 <h:panelGrid> 以及菜单 (<hx:panelMenu>) 和对话框 (<hx:panelDialog>)。在这里我们使用
panelGroup 面板,可以在打开“Web 视图”的页面编辑器右侧的“选用版”中找到(如图 10 所示)。选中“面板 - 组框”,拖放到页面空白处即可建立一个页面区域。
图 10. 面板 panelGroup
选中页面上已经放置好的 panelGroup,在该组件的“属性”视图中,选择“Ajax”选项卡;选中“允许 Ajax 更新”,并且选择“提交”选项,使用
submit 方式将数据更新请求发送到服务器。
图 11. 设置 panelGroup 的 Ajax 支持
之后,我们使用“增强 Faces 组件”中的“数据表”<hx:dataTableEx> 组件来构建我们的客户列表。将“数据表”组件拖放到页面相应位置后,对其增加若干字段用于显示客户数据。“数据表”组件需要指定数据值,我们可以通过点击数据值输入框上的“浏览”按钮来打开“选择页数据对象对话框”。在该对话框中,除了
session/request/application 等级别的数据库对象可供选择外,RAD V7 还能够识别我们添加到和当前页关联的“受管类”
pagecode.CustomerList 中的代码,并且作为页面数据对象提供给我们选择(如图 12 所示)。
图 12. 选择页数据对象
在页面上,为了将参数“页码”传递到后台程序,我们在页面上增加了一个“隐藏域”组件用于承载下一页页码数据。此外在页面底部,我们增加了页码信息以及“上一页”“下一页”按钮(<hx:commandExButton>),用于提供翻页功能。在
<hx:dataTableEx> 组件属性卡上选择“行操作”,添加一个点击行时执行的操作,此时“数据表”组件会增加一个域,当点击“编辑”按钮时将显示一个编辑面板,而编辑面板中的内容可以由程序员来定制。添加完所有组件后,整个页面如图
13 所示。
图 13. 客户列表页面
(
查看大图 )
使用 Ajax 方式提交参数
最后,我们来对页面 Ajax 方式提交参数进行设置,选中“下一步”按钮,打开“快速编辑”视图;选中“使用预先定义的行为”,将操作设置为“多个操作”,将目标设置为
group1(如图 14 所示)。此时,RAD V7 将为“下一步”按钮生成相应的行为响应代码。
图 14. 定义按钮行为
我们结合一段 JavaScript 代码将参数提交给服务器,并且修改“下一步”按钮的行为代码,将属性 behaviorAction
设置为“get;stop;”,并且添加 onActionFunction 为列表中相应代码。通过上述代码,当点击“下一步”按钮时,首先会响应客户端
JavaScript 代码,将当前“页码”设置到隐藏域 form1:PageNo 当中,最后执行操作按钮定义的行为:get;stop。当执行“get”行为时,RAD
V7 所支持的客户端 Ajax 框架将 panelGroup 所包含的页面区域中的所有数据提交到服务器程序,最后进行页面的局部更新。至此,结合清单
7 所给出的服务器端“受管类”代码,该页面已经可以工作良好。
清单 8. 提交 Ajax 参数的相关代码
<script type="text/javascript">
function gotoPage(paramName, value) { // 辅助方法,用于设置当前页参数
var param = document.getElementById(paramName);
if (param != null) param.value = value;
return true;
}
</script>
<h:inputHidden id="PageNo" value="#{pc_CustomerList.customerList.nextPageNo}" />
<hx:commandExButton type="submit" value="下一页" id="button2"
styleClass="commandExButton" style="font-size: 9pt">
<hx:behavior event="onclick" behaviorAction="get;stop;" targetAction="group1"
onActionFunction=
"return gotoPage('form1:PageNo', #{pc_CustomerList.customerList.nextPageNo});">
</hx:behavior>
</hx:commandExButton> |
整个应用程序最终可以分为两个企业应用:
- CustomerListEAR:在该企业应用内部署了 EJB 模块以及用于提供 Web 服务 HTTP 路由支持的路由器模块。
- CustomerListWebClientEAR:该企业应用内部部署的是一个动态 Web 项目模块,包括一个由
RAD V7 生成的 Web 服务客户端代码以及 CustomerList 页面。
这两个企业应用可以分别部署在不同的服务器上。当该应用的目标运行时不是 WebSphere Application Server
V6.1 时,在最终的发布包中还将附带向下兼容的用于支持 Ajax 的程序库。
图 15. CustomerList 应用程序部署(测试环境)
图 16 是程序的最终运行效果。我们没有实现“编辑”功能:通过 Ajax 方式实现数据的更新。这一功能留给感兴趣的读者自行完成。
图 16. CustomerList 运行效果 (客户数据由程序随机生成)
本文中,我们完整了解了如何在 RAD V7 中创建 EJB、发布 Web Service、创建基于 Ajax 的 JSF 应用程序,并且使用这些技术从无到有完成了一个完整的
J2EE 常见应用。通过整个过程,我们也体验了 RAD V7 所增加的新特性,以及这些新特性所带来的新的客户体验和开发效能。当然由于篇幅有限,本文所展示的只是
RAD V7 开发功能提升的一小部分功能,更多的功能读者可以在日常开发过程细细体验。
描述 |
名字 |
大小 |
下载方法 |
本文用到的 J2EE
示例程序 |
rad7-j2ee-dev-sample.zip |
4766KB |
|
学习
获得产品和技术
- 下载
IBM 软件试用版,体验强大的 DB2®,Lotus®,Rational®,Tivoli®
和 WebSphere® 软件。
讨论 |