UML软件工程组织

当前流行的J2EE WEB应用架构分析
作者:陈亚强 出处:BLOG

J2EE体系包括java server pages(JSP) ,java SERVLET, enterprise bean,WEB service等技术。这些技术的出现给电子商务时代的WEB应用程序的开发提供了一个非常有竞争力的选择。怎样把这些技术组合起来形成一个适应项目需要的稳定架构是项目开发过程中一个非常重要的步骤。完成这个步骤可以形成一个主要里程碑基线。

 1. 架构概述

J2EE体系包括java server pages(JSP) ,java SERVLET, enterprise bean,WEB service等技术。这些技术的出现给电子商务时代的WEB应用程序的开发提供了一个非常有竞争力的选择。怎样把这些技术组合起来形成一个适应项目需要的稳定架构是项目开发过程中一个非常重要的步骤。完成这个步骤可以形成一个主要里程碑基线。形成这个基线有很多好处:

各种因数初步确定
 为了形成架构基线,架构设计师要对平台(体系)中的技术进行筛选,各种利弊的权衡。往往架构设计师在这个过程中要阅读大量的技术资料,听取项目组成员的建议,考虑领域专家的需求,考虑赞助商成本(包括开发成本和运行维护成本)限额。一旦架构设计经过评审,这些因数初步地就有了在整个项目过程中的对项目起多大作用的定位。

 定向技术培训
 一旦架构师设计的架构得到了批准形成了基线,项目开发和运行所采用的技术基本确定下来了。众多的项目经理都会对预备项目组成员的技术功底感到担心;他们需要培训部门提供培训,但就架构师面对的技术海洋,项目经理根本就提不出明确的技术培训需求。怎不能够对体系中所有技术都进行培训吧!有了架构里程碑基线,项目经理能确定这个项目开发会采用什么技术,这是提出培训需求应该是最精确的。不过在实际项目开发中,技术培训可以在基线确定之前与架构设计并发进行。

 角色分工
 有了一个好的架构蓝图,我们就能准确划分工作。如网页设计,JSP 标签处理类设计,SERVLET 设计,session bean设计,还有各种实现。这些任务在架构蓝图上都可以清晰地标出位置,使得项目组成员能很好地定位自己的任务。一个好的架构蓝图同时也能规范化任务,能很好地把任务划分为几类,在同一类中的任务的工作量和性质相同或相似。这样工作量估计起来有一个非常好的基础。

 运行维护
 前面说过各个任务在架构图上都有比较好的定位。任何人能借助它很快地熟悉整个项目的运行情况,错误出现时能比较快速地定位错误点。另外,有了清晰的架构图,项目版本管理也有很好的版本树躯干。

 扩展性
 架构犹如一颗参天大树的躯干,只要躯干根系牢,树干粗,长一些旁支,加一些树叶轻而易举无疑。同样,有一个稳定的经得起考验的架构,增加一两个业务组件是非常快速和容易的。

 大家都知道这些好处,一心想形成一个这样的J2EE应用程序架构(就像在windows平台中的MFC)。在这个路程中经历了两个大的阶段:

1.1. 模型1

模型1其实不是一个什么稳定架构,甚至谈不上形成了架构。模型1的基础是JSP文件。它从HTTP的请求中提取参数,调用相应的业务逻辑,处理HTTP会话,最后生成HTTP文档。一系列这样的JSP文件形成一个完整的模型1应用,当然可能会有其他辅助类或文件。早期的ASP 和 PHP 技术就属于这个情况。

总的看来,这个模型的好处是简单,但是它把业务逻辑和表现混在一块,对大应用来说,这个缺点是令人容忍不了的。

1.2. 模型2

在经过一番实践,并广泛借鉴和总结经验教训之后,J2EE应用程序终于迎来了MVC(模型-视图-控制)模式。MVC模式并不是J2EE行业人士标新立异的,所以前面我谈到广发借鉴。MVC的核心就是做到三层甚至多层的松散耦合。这对基于组件的,所覆盖的技术不断膨胀的J2EE体系来说真是福音和救星。

它在浏览器(本文对客户代理都称浏览器)和JSP或SERVLET之间插入一个控制组件。这个控制组件集中了处理浏览器发过来的HTTP请求的分发逻辑,也就是说,它会根据HTTP请求的URL,输入参数,和目前应用的内部状态,把请求分发给相应的WEB 层的JSP 或SERVLET。另外它也负责选择下一个视图(在J2EE中,JSP,SERVLET会生成回给浏览器的html从而形成视图)。集中的控制组件也有利于安全验证,日志纪录,有时也封装请求数据给下面的WEB tier层。这一套逻辑的实现形成了一个像MFC的应用框架,位置如图:


 1.3. 多层应用

下图为J2EE体系中典型的多层应用模型。

Client tier客户层 一般为浏览器或其他应用。客户层普遍地支持HTTP协议,也称客户代理。
 WEB tier WEB应用层 在J2EE中,这一层由WEB 容器运行,它包括JSP, SERVLET等WEB部件。
 EJB tier 企业组件层 企业组件层由EJB容器运行,支持EJB, JMS, JTA 等服务和技术。
 EIS tier 企业信息系统层 企业信息系统包含企业内传统信息系统如财务,CRM等,特点是有数据库系统的支持。
 

 应用框架目前主要集中在WEB层,旨在规范这一层软件的开发。其实企业组件层也可以实现这个模型,但目前主要以设计模式的形式存在。而且有些框架可以扩充,有了企业组件层组件的参与,框架会显得更紧凑,更自然,效率会更高。

最后开发一个JSP来作为测试客户端,这个JSP通过JavaBean调用Web服务,如例程9所示。

