3.3.2. 开发 JAX-WS 客户端应用程序


客户端与 JAX-WS 端点通信和请求工作,该端点部署在 Java 企业版 7 容器中。有关下面提及的类、方法和其他实施详细信息,请查看 JBoss EAP 中包含的 Javadocs 捆绑包的相关部分。

概述

服务 是一种抽象,代表 WSDL 服务。WSDL 服务是相关端口的集合,各自包括绑定到特定协议的端口类型和特定的端点地址。

通常,当从现有的 WSDL 合同生成其余组件存根时,服务会生成。可以通过部署的端点的 WSDL URL 获取 WSDL 合同,也可以使用 EAP_HOME/bin/ 目录中的 wsprovide 工具从端点来源创建。

这种类型的用法被称为静态用例。在这种情况下,您要创建 Service 类的实例,它作为组件 stubs 之一创建。

您还可以使用 Service.create 方法手动创建服务。这称为动态用例。

使用
静态用例

JAX-WS 客户端的静态用例假定您已有 WSDL 合同。这可以通过外部工具生成,或者在创建 JAX-WS 端点时使用正确的 JAX-WS 注释生成。

若要生成组件存根,可使用 EAP_HOME/bin 中包含的 wsconsume 工具。工具将 WSDL URL 或文件取为参数,并生成多个文件,这些文件结构在一个目录树中。代表您的 服务的 源和类文件分别命名为 _Service.java_Service.class

所生成的实施类具有两个公共构造器,一个没有参数,另一个具有两个参数。这两个参数分别代表 WSDL 位置( java.net.URL)和服务名称( javax.xml.namespace.QName)。

no-gument 构造器是最常使用的。在这种情况下,WSDL 位置和服务名称可在 WSDL 中找到。它们从 @WebServiceClient 注释隐式设置,该注释用于解密生成的类。

@WebServiceClient(name="StockQuoteService", targetNamespace="http://example.com/stocks", wsdlLocation="http://example.com/stocks.wsdl")
public class StockQuoteService extends javax.xml.ws.Service
{
   public StockQuoteService() {
      super(new URL("http://example.com/stocks.wsdl"), new QName("http://example.com/stocks", "StockQuoteService"));
   }

   public StockQuoteService(String wsdlLocation, QName serviceName) {
      super(wsdlLocation, serviceName);
   }
   ...
}
Copy to Clipboard Toggle word wrap

有关如何从服务获取端口以及如何在该端口上调用操作的详情,请参阅 Dynamic Proxy。有关如何直接使用 XML 有效负载或使用整个 SOAP 消息的 XML 表示的详情,请参阅 Dispatch

动态用例

在动态情况下,不会自动生成 stubs。相反,Web 服务客户端使用 Service.create 方法来创建 服务 实例。以下代码片段说明了此过程。

URL wsdlLocation = new URL("http://example.org/my.wsdl");
QName serviceName = new QName("http://example.org/sample", "MyService");
Service service = Service.create(wsdlLocation, serviceName);
Copy to Clipboard Toggle word wrap
处理程序 Resolver

JAX-WS 为消息处理模块(称为处理程序)提供灵活的插件框架。这些处理程序扩展了 JAX-WS 运行时系统的功能。Service 实例通过一对 getHandler Resolver 和 setHandlerResolver 方法提供对 Handler Resolver 的访问,它们可以在每个服务、每个端口或协议绑定的基础上配置一组处理程序。

服务 实例创建代理或 Dispatch 实例时,当前注册到该服务的处理程序解析器会创建所需的处理程序链。对为 Service 实例配置的处理器解析器的后续更改不会影响之前创建的代理或 Dispatch 实例上的处理程序。

执行器

服务 实例可以使用 java.util.concurrent.Executor 配置。Executor 调用应用请求的任何异步回调。setExecutorgetExecutor 方法可以修改和检索为服务配置的 Executor

动态代理

动态代理是使用 服务 中提供的其中一个 getPort 方法 的客户端代理实例。portName 指定服务使用的 WSDL 端口的名称。serviceEndpointInterface 指定创建的动态代理实例支持的服务端点接口。

public <T> T getPort(QName portName, Class<T> serviceEndpointInterface)
public <T> T getPort(Class<T> serviceEndpointInterface)
Copy to Clipboard Toggle word wrap

服务端点接口通常使用 ws Consume 工具生成,该工具 解析 WSDL 并从中创建 Java 类。

还提供了返回端口的 typed 方法。这些方法也会返回实施 SEI 的动态代理。请参见以下示例。

@WebServiceClient(name = "TestEndpointService", targetNamespace = "http://org.jboss.ws/wsref",
   wsdlLocation = "http://localhost.localdomain:8080/jaxws-samples-webserviceref?wsdl")

public class TestEndpointService extends Service {
    ...

    public TestEndpointService(URL wsdlLocation, QName serviceName) {
        super(wsdlLocation, serviceName);
    }

    @WebEndpoint(name = "TestEndpointPort")
    public TestEndpoint getTestEndpointPort() {
        return (TestEndpoint)super.getPort(TESTENDPOINTPORT, TestEndpoint.class);
    }
}
Copy to Clipboard Toggle word wrap
@WebServiceRef

