天天看点

JAX-WS指南(翻译自apache)

1.JAX-WS以文档作为消息传递模型为中心,取代JAX-RPC编程模型定义的远程过程调用。

  JAX-WS编程标准的实现为开发WEB服务和客户端提供了如下好处:

  (1)为JAVA应用提供了更好的平台独立性:

    使用JAX-WS的API开发web服务和客户端使开发过程更简化并使java应用具有平台独立性。

    JAX-WS利用动态代理机制来提供一个可插拔的正式委托模型实现。

    而JAX-RPC要依赖于特定供应商的调用存根来生成。

4.开发jax-ws客户端

  (1)调度客户端(Dispatch Client):基于XML消息级别的服务于web service和web service client之间通信的动态客户端。

    a.支持的对象类型:javax.xml.transform.Source(可以与SOAP和HTTP进行绑定);

                     JAXB对象(只能与SOAP和HTTP进行绑定);

                     javax.xml.soap.SOAPMessage(只能与SOAP进行绑定);

                     javax.activation.DataSource(客户端可工作于多用途邮件扩展消息(MIME),只与HTTP绑定)。

     b.调用方式:使用invoke方法对requests和responses的同步调用;

                              使用invokeAsync方法和一个回调(callback)对象或者一个轮询(polling)对象对requests和responses进行异步调用;

                              使用invokeOneWay方法进行单向调用。

     c.开发要求:对Dispatch客户端API的了解;对支持的对象类型的了解;了解WSDL相关文件的信息表征知识。

     d.创建动态客户端的步骤:

                    i.确定动态客户端是以MESSAGE还是PAYLOAD模式发送数据;

                    ii.创建一个服务实例并添加至少一个端口(port),端口携带了协议绑定和服务端点地址信息;

                    iii.使用Service.Mode.PAYLOAD 模式或者 Service.Mode.MESSAGE 模式创建一个Dispatch<T>对象;

                    iiii.配置javax.xml.ws.BindingProvider的请求上下文属性,使用请求上下文指定附加属性如启用HTTP身份验证或指定端点地址;

                    iiiii.组装动态客户端的请求消息;

                    iiiiii.用调度客户端同步或异步调用服务端点;

                    iiiiiii.处理来自服务的响应消息。

  (2)动态代理客户端(Dynamic Proxy Client):JAX-WS的静态客户端编程模型。动态代理客户端根据必须提供的服务端点接口(SEI)对服务进行调用。

    a. 动态代理实例扩展了java.lang.reflect.Proxy类并利用了以JRE5的动态代理功能为基础。

          在运行时环境动态创建代表了SEI的java对象时,动态代理客户端可以提供创建动态代理实例的接口。

    b.调用方式:使用invoke方法对requests和responses的同步调用;

                              使用invokeAsync方法和一个回调(callback)对象或者一个轮询(polling)对象对requests和responses进行异步调用;

                              使用invokeOneWay方法进行单向调用。

