摘 要: 介绍了JAXM结构,并利用其特点构建了不使用消息接发提供者的Web服务应用,分析了基于JAXM设计的体系结构和设计模式。
关键词: JAXM规范 SAAJ包 SOAP规范 Web服务
JAXM(Java API for XML Messaging)是基于SOAP1.1规范并带有Attachments的SOAP规范,它定义了一个能够与XML消息交换的基本框架。JAXM提供了一种能够在Java平台上通过Internet发送XML文档的标准方法,使得开发者可以使用Java平台进行XML消息收发。而大多数的Web服务都是由简单的消息交换组成,对于有些Web服务,直接在低级别的消息层编程通常是很有用的。JAXM提供了使XML数据能够在二个应用之间互操作的框架,允许在二个独立的Web服务之间完成全部XML文件的传输,而SOAP提供了在二个应用之间传输消息的底层格式。
1 JAXM相关概念
完整的JAXM API存在于javax.xml.soap和javax.xml.messaging二个包中。javax.xml.soap是用于接发SOAP消息的基本包,主要包含了发送带有附件的SOAP消息的API(SOAP with Attachments API for Java,SAAJ)。这个包包含所有发送请求-响应消息所必需的API。javax.xml.messaging包含了使用消息接发提供者必须的API,因此能够发送单向消息。现在SAAJ不再依赖于javax.xml.messaging包,可以独立使用。在JAXM1.1规范中定义的javax.xml.messaging包保持了对java.xml.soap包的依赖。
JAXM消息遵循SOAP标准,规定了消息的格式。通过JAXM API可以方便地创建遵从SOAP规范的XML消息。有二类SOAP消息,一类是带有附件的消息,另一类是没有附件的消息。SOAP消息都是通过连接进行接发的,有二种类型的连接,分别由JAXM API提供的类和接口来表示。javax.xml.soap.SOAPConnection表示了消息发送者到接收者的直接连接,这种类型的连接是点对点的,即使不在Servlet或者J2EE容器里也能使用。这种类型的消息接发又称为请求-响应消息接发。javax.xml.messaging.ProviderConnection表示了到消息接发提供者的连接,这种连接方式需要消息发送者和消息使用者通过消息提供者来交互。
2 使用JAXM建立Web服务消息接发
JAXM客户端可以使用消息接发提供者,也可以不用。没有使用消息接发提供者的应用程序被限制只能承担客户端的角色,只能发送请求-响应消息。下面介绍建立不使用消息接发提供者的Web服务消息接发,即点对点的请求-响应消息接发。
(1)获得连接。任何一个JAXM客户端需要完成的第一件事是获得连接。当前客户端使用SOAPConnection对象创建连接,使用SoapConnection对象发送的消息直接从发送者到发送者指定的URL,示例如下:
SOAPConnectionFactory scf=SOAPConnectionFactory.
newInstance( );
SOAPConnection con=scf.createConnection( );
(2)创建消息。生成消息可以使用SAAJ API提供的MessageFactory类的默认实现。
MessageFactory mf=MessageFactory.newInstance( );
SOAPMessage msg=mf.createMessage( );
由messageFactory创建的所有SOAPMessage对象都是基本SOAP消息,这意味着它们没有预定义的头部。JAXM所具有的灵活性之一就是它允许SOAP头部有特殊的用途。例如,像ebXML这样的一些协议可以建立在SOAP消息发送协议之上,以便提供附加头部的实现,这样就获得了附加的功能。
(3)向消息添加内容。可以向SOAPPart对象以及一个或多个AttachmentPart对象添加内容,也可以向消息的这二个部分都添加内容。为了向消息体添加内容,需创建一个SOAPBodyElement对象并添加一个使用SOAPElement.addTextNode方法建立的XML元素。
(4)发送消息。一旦填充了一个SOAPMessage对象,就可以发送此对象了。单独客户端使用SOAPConnection的call方法来发送消息。该方法发送完消息之后就将自己阻塞起来,直到收到响应为止。传给call方法的参数中,一个是要发送的消息,还有一个是URL对象,该对象包含了接收者端点的URL。
(5)从响应消息中检索内容。客户端使用onMessage方法检索消息内容。客户端通过消息得到envelope,再通过envelope得到body,从而访问SOAPBody对象。
3 使用JAXM构建Web服务应用
下面使用JAXM 构建对外提供话费查询的Web服务。由于客户端是Web服务的消费者,所以JAXM客户端不需要消息接发提供者,使用点对点的请求-响应消息接发即可。话费查询服务系统体系结构如图1所示。
客户端可以是一般的Java GUI程序(当然也可以是JSP、Servlet等),客户端通过SOAP消息与Servlet容器中运行的JAXM Servlet进行交互。JAXM Servlet是服务提供者,EJB容器里运行的是业务组件,为JAXM Servlet提供服务。
系统为客户端提供了三种查询服务:每月汇总查询、话费详单查询、即时详单查询。这三种服务分别对应服务端的三个JAXM Servlet实现:TotalMonth,每月汇总查询;DetailMonth,话费详单查询;PrestentDetail,即时详单查询。
(1)数据模型。在数据库中保存每个用户的话费信息。为了便于传输数据,减少远程调用的次数,特别设计了值对象TelExpVA来代表话费信息。值对象设计模式在J2EE模式中大量使用。JAXM Servlet和EJB组件之间传递数据就是通过对象来传递的。这个对象是包含有TelExpVA实例的java.util.Collection。但是JAXM和客户端是通过SOAP消息来传递的(也可以使用序列化的对象作为附件发送)。为了传输话费信息,还需要定义相对应的DTD或者schema。
(2)业务逻辑。业务层是EJB组件,使用了二个EJB组件,一个是TelExpServiceFacadeEJB,它是一个有状态会话Bean;另一个是TelExpEntityEJB,它是一个实体Bean,代表了持久数据。TelExpServiceFacadeEJB是会话门面,JAXM Servlet通过它来和TelExpEntityEJB交互。
(3)JAXM服务端。JAXM服务端Servlet处理消息的步骤是:获得消息(onMessage),读取消息中需要的参数,利用参数调用对应的业务处理,构建响应SOAP消息,返回处理后的消息。
在JAXM 服务端设计了三个服务JAXM Servlet,分别对应三个查询用例,其关系如图2所示。
由于使用了点对点的消息模型,服务端需要实现javax.xml.messaging.ReqRespListener接口,并且需要继承javax.xml.messaging.JAXMServlet类。onMessage方法就是当Servlet接收到SOAPMessage时激发的方法,通过此方法对外界提供服务。每个JAXM Servlet都有一个onMessage方法。
(4)客户端。最终客户端是一个叫TelExpClientGUI的图形界面程序,它并不直接与SOAP消息打交道,而是通过JAXMDelegate类与服务端JAXM Servlet进行交互。另外,还设计了一个BookBusiness接口。JAXMDelegate实现了BookBusiness接口,BookClientGUI持有BookBusiness的实例,它通过这个实例获得信息。BookBusiness返回的信息都是java.util.Collection,它是BookClientGUI和JAXMDelegate通信的桥梁。
(5)使用XML业务代表的模式。用JAXM进行Web服务开发还不普遍,相应的设计模式的探讨还较少,它的设计模式和J2EE平台其他组件的设计模式基本一致。但它有自己的特点,如客户端和服务端是通过SOAP消息进行通信,这与J2EE平台的其他组件之间的通信不同。在JAXM编程中,为了实现数据(这里是SOAP消息)的一致返回,可以使用XML业务代表的模式。用JAXM进行编程时,数据传递的特点如图3所示。
客户端最终要使用的数据是Java对象或者Java的基本数据类型,而客户端和服务端的通信是通过SOAP消息格式来传输,而在服务端要调用业务逻辑,必须使用Java对象或者是Java基本数据类型,这使数据的传输和数据的使用出现矛盾。为解决矛盾,可以使用数据转换器来转换数据,以降低层之间的耦合度,使数据易于处理。当客户端要发送数据时,使用数据转换器把请求数据转换为SOAP消息格式。当在服务端调用业务逻辑后,为使数据能在internet上传输,使用数据转换器把调用结果封装为SOAP消息。
在客户端,通过使用JAXM业务代表,可以降低最终客户和SOAP消息的耦合度。系统的结构如图4所示。
当客户端发出请求时,它调用JAXMDelegate对应的方法;JAXMDelegate根据请求构造对应的SOAP消息,然后把消息发送到服务端;服务端根据客户的请求做出对应的处理,并把处理结果返回到JAXMDelegate;JAXMDelegate使用数据转换器把返回的SOAP Message转化成Java对象(如值Bean),最后返回给客户端;客户端再把获得的数据进行处理后显示。JAXM业务代表使用数据转换器来转换数据,业务代表直接和Web服务进行交互,屏蔽了Web服务请求的复杂过程,为客户端提供易于使用的接口。
服务端的模式和客户端的模式基本一样,只是处理过程相反。服务端从客户端接收到SOAP消息后,读取参数,调用对应的业务方法,然后使用数据转换器把调用的结果转换成SOAP消息返回。
4 结束语
JAXM作为轻量级的API,抽象了底层的消息基础结构。因此,开发时利用SOAP包装的JAXM消息是容易的。需要强调的是,如果使用点对点的消息发送模型,则服务端Servlet必须实现ReqRespListener接口,onMessage( )方法将是开发服务端Servlet的重点任务。本文通过使用适当的设计模式和接口,减少了各层之间的耦合。数据转换在设计中占有很大的分量,业务代表模式在以上数据转换和业务处理中起着重要的作用。
参考文献
1 Sun Microsystems Inc.The Java Web Services Tutorial. http://java.sun.com/webservices/docs/1.0/tutorial/index.html.
2 Kao J.Developer′s Guide to Building XML-based Web Services with the Java 2 Platform,Enterprise Edition (J2EE). http://www.middleware-company.com.