@WebServiceRef 注释声明了对 Web 服务的引用。它遵循 JSR 250 中定义的 javax.annotation.Resource 注释所显示的资源模式。与这些注解对应的 Jakarta EE 遵循 Jakarta Annotations 1.3 规范

  • 您可以使用它来定义类型为生成的 Service 类的引用。在本例中,type 和 value 元素各自引用生成的 Service 类类型。此外,如果引用类型可以通过字段或方法声明推断,则该注解将应用到,则类型和值元素可能具有 Object.class 的默认值,但不是必须的。如果无法推断类型,则至少必须使用非默认值存在 type 元素。
  • 您可以使用它来定义类型为 SEI 的引用。在这种情况下,如果可以从注解的字段或方法声明推断引用的类型,则 type 元素可能会(但不需要)使用默认值。但是,value 元素必须始终存在并引用生成的服务类类型,这是 javax.xml.ws.Service 的子类型。wsdlLocation 元素将覆盖所引用服务类的 @WebService 注释中指定的 WSDL 位置信息。

    public class EJB3Client implements EJB3Remote
    {
       @WebServiceRef
       public TestEndpointService service4;
    
       @WebServiceRef
       public TestEndpoint port3;
     }
    Copy to Clipboard Toggle word wrap
分配

XML Web 服务使用 XML 消息在端点和任何客户端之间进行通信。XML 消息使用名为 Simple Object Access Protocol(SOAP)的 XML 语言。JAX-WS API 为端点和客户端提供了机制,让它们分别能够发送和接收 SOAP 消息。marshalling 是将 Java 对象转换为 SOAP XML 消息的过程。解压是将 SOAP XML 消息转换回 Java 对象的过程。

在某些情况下,您需要访问原始 SOAP 消息本身,而不是转换的结果。Dispatch 类提供此功能。分配 以两种使用模式之一运行,由以下任一常量标识:

  • javax.xml.ws.Service.Mode.MESSAGE - 此模式指示客户端应用直接使用特定于协议的消息结构。与 SOAP 协议绑定一起使用时,客户端应用程序直接与 SOAP 消息配合工作。
  • javax.xml.ws.Service.Mode.PAYLOAD - 此模式使客户端能够处理载荷本身。例如,如果与 SOAP 协议绑定搭配使用,客户端应用程序将处理 SOAP 正文的内容,而不是整个 SOAP 消息。

分配 是一个低级别 API,要求客户端将消息或载荷构建为 XML,并严格遵守各个协议的标准以及对消息或有效载荷结构的详细了解。分配 是一个通用类,支持任何类型的消息或消息有效负载的输入和输出。

Service service = Service.create(wsdlURL, serviceName);
Dispatch dispatch = service.createDispatch(portName, StreamSource.class, Mode.PAYLOAD);

String payload = "<ns1:ping xmlns:ns1='http://oneway.samples.jaxws.ws.test.jboss.org/'/>";
dispatch.invokeOneWay(new StreamSource(new StringReader(payload)));

payload = "<ns1:feedback xmlns:ns1='http://oneway.samples.jaxws.ws.test.jboss.org/'/>";
Source retObj = (Source)dispatch.invoke(new StreamSource(new StringReader(payload)));
Copy to Clipboard Toggle word wrap
异步调用

BindingProvider 接口代表提供客户端可以使用的协议绑定的组件。它由代理实施,并由 Dispatch 接口扩展。

BindingProvider 实例可能会提供异步操作功能。异步操作调用在调用时与 BindingProvider 实例分离。操作完成后不会更新响应上下文。相反,可以使用 Response 接口提供单独的响应上下文。

public void testInvokeAsync() throws Exception {
   URL wsdlURL = new URL("http://" + getServerHost() + ":8080/jaxws-samples-asynchronous?wsdl");
   QName serviceName = new QName(targetNS, "TestEndpointService");
   Service service = Service.create(wsdlURL, serviceName);
   TestEndpoint port = service.getPort(TestEndpoint.class);
   Response response = port.echoAsync("Async");
   // access future
   String retStr = (String) response.get();
   assertEquals("Async", retStr);
}
Copy to Clipboard Toggle word wrap
@Oneway Invocations

@Oneway 注释表示给定 Web 方法采用输入消息,但不返回任何输出消息。通常,@Oneway 方法在执行业务方法之前,将控制线程返回到调用应用。

@WebService (name="PingEndpoint")
@SOAPBinding(style = SOAPBinding.Style.RPC)
public class PingEndpointImpl {
   private static String feedback;

   @WebMethod
   @Oneway
   public void ping() {
      log.info("ping");
      feedback = "ok";
   }

   @WebMethod
   public String feedback() {
      log.info("feedback");
      return feedback;
   }
}
Copy to Clipboard Toggle word wrap
超时配置

两种不同的属性控制 HTTP 连接的超时行为和等待接收消息的客户端的超时。第一个是 javax.xml.ws.client.connectionTimeout,第二个则是 javax.xml.ws.client.receiveTimeout。每个以毫秒为单位表示,正确语法如下所示:

public void testConfigureTimeout() throws Exception {
   //Set timeout until a connection is established
   ((BindingProvider)port).getRequestContext().put("javax.xml.ws.client.connectionTimeout", "6000");

   //Set timeout until the response is received
   ((BindingProvider) port).getRequestContext().put("javax.xml.ws.client.receiveTimeout", "1000");

   port.echo("testTimeout");
}
Copy to Clipboard Toggle word wrap
返回顶部
Red Hat logoGithubredditYoutubeTwitter

学习

尝试、购买和销售

社区

关于红帽文档

通过我们的产品和服务,以及可以信赖的内容,帮助红帽用户创新并实现他们的目标。 了解我们当前的更新.

让开源更具包容性

红帽致力于替换我们的代码、文档和 Web 属性中存在问题的语言。欲了解更多详情,请参阅红帽博客.

關於紅帽

我们提供强化的解决方案,使企业能够更轻松地跨平台和环境(从核心数据中心到网络边缘)工作。

Theme

© 2025 Red Hat