7.异步调用JAX-WS webservice服务

  (1)使用回调(callback)异步调用模型:客户端提供了一个AsyncHandler对象来接收和处理入站响应对象。客户端回调处理程序实现了javax.xml.ws.AsynchHandler接口,

     该接口包含了在收到来自服务端的异步响应时需要执行的应用程序代码。在运行时环境收到并处理来自服务端的异步响应之后,javax.xml.ws.AsynchHandler接口中的

   handleResponse(java.xml.ws.Response)方法会被调用。响应以javax.xml.ws.Response对象的形式传递给回调处理程序。调用Response对象的get()方法可得到响应的内容。

     此外,如果收到一个错误,客户端调用中会返回一个异常。然后响应方法会根据执行器方法使用的线程模型进行调用, 这里的执行器是指用来创建动态代理或调度客户端实例的客户端的

   java.xml.ws.Service上的java.util.concurrent.Executor。该执行器用来执行任何被应用程序注册的异步回调。使用setExecutor()和getExecutor()方法来修改和检索服务配置的执行器。

  (2)使用轮询(polling)异步调用模型:使用轮询模式,客户端可以向服务端发出请求,随后收到响应对象,该响应对象能确认服务器成功对请求作出响应。当服务器响应时,实际响应可以被检索,、

     调用响应对象(Response)的get()方法可以返回响应对象的内容。客户端可以从invokeAsync方法那得到一个javax.xml.ws.Response类型的对象。该响应对象用于监视发送给服务器请求的状态,

     确定当操作完成时,检索响应的结果。

  (3)使用异步消息交换:默认情况下,异步客户端调用没有线上的消息交换模式的行为。编程模型是异步的;然而与服务器交互的请求或响应消息的交换不是异步的。

    为了使用异步消息交换,客户端请求上下文的org.apache.axis2.jaxws.use.async.mep属性必须被设置成Boolean.Ture。当这个属性可用,客户端和服务器之间的消息交换就不同于同步消息交换。

    在异步消息交换下,请求和响应消息有WS-addressing头部,这些头部提供了消息的额外路由信息。异步消息交换和同步消息交换的另一个主要区别是响应会被交付给

    一个异步侦听器,然后异步侦听器返回响应给客户端。如果想强迫客户端停止等待响应,可以通过轮询(polling)调用返回的对象调用Response.cancel()方法或者通过回调(callback)调用返回的对象调用Future.cancel()方法。

    取消的响应不影响正在处理一个请求的服务器。

  (4)异步调用web service的步骤:

    a.确定你想要实现的回调方法或客户端异步轮询方法调用Web服务。

    b.(可选)配置客户端请求上下文。添加org.apache.axis2.jaxws.use.async.mep属性到请求上下文来启用web services客户端的异步消息。

           使用该属性要求服务端点支持WS-addressing(应用程序服务器默认支持)。示例:

           Map<String, Object> rc = ((BindingProvider) port).getRequestContext();

           rc.put("org.apache.axis2.jaxws.use.async.mep", Boolean.TRUE);

    c.实现异步回调(callback)方法,执行以下步骤:

     i.在SEI或javax.xml.ws.Dispatch接口找到异步回调方法。对于SEI,方法名以Async结束,并有比javax.xml.ws.AsyncHandler类型的同步方法多的一个以上的参数。

       invokeAsync(Object, AsyncHandler)方法是在Dispatch接口使用。

     ii.(可选)向客户端应用程序添加service.setExecutor方法。添加执行器方法给了客户端对处理响应的调度方法的控制。

         你也可以使用java.current.Executors类工厂获得打包的执行器或者实现你自己的执行器类。

     iii.实现javax.xml.ws.AsynchHandler接口。该接口只有一个handleResponse(javax.xml.ws.Response)方法,该方法必须包含处理响应或者一个异常的逻辑。

         客户端在运行时收到和处理来自服务器的异步响应时,该方法会被调用。

     iiii.利用参数数据和回调处理handler调用异步回调方法。

     iiiii.当响应可用时handleResponse(Response)方法会调用作用在回调对象上。在该方法调用里面提供响应时,Response.get()方法会被调用。

    d.实现轮询(polling)的方法:

     i.在SEI或javax.xml.ws.Dispatch接口找到异步轮询方法。对于SEI,方法名以Async结束,并有一个javax.xml.ws.Response的返回类型。

       invokeAsync(Object)方法用在Dispatch接口。

     ii.利用参数数据调用异步轮询方法。

     iii.客户端接收对象类型javax.xml.ws.Response,这个对象用于监听发送到服务器请求的状态。isDone()方法表示是否调用完成。

            当isDone()方法返回true,调用get()方法可检索到响应对象。

    e. 如果客户端需要停止等待服务的响应可以使用回调方法或者轮询方法的cancel()进行取消。

            如果cancel()被调用,端点继续处理请求。然而,客户端的等待和响应处理被停止。

       -->下面的例子说明了一个有客户端异步请求方法的web services接口:

       @WebService

   public interface CreditRatingService {

          // Synchronous operation.

          Score getCreditScore(Customer     customer);

          // Asynchronous operation with polling.

          Response<Score> getCreditScoreAsync(Customer customer);

          // Asynchronous operation with callback.

          Future<?> getQuoteAsync(Customer customer,AsyncHandler<Score> handler);

   }

  -->使用回调(callback)方法需要一个回调处理器(handler)。当回调方法请求之后,回调处理器负责对响应进行处理,响应的值有可能是响应对象或者一个异常。

      Future<?>表示一个异步计算及检查异步计算是否完成的结果,调用Future.isDone()可检查请求是否完成。

          请注意Future.get()不提供一个有意义的响应,且和Response.get()方法不同。如下示例:

       CreditRatingService svc = ...;

   Future<?> invocation = svc.getCreditScoreAsync(customerTom,

          new AsyncHandler<Score>() {

                 public void handleResponse (

                        Response<Score> response)

                     {

                        score = response.get();

                        // process the request...

                     }

       }

  );

  -->下面的示例说明了一个使用异步轮询方法的客户端:

   CreditRatingService svc = ...;

   Response<Score> response = svc.getCreditScoreAsync(customerTom);

   while (!response.isDone()) {

          // Do something while we wait.

   }

   score = response.get();

