级别: 中级 李 凌, 软件架构师, IBM
2009 年 7 月 31 日 本文介绍了如何使用 Rational Applicational Developer (RAD) 7.5.2 的可视化编辑器开发基于 JAX-WS 2.1 Web 服务的 RCP 应用程序,从而构建面向服务架构(SOA)的展示层。本文提供了在 RCP 中调用 JAX-WS 服务的完整解决方案,包括如何使客户端通过认证、授权以及如何实现 SSL 加密通信。您将看到示例应用程序的详细内容,其中验证了本方案并阐明了关键的设计细节。
客户端技术简介
随着 IT 技术的发展,应用程序的系统架构经历了一系列重要的转变,从早期的主机模式,到 C/S 模式,再到 B/S 模式。在此过程中,客户端的表现能力也在不断地变化。
在主机模式中,客户端通常是字符终端,用户通过终端登录到主机进行操作,一般只允许技术水平较高的内部人员使用,因此不适合大型商业系统。
在 C/S 模式中,客户端一般采用 Windows 图形界面,并集成了大部分的应用逻辑,数据处理能力较强,但涉及到客户端程序更新的问题,部署与维护成本很高,不利于大规模部署。基于 C/S 模式的客户端也被成为胖客户端。
随着网络的普及,B/S 模式即基于 Web 浏览器的瘦客户端大行其道,它解决了胖客户端部署和更新困难的问题,降低了维护成本,但基于浏览器运行的特性也降低了其表现力,影响用户体验。
为了兼顾胖客户端与瘦客户端的优点,富客户端(Rich Client)应用程序应运而生,它提供了独立于系统平台的运行环境,用于支撑已编译的客户端程序,提供了丰富的用户体验,并支持 HTTP 形式的客户端程序增量更新;同时,它与后端应用服务器相连,由服务器提供数据处理能力,是一种具有良好适应性的面向服务模型。
使用 RCP 作为 SOA 展示层的优点
在 SOA 架构中,人们通常使用 Web 页面作为展示层,尤其是近年来 AJAX、Flash、Web2.0 提供的技术使得构建 RIA(Rich Internet Application)成为可能,这些框架和技术大大提升了 Web 应用程序的表现力。
尽管如此,在有些场景中,Eclipse Rich Client Platform(简称 RCP)富客户端技术依然是更好的选择。RCP 提供了一个通用的富客户端框架,允许开发人员以插件的形式扩展和构造自己的桌面应用程序,它是当前最为流行的富客户端实现形式,如图 1 所示。
图 1. RCP 作为 SOA 展示层
相对于 Web 应用而言,RCP 在以下一些方面更具有优势:
-
丰富的界面元素
RCP 界面元素基于成熟可靠的 SWT 技术,允许在多种平台上构建具有本机风格的专业外观。同时,SWT 带来的种类齐全的控件可以有效满足企业用户复杂而苛刻的展现需求,包括字体、外观样式、边距等细节。虽然 RIA 形式的 Web 应用也具有良好的界面表现力,但在复杂的企业应用领域还是力不从心。
-
快速的客户端响应
SWT 图形库直接调用操作系统的绘图接口,大幅度提高了界面元素的响应速度,能够提供流畅的用户体验。而 Web 应用的界面响应速度受到 Web 浏览器执行效率和网络状况等多种因素的影响,普遍较慢。
-
支持海量数据处理
RCP 能够支持海量的数据显示及处理,这些业务数据被缓存在客户端,利用客户机的性能分担了服务器的部分负担,有效地提高了整个系统的性能。由于 Web 应用需要借助于 Web 浏览器来显示数据,受此局限显然不适合在客户端显示或缓存大量的数据。
-
支持快捷键导航
对于一些功能众多的应用而言,用户通常要求尽可能多且方便的快捷键,以支持日常频繁的使用。RCP 的控件都支持快捷键的定义和使用。而 Web 应用的界面内容通常不支持快捷键操作。
-
支持脱机工作
由于可以缓存部分数据,RCP 并不要求持续在线,用户可以在脱机的情况下对数据进行处理,RCP 会在需要的时候与服务器进行同步,具有良好的伸缩性,是一种智能客户端。而 Web 应用通常要求浏览器持续在线操作。
此外,RCP 支持跨平台运行及 HTTP 方式下发及更新,解决了传统胖客户端程序部署和更新困难的问题。
RAD 7.5.2 集成开发环境
IBM Rational Application Developer 是开发、调试和测试 Java 应用程序的集成开发环境。在 7.5.0 版本中,它提供了 RCP 客户端调用 JAX-WS 服务所需的 IBM SDK V6.0 编译及运行时环境;提供了支持 JAX-WS 标准的 Web 服务及客户端生成向导;提供了可以运行和调试 JAX-WS 服务的 WebSphere Application Server V7.0 测试环境等新特性。
在最新的 7.5.2 版本中,更是增加了激动人心的可视化 RCP UI 编辑器 Java client application editor,它基于 JavaBeans 组件模型并支持 SWT、AWT 及 Swing 控件的可视化构建,可以所见即所得地布局、调试 RCP 界面程序,极大加速了开发进程。要使用这个工具,必须在 RAD 7.5.2 的安装过程中确保启用了该功能,如图 2 所示。如果正在使用的是 RAD 7.5.0 或 7.5.1 版本,那么需要使用 IBM Installation Manager 进行升级,并在升级过程中启用该功能。
图 2. 安装 RAD 7.5.2
开发 RCP 应用程序
首先,使用 RAD 创建一个名为 DemoRCP 的 Plug-in 工程(本文涉及的所有样例代码均可从文章末尾的下载部分获取),如图 3 所示。
图 3. 新建 RCP 项目
在接下来的选项中都保持默认值,最后点击 Finish,完成创建,如图 4 所示。
图 4. 完成创建
然后,在 DemoRCP 工程中创建一个 View Visual Class,如图 5 所示,这是一个 RCP 视图类。
图 5. 创建视图类
指定类名为 JaxwsClient,该类继承于 ViewPart 类,可以被可视化编辑,如图 6 所示
图 6. 指定视图类名
点击 Finish,RAD 自动打开可视化编辑器界面,如图 7 所示。左侧的编辑区同时显示了视图类的图形界面和代码,右侧的控件区显示了可以被拖拽到图形区的各种控件。当改动图形界面或编辑代码时,他们之间会自动同步,以保持一致性。
图 7. 可视化编辑器
使用鼠标向图形区拖拽 2 个 Label 控件,1 个 Text 和 Button 控件,如图 8 所示。
图 8. 添加控件
同时可以在各个控件的 Properties 窗口调整控件的各种属性值,如图 9 所示;调整的效果可在图形区预览。
图 9. 属性编辑器
接下来需要在 Button 控件上添加鼠标事件监听器,右键点击按钮控件,选择 Events -> Add Events,在向导中选取 mouseDown 事件,如图 10 所示,当用户点击该按钮时,mouseDown() 方法将被调用,代码如清单 1 所示。
图 10. 添加鼠标事件
清单 1. 鼠标事件监听器
public void createPartControl(Composite parent) {
button.addMouseListener(new org.eclipse.swt.events.MouseAdapter() {
public void mouseDown(org.eclipse.swt.events.MouseEvent e) {
}
});
}
|
最后,需要将开发完成的 JaxwsClient 视图类注册到 RCP 程序中。打开位于 DemoRCP 项目文件夹下的 plugin.xml 配置文件,将 Extensions 选项卡中的 View 的注册 class 改为 demorcp.JaxwsClient,如图 11 所示。
图 11. 注册视图类
在 Package Explorer 中右键点击 DemoRCP 项目,并在菜单中选择 Run as -> Eclipse Application 运行该 RCP 程序,将出现图 12 所示的窗口。这是一个简单的 RCP 客户端程序,用户可以在文本框中输入任意字符串,然后点击 Invoke 按钮调用 Web 服务,如果调用成功,结果将显示在 Result 标签栏。可以看到,RAD 可视化编辑器显示的视图效果和程序真正运行的效果一模一样。
图 12. 示例 RCP 程序运行结果
这样就完成了示例 RCP 客户端程序的 UI 框架,下一章节将介绍如何添加调用 JAX-WS Web 服务的代码。
部署示例 JAX-WS Web 服务
作为示例的服务端,本文引用了一个名为 EchoWS 的应用程序,它基于 JAX-WS 标准实现了一个简单的字符串回显服务。
首先,在 RAD 中导入这个示例程序的 EAR 文件。然后,发布到 RAD 自带的 WebSphere Application Server V7.0 测试环境中。最后,用 Web 浏览器访问下列链接(注意端口号取决于测试服务器的具体配置):
http://localhost:9083/EchoWS/EchoService
如果浏览器显示结果如图 13 所示,则说明该服务已经发布成功。
图 13. 检验服务发布
使用 Web Service Client 向导
客户端调用 JAX-WS Web 服务有 3 种方法:
-
静态客户机
这是一种使用事先生成的静态客户机代码来调用 Web 服务的方式。客户端使用类似于普通 Java 调用的方式调用 Web 服务。这种使用方式最为普遍和便捷。
-
动态代理(Dynamic Proxy)
动态代理是 JAX-WS 标准中定义的静态客户端编程模型,它通过 SEI(Service Endpoint Interface,服务端点接口)调用 Web 服务。它与静态客户机调用方式的区别在于,它不需要事先生成调用桩(Stub)代码,而是在运行时使用 JDK 5.0 中的代理功能动态生成代表目标服务的 Proxy 实例,进而调用该 Web 服务。
-
Dispatch
JAX-WS 标准还支持动态客户端编程模型,也就是 Dispatch 方式。Dispatch 客户端可以操作 XML 消息来进行 Web 服务客户端与服务端之间的通信。与前两种高层次的服务调用 API 不通,Dispatch 能够直接操作 XML 消息。Dispatch 相关接口要求使用者自己构造 XML 消息或 Payloads,这需要深入的领域知识。
本文使用静态客户机的方式,在 RCP 端调用 Web 服务。RAD 7.5.2 中的 Web Service Client 向导可以方便地从 WSDL 文件生成静态客户机。需要特别注意的是,在生成客户机代码之前要做下列准备工作:
-
复制 {RAD Installation Path}/runtimes/base_v7/runtimes/com.ibm.jaxws.thinclient_7.0.0.jar 文件到 DemoRCP 工程的 META-INF 文件夹下,这个文件实现了解析 Web 服务消息所必须的协议栈;
-
打开 plugin.xml 中的 runtime 选项卡,将上述 jar 包添加到 Classpath 下,如图 14 所示;
图 14. RCP Classpath 设置
-
打开 DemoRCP 工程的 Java Build Path,确保 JRE System Library 为 IBM JDK 6.0,如图 15 所示。
图 15. Java 构建路径设置
准备工作完成后,就可以使用 RAD 中的 Web Service Client 向导生成客户机代码了,具体步骤如下:
-
打开 File -> Other,选择 Web Service Client,点击 Next,如图 16 所示;
图 16. 选择新建 Web 服务客户端向导
-
在接下来的向导界面输入 Service definition 地址为:
http://localhost:9083/EchoWS/EchoService/EchoService.wsdl,以便直接从服务器端获取 WSDL 文件;拖动左边滑块到 Deploy client 级别;并在右边 Configuration 列表中选择 Server 类型为 WebSphere Application Server V7.0;选择 Web service runtime 为 IBM WebSphere JAX-WS;并选择目标项目为 DemoRCP 工程,如图 17 所示;
图 17. 选择服务定义
-
点击 Finish 完成客户机代码的生成。
打开 DemoRCP 工程,可以看到在 src 目录下生成了包名为 com.test 的客户机代码,并在 META-INF 文件夹下存在目标 Web 服务的 WSDL 文件,整个项目结构如图 18 所示。
图 18. 完整项目包结构
调用 JAX-WS Web 服务
要调用示例 JAX-WS Web 服务,首先创建服务代理类 EchoPortProxy 的一个实例 proxy,该实例包含了将要调用的服务的业务方法 echo()。然后,就可以使用 proxy 实例发起调用,具体实现如清单 2 所示。
清单 2. 调用 Web 服务代码
// Invoke a Web service
private String invokeEchoService(String str){
String result=null;
EchoPortProxy proxy=new EchoPortProxy();
result=proxy.echo(str);
System.out.println("invoke result: "+result);
return result;
}
|
为了在 RCP 界面发起服务调用并显示调用的结果,将上述方法添加到 RCP 视图实现类 JaxwsClient 的 mouseDown 方法中,如清单 3 所示。
清单 3. 实现鼠标事件监听方法
public void mouseDown(org.eclipse.swt.events.MouseEvent e) {
String resultStr=invokeEchoService(text.getText());
result.setText("Result: "+resultStr);
}
|
这时,运行 DemoRCP 项目,发现 RCP 界面虽然正常显示,但服务调用并没有成功。这是由于调用在 RCP 运行时中调用 JAX-WS Web 服务需要 JDK 6.0 的支持,因此,打开 Run Configurations 菜单,配置运行环境为 JavaSE-1.6,如图 19 所示。
图 19. RCP 运行时环境
再次运行该程序,发现调用成功,运行结果如图 20 所示。
图 20. 服务调用结果
实现认证和授权的安全令牌
基于 HTTP 协议的 Web 服务通常使用 HTTP Authentication 机制来对服务请求进行认证和授权。HTTP Authentication 基于现有的 Java EE 安全模型,它使得 Web 服务可以借助于 Java EE 的安全性机制构建出一套完善的认证与授权体系。本节将介绍如何在 RCP 客户端中创建包含用户名和口令的 HTTP 安全令牌,从而通过服务端的认证与授权。
首先,按照文章前面部分介绍的内容,将已经启用了 HTTP Authentication 机制的 Web 服务 Secured Echo WS 导入并发布到测试服务器。同时确保测试服务器的安全性相关设置已经开启,它包括服务器全局安全性和应用程序安全性。
然后,打开 DemoRCP 工程,找到并编辑 EchoWS.wsdl 文件,修改其中的服务调用地址为:http://localhost:9083/SecuredEchoWS/EchoService,使 RCP 客户端调用开启了安全性的 Web 服务。这时如果马上运行 RCP 程序,并调用 Web 服务,会收到以下异常,如清单 4 所示:
清单 4. 未通过授权异常
WebServicesFault:
faultCode: HTTP
faultString: ( 401 ) Unauthorized
faultActor: http://localhost:9083
|
为了通过认证和授权,需要在服务请求中添加安全令牌,在 RCP 客户端代码中添加清单 5 中的方法:
清单 5. 添加认证和授权令牌
private void setBasicAuth(Object service, String user, String pwd) {
((BindingProvider) service).getRequestContext().put(BindingProvider.
USERNAME_PROPERTY, user);
((BindingProvider) service).getRequestContext().put(BindingProvider.
PASSWORD_PROPERTY, password);
}
|
同时,在 RCP 界面中添加两个文本框,用于指定服务调用的用户名和密码。重新运行 RCP 客户端,输入正确的用户名和密码,并调用 Web 服务,可以发现调用成功,如图 21 所示。
图 21. 服务调用结果
实现 SSL 加密通信
由于 HTTP 是一种明文的文本协议,它在网络上传输时特别容易被截取并掌握传输的内容,这对于信息敏感型的 Web 服务是极其不安全的,避免这种信息泄露最普遍且有效的方法是使用 SSL(Secured Socket Layer,安全套接层)进行通信的加密。
SSL 是一种基于非对称(公钥)加解密体系的安全传输协议。它通过数字证书来交换通信双方的公钥和私钥。同时,数字证书还可以用来证明一个实体的身份。通信双方拥有了彼此的证书之后,就可以进行的通信的加解密和身份的识别。本节要介绍的是,如何在 RCP 中引用服务端的签署者证书,从而实现 RCP 客户端与 Web 服务端之间的加密通信。
在 IBM WebSphere Application Server 的安全体系中,存在两种类型的证书库文件,其中的 Key Store 文件用于存放证书及其关联的私钥集合,而另一种 Trust Store 文件用于存放 SSL 握手时所信任的证书集合。简而言之,要想在 RCP 客户端和 Web 服务端建立 SSL 加密通信,需要将服务端的证书导入到 RCP 端所使用的 Trust Store 证书库中。
获取服务端证书
获取 Web 服务端证书最简便的方法是使用 Web 浏览器直接从服务端下载证书,以 IE 为例具体步骤如下:
-
访问启用了 SSL 的 Web 服务地址 https://localhost:9446/SecuredEchoWS/EchoService,如果出现“是否接受该证书,并继续访问”之类的提示,都选择“是”并继续访问;
-
点击地址栏右侧的证书图标打开正在使用的服务端证书(IE 提示的“证书错误”可以忽略);
-
打开“查看证书”向导中的 Detail 选项卡,并选择 Copy to File 以启动导出证书向导;
-
在该向导中可以选择导出证书的格式类型,选择导出证书的格式为 DER 类型;
-
指定证书文件名称为 server,将证书导出到文件。
导入证书到 Trust Store 文件
IBM WebSphere Application Server 提供了一个证书库制作工具 IBM Key Management,可以用它创建证书库并导入导出证书文件。首先,通过下面的命令行运行这个工具:
{RAD Installation Path}/runtimes/base_v7/bin/ikeyman.bat
然后,按照下列步骤创建证书库并导入服务端证书:
-
新建一个名为 trust 的证书库,选择证书库类型为 JKS 格式,如图 22 所示;
图 22. 创建 Trust Store 文件
-
在接下来的窗口中为这个证书库设置一个访问密码,用来保护证书的私密性;
-
向该证书库添加一个签署者证书,这个证书就是刚才从服务端导出的证书,如图 23 所示;
图 23. 添加服务端证书
-
关闭 iKeyman 工具,所做的更改被自动保存。
应用 Trust Store 文件
要在 RCP 中使用 Trust Store 文件,需要设置 RCP 客户端所使用的 JVM 的系统参数 ConfigURL,用以指定 SSL 配置文件的路径;并在配置文件中定义 Trust Store 文件的路径和访问密码等信息,代码如清单 6 所示:
清单 6. 初始化 SSL
public static void initSSL(String sslCfgUrl){
// specify ssl configuration file path
// sample file content:
// com.ibm.ssl.defaultAlias=DefaultSSLSettings
// com.ibm.ssl.alias=DefaultSSLSettings
// com.ibm.ssl.trustStore=C:/trust.jks
// com.ibm.ssl.trustStorePassword=123456
System.setProperty("com.ibm.SSL.ConfigURL", sslCfgUrl);
}
|
对比测试
RAD 7.5 中提供了 TCP/IP Monitor 工具(通过 Window -> Show view -> Other 菜单打开),可以监视服务调用产生的通信数据,是开发调试 Web 服务的利器。测试发现当未使用 SSL 进行服务调用时,网络上传输的报文是明文的,TCP/IP Monitor 工具界面清楚显示了 Web 服务调用的请求和响应的报文内容,如图 24 所示。
图 24. 未使用 SSL
当 RCP 端启用 SSL,并访问 Web 服务的 HTTPS 监听端口,由于整个通信过程处于加密状态,因此 TCP/IP Monitor 只记录了请求和响应的发生时间,但未能显示请求和响应的内容,从而验证了本次通信的私密性,如图 25 所示。
图 25. 使用 SSL
总结
使用 RCP 作为 SOA 展示层具有界面元素丰富、控件允许定义快捷键且响应速度快、支持海量数据处理和脱机工作等优点,使其在企业级应用领域极具优势。本文详细介绍了使用 RAD 7.5.2 提供的可视化 UI 编辑器开发 RCP 程序的方法;并以 JAX-WS 服务为例,介绍了在 RCP 中调用 Web 服务的解决方案。读者可以以此为框架,进一步丰富它的内容,例如,在 RCP 视图中使用列表框等更复杂的控件;添加对 WS-Security 和 WS-Policy 标准的支持;在实现 SSL 证书认证等等。
参考资料 学习
获得产品和技术
讨论
关于作者  | 
|  | 李凌,IBM 中国软件开发中心软件架构师,主要负责 WebSphere 相关产品的咨询、培训和实施工作;从 2007 年以来主要从事 SOA(Governance)解决方案咨询与实施工作;在 Web 服务、信息安全和 IP Multimedia Subsystem 领域有丰富的实践经验。 |
对本文的评价
|