分享
 
 
 

使用J2EE构建服务

王朝java/jsp·作者佚名  2008-05-31
窄屏简体版  字體: |||超大  

版权声明:可以任意转载,转载时请务必以超链接形式标明文章原始出处和作者信息及本声明

英文原文地址:

http://www.onjava.com/pub/a/onjava/2005/05/25/j2ee-services.Html

中文地址:

http://www.matrix.org.cn/resource/article/43/43674_J2EE.html

关键词: J2EE Service

如今,web services 是一门流行的实现面向服务应用的技术。J2EE已经成为一个流行的用来部署web services 应用的平台。并且,J2EE1.4制定了在Java平台上建立和部署web services应用的标准。

在我的上一篇文章中,我从一个Java开发者的角度介绍了面向服务架构。在这篇文章中,我将说明如何在实现了J2EE1.4规范的应用服务器之间,比如Oracle application Server 10g,使用J2EE1.4建立可互操作的,轻便灵活的服务。

Web Services 架构

在深入研究J2EE平台上web services的开发和部署的细节之前,让我们先简要的查看一下web service的架构。

Web services 有很多种定义,但是简而言之,web services 是能够通过网络被发布,发现和调用的独立的,自我描述的组件。如图1所示,一个web service可能会执行一个简单的功能,比如核算银行存款记录,也可能会是一个横跨多个商业过程的复杂的任务。

图1. 一个web service 是如何工作的

有两种与web services 交互的方法:RPC类型和文档类型。最初,RPC类型的web services在工业界很流行,但是最近几年它已经被文档类型的web services所超越,后者被认为是在web services中交换信息的首选方法。

RPC类型的web services提出将数据交换模拟成远程过程调用(RPC)。这在商业应用中是很常见的。对于远程调用和其返回值,让相互交换的消息都遵照一个明确定义的准则。与之相反,文档类型的web services模拟xml文档的交换,交换模式由发送和接收应用程序共同定义。文档类型的服务更能适应需要交换商业或其他类型文档的应用程序,而且不同于RPC类型的web services,发送方不需要期望或等待一个即时的响应。

大多数开发者一定会同意:web services是一种有效的实现SOA的技术,因为它提供了不同平台之间的互操作性,以及依赖于XML,SOAP和HTTP等的轻量级的技术。

平台独立性和技术实现性是web services普及的主要原因。客户端不必了解相关技术的实现,而只需简单地通过网络调用服务就可以了。例如,即使你使用Java/J2EE 技术创建了一个服务并且部署在一个J2EE服务器上,比如Oracle Application Server Container for J2EE(OC4J),客户端也可以使用微软的.NET架构创建。

既然我们已经对web services有了基本的了解,就让我们关注一下构成web service的基本元素吧。

Web Services是由什么构成的?

Web Services 定义语言(WSDL;发音为“wizdle”)文档是一个web service的核心。WSDL描述了服务,而且也是web service保证遵守的“契约”。WSDL提供了对于一个web service的完整的描述,包括端口,操作和相关的消息类型。

这里是WSDL文档的一个简单的例子,它描述了一个Hello World web service:

<definitions

name="HelloService"

targetNamespace="http://oracle.j2ee.ws/ejb/Hello"

xmlns="http://schemas.xmlsoap.org/wsdl/"

xmlns:tns="http://oracle.j2ee.ws/ejb/Hello"

xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/"

xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/"

xmlns:ns1="http://oracle.j2ee.ws/ejb/Hello/types"

xmlns:xsd="http://www.w3.org/2001/XMLSchema"

xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/">

<types>

<schema elementFormDefault="qualified"

targetNamespace="http://oracle.j2ee.ws/ejb/Hello/types"

xmlns="http://www.w3.org/2001/XMLSchema"

xmlns:soap11-enc="http://schemas.xmlsoap.org/soap/encoding/"

xmlns:tns="http://oracle.j2ee.ws/ejb/Hello/types"

xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

<complexType name="sayHello">