8.在JAX-WS web服务中使用处理程序(handlers):

  (1)相对于基于xml的RPC的Java API(jax-rpc)编程模型,jax-ws的编程模型提供了一个应用程序处理器工具,可以使你操作处理出入站消息流。

    你可以添加处理程序到你的JAX-WS运行时环境中去对请求和响应消息做附加的处理。您可以使用各种各样的处理程序达到捕获和打印日志信息和添加信息安全或其他信息等目的。

    因为支持除SOAP之外多个附加协议,JAX-WS提供了两种不同分类的处理程序(handlers)。

    a.一种类型的处理程序是一个协议独立的并可获得流消息作为可扩展标记语言(XML)消息的逻辑处理器(logic handler)。

           逻辑处理程序操作消息上下文属性和消息有效负载。这些处理器必须实现javax.xml.ws.handler.LogicalHandler接口。

           一个逻辑处理器接收一个LogicalMessageContext对象以获得消息信息。逻辑处理器在SOAP和基于XML/HTTP协议的应用程序中都可以配置。

    b.另一种处理程序是一个协议处理器(protocal handler)。协议处理程序操作消息上下文属性和特定于协议的消息。

           协议处理程序是有限的,它基于soap配置且必须实现javax.xml.ws.handler.soap.SOAPHandler接口。

           协议处理器接收一个javax.xml.soap.SOAPMessage来阅读消息数据。

  (2)JAX-WS运行时没有在服务器端和客户端对处理器类加以区分。当特定的处理器调用了handleMessage(MessageContext)方法或 handleFault(MessageContext)方法,

          运行时不区分入站流或出站流。你必须为服务器或客户端配置处理器,并且在这些方法里实现充分的逻辑以检测当前消息入站或出站的方向。

  (3)web services客户端应用程序使用处理器必须在服务端点接口或者生成的服务类上添加@HandlerChain注解,并提供相关的处理程序链(handler chain)配置文件。

      @HandlerChain 注释包含一个文件属性指向一个您创建的处理程序链配置文件。对于Web服务客户端应用程序,你还可以使用Binding API编程方式配置处理程序链。

          使用默认实现或一个HandlerResolver的自定义的实现,编程式的修改handlerchain 类。

  (4)web services服务器应用程序使用处理器必须在服务端点接口或者端点实现类上添加@HandlerChain注解,并提供相关的处理程序链(handler chain)配置文件。

           配置服务器的处理器只需要在服务端点实现或者实现类上添加@HandlerChain注解。处理器类必须被包含在部署工件里。

  (5)客户机和服务器为实现处理程序使用 @HandlerChain注释,必须指定一个处理程序的配置文件的位置,可能会是一个文件相对路径或绝对URL。例如:

      @HandlerChain(file="../../common/handlers/myhandlers.xml") 或 @HandlerChain(file="http://foo.com/myhandlers.xml")

  (6)创建JAX-WS处理器程序(handler):

    a.确定实现客户端或服务器处理程序。

      i.使用处理程序解析器(handler resolver)的默认实现。运行时现在使用 @HandlerChain注释和HandlerResolver类的默认实现构建处理程序链。

            你可以从Binding中获取现有的处理程序链,添加或删除处理器,然后将修改后的处理程序链返回给Binding对象。

      ii.使用处理程序解析器(handler resolver)的定制实现,需要对Service实例设置自定义HandlerResolver。在运行时使用HandlerRosolver类的自定义实现

             构建处理程序链,且不使用默认的运行时实现。在这种情况下,当在自定义的HandlerResolver实例被注册到Service实例后,从Binding中检索处理程序链时,

         @HandlerChain注解不会被读取。你可以从Binding中获取现有的处理程序链,添加或删除处理器,然后将修改后的处理程序链返回给Binding对象。

     b.配置客户端处理程序可以通过在service实例或服务端点接口(SEI)上添加@HandlerChain注解,也可以通过编程式修改处理程序链来控制运行时如何构建处理程序链。

            如果你选择以编程式修改处理程序链,那么你必须确定是否使用默认的处理程序解析器或使用已注册到service实例上的处理程序解析器的自定义实现。

            当创建binding providers时可以使用处理程序解析器。当binding providers创建好后,注册到一个service上的处理程序解析器将会被用来创建处理程序链,

            随后处理程序链将会被用于配置binding providers。

     c.配置服务器处理程序可以通过在服务端点接口或实现类上添加@HandlerChain注解。当@HandlerChain注解在服务端点接口和实现类上都配置了,那么实现类优先。

     d.创建处理程序链配置文件(xml)。你必须创建一个处理程序链配置文件供@HandlerChain参考。

     e.当配置服务器或客户端处理程序(handlers)时使用@HandlerChain注解,需要将处理程序链配置XML文件添加到服务端点接口所在的类路径下。

             你还必须在类路径下的处理程序链配置文件(XML)中包含处理程序类(handler classes)。

     f.编写处理程序实现。

  (7)@HandlerChain注解有一个file属性指向你创建的处理程序链配置文件。配置文件示例如下,protocol-bindings, port-name-pattern, and service-name-pattern元素

        都是限制哪些services能够使用这些处理程序的过滤器。

      <?xml version="1.0" encoding="UTF-8"?>

   <jws:handler-chains xmlns:jws="http://java.sun.com/xml/ns/javaee">

   <!-- Note:  The '*" denotes a wildcard. -->

        <jws:handler-chain name="MyHandlerChain">

                <jws:protocol-bindings>##SOAP11_HTTP ##ANOTHER_BINDING</jws:protocol-bindings>

                <jws:port-name-pattern 

                 xmlns:ns1="http://handlersample.samples.apache.org/">ns1:MySampl*</jws:port-name-pattern>

           <jws:service-name-pattern 

                 xmlns:ns1="http://handlersample.samples.apache.org/">ns1:*</jws:service-name-pattern>

                <jws:handler>

                        <jws:handler-class>org.apache.samples.handlersample.SampleLogicalHandler</jws:handler-class>

                </jws:handler>

                <jws:handler>

                        <jws:handler-class>org.apache.samples.handlersample.SampleProtocolHandler2</jws:handler-class>

                </jws:handler>

                <jws:handler>

                        <jws:handler-class>org.apache.samples.handlersample.SampleLogicalHandler</jws:handler-class>

                </jws:handler>

                <jws:handler>

                        <jws:handler-class>org.apache.samples.handlersample.SampleProtocolHandler2</jws:handler-class>

                </jws:handler>

        </jws:handler-chain>

   </jws:handler-chains>

   以下示例说明了一个处理程序的实现:

   package org.apache.samples.handlersample;

   import java.util.Set;

   import javax.xml.namespace.QName;

   import javax.xml.ws.handler.MessageContext;

   import javax.xml.ws.handler.soap.SOAPMessageContext;

   public class SampleProtocolHandler implements

           javax.xml.ws.handler.soap.SOAPHandler<SOAPMessageContext> {

       public void close(MessageContext messagecontext) {

       }

       public Set<QName> getHeaders() {

           return null;

       }

       public boolean handleFault(SOAPMessageContext messagecontext) {

           return true;

       }

       public boolean handleMessage(SOAPMessageContext messagecontext) {

           Boolean outbound = (Boolean) messagecontext.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);

           if (outbound) {

               // Include your steps for the outbound flow.

           }

           return true;

       }

   }