例程9 测试的JSP

<%@ page contentType="text/htmlcharset=ISO-8859-1"%>
<%@ page import="com.hellking.study.webservice.tax.*,javax.naming.*"%>
<jsp:useBean id="tax" class="com.hellking.study.webservice.tax.TaxBean"/>
<%
double salary=0;
try{
salary=Double.parseDouble((String)request.getParameter("salary"));
}
catch(Exception e){}
%>
<html>
<head>
<title>通过JNDI调用Web服务。</title>
</head>
<body>
<div align="center">
<h1>Web服务----适合北京地区,2003年</h1>
<%
out.println("个人所得税是:<br>");
out.println(tax.getTax1(salary));
out.println("<br>另一种方法调用Web服务,个人所得税是:<br>");
out.println(tax.getTax2(salary));
%>
<hr>
<form action="/tax/tax">
<table border=1>
<tr bgcolor=654321>
<td >输入工资</td>
<td><input type=text name=salary></td>
</tr>
<tr><td colspan=2><input type=submit value=查看></td>
</tr>
</table>
</form>
</div>
<hr>
</body>
</html>

最后来看具体的部署描述符。

在客户端的描述中引用Web服务

打开J2EESDK部署工具(执行%J2EESDK_HOME%\\AppServer\\bin\\deploytool.bat或者$J2EESDK/AppServer/bin/deploytool.sh),新建一个Web应用,把上面的测试JSP添加进来。在部署时,Web应用将包含如图1所示的文件。

 
 点击这个Web应用,在右边再点击【Web services Refs】选项卡,再点击【Add】按钮。现在可以增加Web服务引用了。增加一个名称为service/tax的Web服务引用,如图2所示。


 注意上面的Service接口是com.hellking.study.webservice.tax.MyTaxService。然后点击【Container Managed Ports】,如图3所示。


 到此,一种引用Web服务的方式就完成了。

下面看服务接口直接是Service的情况,再增加一个Web服务引用,如图4所示。
 
 注意上面Service Interface是javax.xml.rpc.Service,并且指定了名称空间(urn:Tax)和Local Part(MyTaxService)。同样,按照图3所示方法增加一个容器管理端点,端点接口名称和端口组件名称和图3一致。

经过了上面的部署,实际上在web.xml中生成了以下的部署描述符。

例程 10 生成的部署描述符

<service-ref>
<service-ref-name>service/tax</service-ref-name>
<service-interface>com.hellking.study.webservice.tax.MyTaxService</service-interface>
<wsdl-file>WEB-INF/wsdl/MyTaxService.wsdl</wsdl-file>
<jaxrpc-mapping-file>mapping.xml</jaxrpc-mapping-file>
<port-component-ref>
<service-endpoint-interface>com.hellking.study.webservice.tax.TaxService
</service-endpoint-interface>
<port-component-link>TaxServicePort</port-component-link>
</port-component-ref>
</service-ref>
<service-ref>
<service-ref-name>service/tax2</service-ref-name>
<service-interface>javax.xml.rpc.Service</service-interface>
<wsdl-file>WEB-INF/wsdl/MyTaxService.wsdl</wsdl-file>
<jaxrpc-mapping-file>mapping.xml</jaxrpc-mapping-file>
<service-qname xmlns:service-qname_ns__="urn:Tax">service-qname_ns__:MyTaxService
</service-qname>
<port-component-ref>
<service-endpoint-interface>com.hellking.study.webservice.tax.TaxService
</service-endpoint-interface>
<port-component-link>TaxServicePort</port-component-link>
</port-component-ref>
</service-ref>

下面解释一下这个描述付。对Web服务的引用通过<service-ref>元素来指定;
 <service-ref-name>就是在客户端编程中要使用的引用名字;
 <service-interface>就是服务接口,有两种,分别是javax.xml.rpc.Service和com.hellking.study.webservice.tax.MyTaxService;
 <service-qname>是服务的有效名称空间,如果直接使用com.hellking.study.webservice.tax.MyTaxService作为服务接口,就不需要指 定<service-qname>元素;
 <port-component-ref>就是对服务端点的引用,它引用的是webservices.xml中定义<port-component>元素。
 <port-component-link>用来链接到webservices.xml中指定的<port-component-name>,并且两者的名字是一致的。

· 调用测试

部署完成后,在浏览器里输入:

http://127.0.0.1:8080/tax/tax

将出现如图5所示的界面。

总结

通过上面的介绍,相信读者对Web服务的引用已经有了全面的认识。我们可以看到,通过使用JNDI,在J2EE组件中调用Web服务就像面向对象编程一样,甚至可以不理解WSDL、XML之类的概念就能调用Web服务。

参考资料

 本文的全部代码在这里 下载 。

下载J2EESDK1.4 http://java.sun.com/downloads/ 。

J2EE Home Page, http://java.sun.com/j2ee 。

J2EE 1.4 (JSR 151), http://www.jcp.org/jsr/detail/151.jsp 。

Web Services for J2EE (JSR 109), http://www.jcp.org/jsr/detail/109.jsp 。

Jwdp1.3 http://java.sun.com/webservices 。

JAX-RPC规范, http://java.sun.com/xml/downloads/jaxrpc.html 。

JNDI教学, http://java.sun.com/ 。

关于作者
 陈亚强:北京华园天一科技有限公司高级软件工程师,擅长J2EE技术,曾参与多个J2EE项目的设计和开发,对Web服务有很大的兴趣并且有一定的项目经验。热爱学习,喜欢新技术,曾参与多本图书的写作。好交朋友,您可以通过 cyqcims@mail.tsinghua.edu.cn 和他联系。

 

版权所有:UML软件工程组织