用JAXM开发Web服务.docx
- 文档编号:11975711
- 上传时间:2023-04-16
- 格式:DOCX
- 页数:33
- 大小:104.06KB
用JAXM开发Web服务.docx
《用JAXM开发Web服务.docx》由会员分享,可在线阅读,更多相关《用JAXM开发Web服务.docx(33页珍藏版)》请在冰豆网上搜索。
用JAXM开发Web服务
阅读本文前您需要以下的知识和工具:
JavaTMWebServicesDeveloperPack1.1,并且会使用初步使用;
至少会使用一种EJB容器来开发、部署EJB,并且了解怎么在客户端访问EJB组件;
一般的Java编程知识。
在J2EE平台里,要开发一个Web服务,我们通常有两种选择:
使用JAX-RPC(JavaAPIforXML-basedRPC)
使用JAXM(JavaAPIforXMLMessaging)
作为对JAXM开发技术的入门,本文先不比较它们的技术特点。
我将结合一个具体的案例来讨论JAXM的开发技术方方面面。
JAXM相关概念介绍
通常我们说的JAXMAPI,它包括两个包:
Javax.xml.soap:
它是发送SOAP消息的基本包,主要包含了发送带有附件的SOAP消息的API(SOAPwithAttachmentsAPIforJava,SAAJ)。
它是SOAP消息的基本包,它为构建SOAP包和解析SOAP包提供了重要的支持。
它包含了发送请求-响应消息相关的API。
Javax.xml.messaging:
定义了JAXM的规范,包含了发送和接收消息所需的API。
JAXM包含了以下几个概念:
消息(Message)、连接(Connection)、消息提供者(Messagingproviders)。
消息
JAXM消息遵循SOAP标准,我们可以通过JAXMAPI方便的创建SOAP消息。
有两种类型的消息,带附件的消息和不带附加的消息。
不带附件的消息结构如图1所示。
如图1所示,在SAAJAPI中,它使用SOAPMessage类来代表SOAPMessage,相应的,使用SOAPPart类来代表SOAPPart,SOAPBody类代表SOAPBody。
图1不带附件的SOAP消息
其中Header和SOAPFault是可选的,Header可以多个,Body只有一个,如果有SOAPFault,那么它一定在SOAPBody后面。
带附加的SOAP消息如图2所示。
图2带附件SOAP消息
可以看出,一个SOAP消息可以有一个或者多个附件。
SAAJAPI使用AttachmentPart类来代表SOAP消息的附件。
每个AttachmentPart有一个MIMEHeader来表示附件的类型。
连接
有两种类型的连接,它们是:
消息发送者到接收者的直接连接,javax.xml.soap.SOAPConnection表示了这种类型的连接,由于它是点对点的,所以比较容易使用,即使不在Servlet或者J2EE容器里也能使用;
到消息提供者的连接,javax.xml.messaging.ProviderConnection表示了这种连接,这种方式需要消息提供者,消息发送者和消息使用者通过消息提供者来交互。
消息提供者
消息提供者主要负责传送消息,它把消息路由到目的地,一个消息发出后,可能要经过多个消息提供者才能到达目的地。
如果使用MessageProvider,可以达到以下的目的:
除了能够发送request-response类型的消息外,还可以发送One-way(单向)消息;
(消息)客户端有时也可以作为服务端来使用。
案例介绍
在本文,我将结合一个具体的案例来介绍JAXMWeb服务的开发。
此案例具体情况如下。
某图书城决定使用Web服务来对外提供图书信息查询服务,图书城现有的系统运行在J2EE平台上,客户端通过JAXM来使用图书城提供的Web服务。
系统的体系结构如图3所示:
图3系统体系结构
客户端可以是一般的javaGUI程序(当然也可以是JSP、Servlet等)。
客户端通过SOAP消息和Servlet容器里运行的JAXMServlet进行交互,JAXMServlet是服务提供者,EJB容器里运行的是业务组件,它们为JAXMServlet提供服务。
客户端请求传递的过程如图4所示:
图4请求传递的过程
可以看出,客户端通过SOAP和JAXM服务端通信,JAXM使用EJB组件来获得业务服务。
系统为客户端提供了三种查询服务:
查询所有图书,按类别查询图书,按图书名搜索某本特定的图书。
这三种服务分别有服务端的三个JAXMServlet实现。
它们是:
ListAllBook:
查询所有的图书信息;
ListByCategory:
按类别查询图书信息;
BookDetail:
查询某个特定名称的图书信息。
客户端是用Swing编写的GUI界面,使用界面如图5所示。
图5客户端界面
客户端和服务端传输图书信息时采用例程1所示的格式。
例程1传输图书信息的格式(book.dtd)
ELEMENTbooks(book*)>
ELEMENTbook(name,publisher,price,author+,category,description)>
ELEMENTname(#PCDATA)>
ELEMENTpublisher(#PCDATA)>
ELEMENTprice(#PCDATA)>
ELEMENTauthor(#PCDATA)>
ELEMENTcategory(#PCDATA)>
ELEMENTdescription(#PCDATA)>
ATTLISTbookidCDATA#REQUIRED>
这个信息包含在SOAP消息的Body里,按照这个格式,传输的SOAP消息结构如例程2所示。
例程2传输的SOAP消息的格式(book.msg)
Envelopexmlns: soap-env="http: //schemas.xmlsoap.org/soap/envelope/"> Header/> Body> GetAllBooksxmlns: books=""> bookid="2-1234-4455-4"> name>J2EE企业应用开发 name> publisher>电子工业出版社 publisher> price>60 price> category>计算机类 category> description>非常好的介绍J2EE企业应用开发的书 description> author>陈亚强 author> author>刘晓华 author> book> GetAllBooks> Body> Envelope> 为了传输数据的便利,我把图书信息用一个专门的值对象来表示,如例程3所示。 例程3BookVO值对象 packagecom.hellking.webservice; importjava.util.Collection; publicclassBookVOimplementsjava.io.Serializable { privateStringname;//图书名字 privateStringpublisher;//图书出版社 privatefloatprice;//图书价格 privateStringisbn;//图书ISBN privateStringdescription;//图书的简介 privateStringcategory;//图书的类别 privateCollectionauthors;//图书的作者,因一本书可以有多个作者,故把它表示成Collection。 publicvoidsetName(Stringname) { this.name=name; } publicStringgetName() { returnthis.name; } …其它的getter和setter方法 可以看出,BookVO其实是和例程1中的DTD是对应的。 需要指出的是,BookVO可以使用JAXB(JavaAPIforXMLBinding)中的工具来生成。 EJB组件介绍 本案例使用了两个EJB组件,它们分别是BookEntityEJB和BookServiceFacadeEJB。 其中BookEntityEJB是实体Bean,它代表了每本书的详细信息;BookServiceFacadeEJB为有状态会话Bean,它是一个会话门面,为JAXMServlet提供业务服务。 BookServiceFacadeEJB组件的远程接口如例程4所示。 例程4BookServiceFacadeEJB组件的远程接口 packagecom.hellking.webservice.ejb; importjava.rmi.RemoteException; importjavax.ejb.*; publicinterfaceBookServiceFacadeextendsEJBObject { /** *@J2EE_METHOD--getAllBook,查找所有的书 */ publicjava.util.CollectiongetAllBook()throwsRemoteException; /** *@J2EE_METHOD--findByCategory,按类别查找 */ publicjava.util.CollectionfindByCategory(Stringcategory)throwsRemoteException; /** *@J2EE_METHOD--getBookDetail,按名字查找 */ publicjava.util.CollectiongetBookDetail(Stringname)throwsRemoteException; } 可以看出,它提供了三个业务服务,分别是getAllBook(),findByCategory(Stringcategory),getBookDetail(Stringname)。 这三个业务方法返回的都是java.util.Collection。 其实,getBookDetail(Stringname)方法返回的应该是一个值对象,但是为了方便统一处理,也通过处理让它返回java.util.Collection类型,这一点以后的代码中体现出来。 在BookEntityEJBHome接口也提供了对应的查找方法,如例程5所示。 例程5BookEntityEJB的Home接口 packagecom.hellking.webservice.ejb; importjava.rmi.RemoteException; importjavax.ejb.*; publicinterfaceBookEntityHomeextendsEJBHome { publicBookEntityfindByPrimaryKey(StringprimaryKey) throwsRemoteException,FinderException; publicBookEntitycreate(Stringisbn)throwsRemoteException,CreateException; /** *@J2EE_METHOD--getAllBook,查找所有的书 */ publicjava.util.CollectionfindAllBook() throwsRemoteException,FinderException; /** *@J2EE_METHOD--findByCategory,按类别查找 */ publicjava.util.CollectionfindByCategory(Stringcategory) throwsRemoteException,FinderException; /** *@J2EE_METHOD--getBookDetail,按名字查找 */ publicBookEntityfindByName(Stringname) throwsRemoteException,FinderException; } 开发服务端 下面开发服务端,我们前面说过,服务端共有三个JAXMServlet,它们分别提供三种不同的查询服务。 由于使用了点对点的消息模型,故服务端需要实现javax.xml.messaging.ReqRespListener接口,并且需要继承javax.xml.messaging.JAXMServlet类。 javax.xml.messaging.JAXMServlet是一个Servlet,它为开发消息服务的Servlet提供了一个框架。 需要指出的是,javax.xml.messaging.ReqRespListener接口定义了一个 publicSOAPMessageonMessage(SOAPMessagemessage) 方法,故我们开发的JAXM服务端Servlet必须实现这个方法。 onMessage方法就是当此Servlet接收到SOAPMessage时激发的方法,它通过此方法对外界提供服务(我们可以把这个方法简单的比喻成普通的HttpServlet中的doGet()、doPost()方法,HttpServlet正是通过doGet()、doPost()来为客户端提供服务)。 ListAllBook的部分代码如例程6所示。 例程6ListAllBook的部分代码 publicclassListAllBookextendsJAXMServletimplementsReqRespListener { publicvoidinit(ServletConfigservletConfig)throwsServletException { super.init(servletConfig); } publicSOAPMessageonMessage(SOAPMessagemessage) { System.out.println("fromListAllBookServlet: receiveamessage"); try { System.out.println("fromListAllBookServlet: "); message.writeTo(System.out);//在控制台打印收到的消息 //调用其它类来实现业务方法 SOAPMessagemsg=newXMLBusinessDelegate().listAllBook(); System.out.println("thisisthereply....."); msg.writeTo(System.out); msg.saveChanges();//注意,在返回消息之前要调用这个方法 returnmsg;//返回消息 } catch(Exceptionex) { ex.printStackTrace(); //处理错误…. returnnull; } } } 在这个例子里,由于接收到的消息不含任何参数,故没有对它进行处理,一般情况下,接收的消息是有参数的,并且服务端需要使用这个参数来调用业务层组件,如当用户按类别查找图书时,服务端需要获得类别的名字,例程7是按类别查找图书的服务端Servlet的部分代码,我们看服务端是怎么获得客户端的请求参数。 例程7ListByCategory的部分代码 publicSOAPMessageonMessage(SOAPMessagemessage) { try { … SOAPEnvelopeenv=message.getSOAPPart().getEnvelope(); Iteratorit=env.getBody().getChildElements( env.createName("books","GetBookByCategory","")); SOAPElementbooks=(SOAPElement)it.next(); Iteratorit2=books.getChildElements( env.createName("category","GetBookByCategory","")); Stringcategory=((SOAPElement)it2.next()).getValue(); //这里的category是从SOAP消息中读出的参数 SOAPMessagemsg=newXMLBusinessDelegate().listByCategory(category); msg.saveChanges(); returnmsg;//返回处理消息 } catch(Exceptionex) { ex.printStackTrace(); //处理错误…. returnnull;//如果出错,一般返回SOAPFault,这里简化了。 } } SAAJAPI为解析SOAP消息提供了很好的支持,注意上面的黑体子,它是读取获得查找图书类别参数category的代码,这个参数是客户端设置的,在以后我们将看到客户端怎么设置这个参数。 总结一下,JAXM服务端Servlet处理消息的步骤是: 1.获得消息(onMessage) 2.读取消息中需要的参数 3.利用参数调用对应的业务处理 4.构建响应SOAP消息 5.返回处理后的消息 从上面的例子可以看出,JAXM服务端Servlet并没有处理具体的业务,而是把业务处理交给一个叫XMLBusinessDelegate业务代表的类来处理。 我们来看一下XMLBusinessDelegate是怎么来进行业务处理的。 如例程8所示。 例程8XMLBusinessDelegate的部分代码 … publicclassXMLBusinessDelegate { InitialContextinit=null; BookServiceFacadeHomefacadeHome; OTDEngineotd;//对象到数据的转换器 publicXMLBusinessDelegate()throwsNamingException { init=this.getInitialContext(); otd=newBeanToSOAPEngine();//生成对象到数据转换器实例 } publicstaticInitialContextgetInitialContext()throwsjavax.naming.NamingException { //更据不同的EJB容器,使用不同的url和连接工厂来获得上下文,然后返回… } //业务方法,按类别查找图书 publicSOAPMessagelistByCategory(Stringcategory) { try { Objectobjref=init.lookup("ejb/bookservicefacade"); facadeHome=(BookServiceFacadeHome) javax.rmi.PortableRemoteObject.narrow(objref,BookServiceFacadeHome.class); System.out.println("calljboss======>>"); Collectionresult=facadeHome.create().findByCategory(category);//调用业务方法 System.out.println("getresult======>>"); System.out.println(result.size()); //使用BeanToSOAPEngine把调用结果转换成SOAP消息 otd.init(result,"GetAllBooks"); SOAPMessageret=otd.getResult(); returnret; } catch(Exceptione) { e.printStackTrace(); returnnull; } } … 可以看出,XMLBusinessDelegate只是调用EJB组件的业务方法,然后把构建SOAP消息的任务交给BeanToSOAPEngine,BeanToSOAPEngine是负责把包含了BookVO的Collection转换成SOAP消息的专门的类。 BeanToSOAPEngine的部分代码如例程9所示。 例程9BeanToSOAPEngine的部分代码 … publicclassBeanToSOAPEngineimplementsOTDEngine { CollectionbookVos;//要处理的信息 SOAPMessagemsg;//待返回的消息 Stringtype;//type为返回消息的名字空间,如GetBookByCategory publicBeanToSOAPEngine() { try { MessageFactorymf=MessageFactory.newInstance();//获得MessageFactory的实例 msg=mf.createMessage();//从MessageFactory建立一个空的Message } catch(Exceptionex) { ex.printStackTrace(); } } publicvoidinit() { this.bookVos=c; this.type=type; } publicSOAPMessagegetResult() { build(); returnmsg; } publicvoidbuild() { try { SOAPPartpart=msg.getSOAPPart(); SOAPEnvelopeenvelop
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- JAXM 开发 Web 服务
![提示](https://static.bdocx.com/images/bang_tan.gif)