<message name="HelloServiceInf_sayHello">

<part name="parameters"

element="ns1:sayHelloElement"/>

</message>

<message name="HelloServiceInf_sayHelloResponse">

<part name="parameters"

element="ns1:sayHelloResponseElement"/>

</message>

<portType name="HelloServiceInf">

<Operation name="sayHello">

<input message="tns:HelloServiceInf_sayHello"/>

<output message="tns:HelloServiceInf_sayHelloResponse"/>

</operation>

</portType>

<sequence>

<element name="String_1" nillable="true" type="string"/>

</sequence>

</complexType>

<complexType name="sayHelloResponse">

<sequence>

<element name="result" nillable="true" type="string"/>

</sequence>

</complexType>

<element name="sayHelloElement" type="tns:sayHello"/>

<element name="sayHelloResponseElement"

type="tns:sayHelloResponse"/>

</schema>

</types>

<binding name="HttpSoap11Binding" type="tns:HelloServiceInf">

<soap:binding style="document"

transport="http://schemas.xmlsoap.org/soap/http"/>

<operation name="sayHello">

<soap:operation

soapAction="http://oracle.j2ee.ws/ejb/Hello:sayHello"/>

<input>

<soap:body use="literal" parts="parameters"/>

</input>

<output>

<soap:body use="literal" parts="parameters"/>

</output>

</operation>

</binding>

<service name="HelloService">

<port name="HttpSoap11" binding="tns:HttpSoap11Binding">

<soap:address location="REPLACE_WITH_ACTUAL_URL"/>

</port>

</service>

</definitions>

如果你观察这个WSDL,你会注意到它有一个对于HelloService web service的完整的描述,包括端口,操作和消息类型。WSDL是web service和它的客户之间的合约,并且它能够帮助自动生成客户代理。

Web services平台的另外两项关键技术是SOAP,被用来调用web service的协议,和UDDI,它提供了用来定位web services 的注册器。

对于这些技术的支持已经完全被集成到J2EE平台中了。让我们关注一下J2EE对于web services的支持。

使用J2EE作为Web Services的平台

J2EE 1.4为使用常规Java类或企业级Java Beans来创建和部署web services提供了一个全面的平台。以下表格给出了J2EE 1.4中包括的web service APIs的细节。

点击查看大图

定义在Java Community PRocess的JSR 101之下的JAX-RPC,提供了创建和访问web services的Java API,因此它是使用J2EE平台创建和部署web services的“心脏和灵魂”。通过向应用程序开发者隐藏XML类型和Java类型映射的复杂性,以及处理XML和SOAP消息的底层细节,它提供了一个简单的,健壮的创建web services应用的平台。为了引入一个方法调用范式,它提供了两种编程模式:服务器端模式,使用Java类或无状态EJB开发web service 端点,和客户端模式,创建作为本地对象访问web services的Java客户端。JAX-RPC 1.1要求使用SOAP 1.1,并且实现与使用其他技术创建的web services之间的互操作性,比如微软的.NET。实现了J2EE1.4规范的应用服务器,比如OC4J 10.1.3和SUN的Java System Application Sever,提供了对于JAX-RPC的支持。

JAX-RPC的叫法有点用词不当,因为它既支持RPC类型的web services,也支持文档类型的web services。

Web Services部署模型

在J2EE 1.4之前,所有J2EE商家都使用他们私有的部署模型支持web services。J2EE 1.4为Java Web Services定义了部署模型。它为J2EE平台上的web services制定了开发,部署以及服务发布和使用的标准。

在这篇文章的后续部分,我将讨论基于Java的web services的部署和使用的细节。

有了J2EE 1.4对web services的支持,让我们学习使用J2EE平台来建造web service的方法。

使用J2EE创建一个Web Service

把web service创建成一个轻便的和可互操作的分布式组件不是一项琐碎的任务。如之前讨论的,你既可以把常规Java类,也可以把无状态EJB部署成web services。常规Java类被打包在一个web模块中,而EJB web services被打包在标准的ejb-jar模块中。