9.对JAX-WS应用程序启用HTTP会话管理支持

    使用HTTP会话管理以保持服务器上的用户的状态信息,同事返回极少的信息给用户以跟踪会话。

    你可以使用会话cookies或URL重写实现应用程序服务器上的HTTP会话管理。浏览器、应用程序服务器、应用之间的交互对用户和应用程序来说是透明的。

    应用程序和用户通常不知道服务器提供的会话标识符。

  (1)会话cookie

     HTTP会话使用一个cookie和JSESSIONID维持会话功能,这个cookie包含会话标识符。该cookie与对存储在服务器上会话信息的请求相关联。 

         从JAX-WS应用程序的后续请求中,会话ID会作为请求头的一部分被传送,这使得应用程序可以关联来自该用户之前的请求给定的会话ID相关的每一个请求。

     JAX-WS客户端应用程序可以从响应头中检索会话ID,然后通过在HTTP请求头中设置会话ID,以在后续请求中使用这些会话ID。

  (2)URL重写

     URL重写类似重定向的URL工作因为它在URL中存储了会话标识符。会话标识符被编码作为从网页提交的任何链接或形式的参数。

         该编码的URL用于后续的请求到同一服务器。要启用HTTP会话管理。

     a.配置服务器以启用会话跟踪。

     b.启用客户端会话管理,可通过在BindingProvider上设置JAX-WS属性javax.xml.ws.session.maintain的值为true。

      Map<String, Object> rc = ((BindingProvider) port).getRequestContext();

      ...

      ...

      rc.put(BindingProvider.SESSION_MAINTAIN_PROPERTY, Boolean.TRUE);

      ...

      ...

10.启用MTOM(Message Transmission Optimization Mechanism)消息优化传输机制

   JAX-WS支持使用SOAP消息优化传输机制即MTOM发送二进制附件数据。

继续阅读