在这两种部署选择中,你会使用哪一个呢?

Java 类对无状态EJB:永无止境的争论

你会选择常规Java类还是EJB作为你创建web service的技术可能是一个长期的争论。Java类比EJB更容易开发,它是纯的Java对象,并且它不具有EJB带来的“额外辎重”。但是,EJB提供了几个很好的特点,比如被声明的事务和安全性,因此它使开发者将精力集中于建立商业逻辑,而不需要担心基础服务架构。EJB 3.0大大简化了设计模型,在它的规范中,EJB看起来就像常规Java类。

打包要求

无论你决定使用常规Java类还是EJB,你都必须把一些定义文件打包到你的WAR或ejb-jar中,这样你才能将你的组件作为Java web service展示出来。下面是分别基于EJB和Java类的web service的打包结构:

基于EJB 的web service的ejb-jar:

/meta-inf/

ejb-jar.xml

webservices.xml

oracle-webservices.xml

mapping-file.xml

wsdl/ wsdl 文件

ejb classes (包括端点和bean类)

常规Java web service的web 应用(.war)

/web-inf/

web.xml

webservices.xml

oracle-webservices.xml

mapping-file.xml

wsdl/ the wsdl 文件

/classes/(包括端点和bean类)

/lib/

让我们讨论每一个部署时的定义文件和描述符:

wsdl:如前所描述。

端点接口:web service端点必须实现java.rmi.Remote接口,并且在端点接口中的每一个方法都必须抛出java.rmi.RemoteException异常。这个端点需要注册到模块(ejb-jar.xml或web.xml)的标准部署描述符中。你的部署描述符(比如,ejb-jar.xml)需要包括如下条目:

<service-endpoint>

oracle.ejb21.ws.HelloServiceInf

</service-endpoint>

如下是一个Hello World web service的端点的代码:

public interface HelloServiceInf

extends java.rmi.Remote {

java.lang.String sayHello(java.lang.String name)

throws java.rmi.RemoteException;

}

web service部署描述符:J2EE平台需要一个名叫webservices.xml的部署描述符。它指定了部署到J2EE应用服务器所需的全部web service描述符,以及它们与容器资源和服务的依赖关系。同时,它还指定了:WSDL的位置;mapping.xml,它包含了Java到WSDL的映射;和Hello World web service的服务端点接口。在Resources章节中给出了一个与示例代码打包在一起的webservices.xml的例子。

商家规范部署描述符:一些实现规范参考,比如上下文根目录和端点地址,不能在web service部署描述符中指定。取而代之,你应该在商家规范部署描述符中指定它们。例如,如果你正使用OC4J,你将需要在WAR或ejb-jar中打包一个oracle-webservices.xml文件来定义那些属性。

java-wsdl映射:这个文件定义了WSDL和Java类间的映射。映射文件没有标准的名字;web services部署描述符决定了它的名字。

在把你的组件部署为web service之前,你必须把所有的定义文件打包到WAR或ejb-jar模块中。有很多开发工具,比如Oracle JDeveloper,通过完成平凡的任务,比如生成部署描述符,映射文件等,简化了web service的开发。此外,大多数应用服务器都提供了web services装配工具,它们能够满足J2EE web service的打包要求。

除了理解组成一个web service的组件和相关的打包要求外,还有一些在你开发web service时必须解决的架构问题。

构建服务的途径

创建一个web service时的主要挑战是为服务确定合适的粒度。你可以新建一个服务,也可以展示一个由Java类或EJB创建的已经存在的组件并把它发布为一个服务。当创建服务的时候,你可以使用自顶向下方法或自底向上方法:

自底向上方法:这个方法允许把一个现有的Java类或EJB发布为web service。这是很流行的创建服务的方法,因为它使你不必重写应用程序,而是重用你现有的商业逻辑。如果你使用这种方法,你必须为你的web service实现添加一个web service端点接口,同时创建一个WSDL,它同其他部署描述符一样用来描述web service。由应用服务器提供的工具,比如Oracle Application Server的web service装配工具,通过生成WSDL,webservices.xml等描述符以及web services组件的映射文件使您的开发生活更加简单――这把开发者从手工创造那些文件的痛苦中解放了出来。

自顶向下方法:这是创建服务的“纯粹”的方法,它更适合于当你根据草稿创建服务的时候。你从使用WSDL来描述服务开始,而不是直接跳入到实现。这个方法比自底向上方法更优越,因为在开发web service的同时,由于对操作,信息和对WSDL的控制的仔细考虑,使得服务更容易使用,更可维护和更可互操作。一些J2EE厂商提供了工具使这种方法变得更容易,例如,Oracle Application Server的web services装配器能够生成接口,部署描述符以及你用来创建应用程序的类框架。

互操作问题

显然,你的web services在本质上的可互操作性是必要的。J2EE 1.4要求与Basic Profile 1.0(由Web Services:Interoperability(WS-I)机构指定)保持一致。当创建web services时,你必须在将它们部署到产品中之前测试它们的互操作性。

除了设计方法和服务互操作的需要,你可以遵循一些最优方法来使你的web service效用最大化。

最优方法

最佳实践

这里有一些开发web services的最优方法:

避免在你的应用程序中过度使用web services。检查你是否真的需要把你的应用程序发布为web service。

服务的模块性是很重要的。使用一个粗粒度的web service;例如:一个会话把你的商业逻辑封装为web service。

确定你设计了你的web service,以使它制造最少的网络通信量。

遵循WS-I基础框架。使用JAX-RPC数据类型作为调用你的web service的方法的参数,这样可以使它具有与异类web services的互操作性。如果互操作性对于你的应用程序来说很重要,那么请避免使用Collection,HashMap和List之类的数据类型作为你的web service的参数。

许多对于J2EE应用的传统最优方法也同样适用于web services。比如,避免把一个包含长时间事务的组件发布为web service。

权衡你的web service的安全需求和性能,因为安全性需要更高的开销。一个端到端安全的web service所需的性能开销是很高的。

J2EE蓝图应用软件Java Adventure Builder提供了一个很优秀的用来创建基于Java 的web services 应用的工具。

一旦一个web service完成了设计,开发和部署,那么能与之提供的服务相交互的客户端组件也会被随之创建。

调用 Web Services

一个web service的客户端可以是如下的任意一种:静态桩,动态代理或者动态调用接口(DII)。

创建一个web service客户端可能跟创建一个简单的web service一样复杂。幸运的是,J2EE 1.4为开发者简化了这一过程,你可以通过任何J2EE组件(即web客户端或EJB组件)来使用web services。

通过如下过程,你可以像使用JNDI访问其他任何资源一样来调用web service:

在你的组件的部署描述符中定义一个service-ref元素。例如,如果你从一个web模块来访问HelloWorldService web service,那么该模块的web.xml文件应该包含如下:

<service-ref>

<service-ref-name>service/HelloWorldService</service-ref-name>

<service-interface>oracle.ws.HelloWorldService</service-interface>

<wsdl-file>META-INF/HelloWorldService.wsdl</wsdl-file>

<service-qname>urn:oracle-ws</service-qname>

</service-ref>

为了使你的应用程序能够找到web service,你必须在你的商家规范部署描述符中指定web service 的位置。例如,如果你使用OC4J从你的网络模块来查询web service,你的商家规范网络描述符orion-web.xml必须包含如下内容:

<service-ref-mapping name="service/HelloWorldService">

<port-info>

<wsdl-port namespaceURI="urn: HelloWorldService"

localpart="HelloWorldServicePort"/>

<stub-property>

<name>javax.xml.rpc.service.endpoint.address</name>

<value>http://localhost:8888/hello/HelloWorldInf</value>

</stub-property>

</port-info>

</service-ref-mapping>

在你的服务器中进行部署之前,你必须把端点接口和类文件打包到你的应用程序中。你可以通过JNDI查找来使用web service:

InitialContext ctx= new InitialContext();

HelloServiceInf hs = (HelloServiceInf)

ctx.lookup("java:comp/env/service/HelloWorldService");

HelloWorld hello= hs.getHelloWorldServicePort();

String myhello = hs.sayHello("Debu Panda") ;

Java Web Services 的未来

正在形成的Web Services标准的推广

Web services平台已经成长为具有可靠性,安全性,事务性,易管理性,政策性等特性的平台。在web services领域有相当一部分已经出现或正在出现的标准。为了设计一套全新的Java API来推广那些正在形成的标准,在Java Community Process中有一些JSR正在完成中,下表列出了其中的一些JSR:

除了那些正在进化的标准,我们现在来领略一下下一代J2EE平台的主要版本对于web services的支持。

使用J2EE 5.0简化SOA的开发

使用J2EE创建面向服务的应用程序确实很困难,因此通过使用由JSR 181定义的Web Services 元数据注解,J2EE 5.0将使开发更简单。EJB 3.0和Web Services元数据具有相似的目标,就是向开发者提供亲和力。

为了在J2EE 1.4中开发一个简单的Java web service,你需要几个web service定义文件:WSDL,映射文件和几个冗长的标准以及私有的web services部署描述符。Web Services元数据规范使用一种类似于EJB 3.0的缺省配置方法来使开发更简便。Web Services元数据注解处理器(或web services 装配工具)会为你生成这些文件,因此你只需要关心类的实现。

当你使用Web Services元数据开发时,这是一个看起来如此简单的Java web service:

package oracle.jr181.demo;

import javax.jws.WebMethod;

import javax.jws.WebService;

@WebService(name = "HelloWorldService",

targetNamespace = "http://hello/targetNamespace" )

public class HelloWorldService {

@WebMethod public String sayhello(String name ) {

return "Hello” +name+ “ from jws";

}

}

正如我之前提到的,EJB 3.0使用常规Java类简化了EJB的开发。通过利用EJB 3.0和Web Services元数据,开发基于EJB的web services将会变得越来越简单。当使用EJB 3.0和web services元数据时,这是一个看起来如此简单的HelloWorld EJB web service。你不必担心创建WSDL,部署描述符等等,应用服务器会在部署过程中生成这些定义文件。

package oracle.ejb30.ws;

import javax.ejb.Remote;

import javax.jws.WebService;

@WebService

public interface HelloServiceInf extends java.rmi.Remote{

@WebMethod java.lang.String sayHello(java.lang.String name)

throws java.rmi.RemoteException;

}

如下是EJB 3.0中 HelloWorld EJB的实现类:

package oracle.ejb30.ws;

import java.rmi.RemoteException;

import javax.ejb.Stateless;

@Stateless(name="HelloServiceEJB")

public class HelloServiceBean implements HelloServiceInf {

public String sayHello(String name) {

return("Hello "+name +" from first EJB3.0 Web Service");

}

}

以上例子清楚的表明了通过使用web services元数据和EJB 3.0,服务开发正在变得越来越简单。

总结

在这篇文章中,你学习了使用J2EE平台创建web services的基础知识。现在,你可以在你最喜欢的实现了J2EE规范的应用服务中,比如Oracle Application Server 10g,Sun Java System Application Server等,开始创建和部署你的web services了。

资源

本文中使用的web service例子

“如何从一个现有的Java类开发一个Web Service”(.zip):[下载文件]

“如何从一个WSDL文档开发一个Web Service”(.zip):[下载文件]

“面向服务架构:Web Services之外” by Ted Farrell

“面向服务架构:部分1 & 2” by Samudra Gupta

“面向服务架构是什么?” by Hao He

OTN Web Services技术中心

Debu Panda是Oracle Application Server开发小组的一个主要产品经理。进入讨论组讨论。

(出处:http://www.knowsky.com)

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有