杰瑞科技汇

Java webservice动态调用如何实现?

Java WebService动态调用

在Java中动态调用WebService有几种常见方法,以下是几种主要的实现方式:

使用JAX-WS动态调用

1 使用Dispatch API

import javax.xml.namespace.QName;
import javax.xml.soap.MessageFactory;
import javax.xml.soap.SOAPBody;
import javax.xml.soap.SOAPEnvelope;
import javax.xml.soap.SOAPMessage;
import javax.xml.ws.Dispatch;
import javax.xml.ws.Service;
import javax.xml.ws.soap.SOAPBinding;
import java.net.URL;
public class JAXWSDynamicClient {
    public static void main(String[] args) throws Exception {
        // 1. 创建Service实例
        URL wsdlUrl = new URL("http://example.com/service?wsdl");
        QName serviceName = new QName("http://example.com/", "MyService");
        Service service = Service.create(wsdlUrl, serviceName);
        // 2. 创建Dispatch实例
        QName portName = new QName("http://example.com/", "MyPort");
        Dispatch<SOAPMessage> dispatch = service.createDispatch(portName, SOAPMessage.class, Service.Mode.MESSAGE);
        // 3. 创建SOAP请求
        MessageFactory mf = MessageFactory.newInstance();
        SOAPMessage request = mf.createMessage();
        SOAPEnvelope envelope = request.getSOAPPart().getEnvelope();
        SOAPBody body = envelope.getBody();
        // 添加请求内容
        body.addBodyElement(new QName("http://example.com/", "sayHello"))
            .addTextNode("Dynamic Client");
        // 4. 发送请求并获取响应
        SOAPMessage response = dispatch.invoke(request);
        response.writeTo(System.out);
    }
}

2 使用Provider API

import javax.xml.namespace.QName;
import javax.xml.soap.MessageFactory;
import javax.xml.soap.SOAPMessage;
import javax.xml.ws.Dispatch;
import javax.xml.ws.Service;
import javax.xml.ws.Provider;
import javax.xml.ws.Service.Mode;
import javax.xml.ws.soap.SOAPBinding;
import java.net.URL;
public class JAXWSProviderClient {
    public static void main(String[] args) throws Exception {
        URL wsdlUrl = new URL("http://example.com/service?wsdl");
        QName serviceName = new QName("http://example.com/", "MyService");
        Service service = Service.create(wsdlUrl, serviceName);
        QName portName = new QName("http://example.com/", "MyPort");
        Dispatch<SOAPMessage> dispatch = service.createDispatch(portName, SOAPMessage.class, Mode.PAYLOAD);
        // 创建请求
        MessageFactory mf = MessageFactory.newInstance();
        SOAPMessage request = mf.createMessage();
        request.getSOAPBody().addBodyElement(new QName("http://example.com/", "sayHello"))
              .addTextNode("Provider Client");
        // 调用服务
        SOAPMessage response = dispatch.invoke(request);
        response.writeTo(System.out);
    }
}

使用Apache CXF动态调用

1 使用JAX-WS前端

import org.apache.cxf.endpoint.Client;
import org.apache.cxf.frontend.ClientProxy;
import org.apache.cxf.jaxws.JaxWsProxyFactoryBean;
import org.apache.cxf.jaxws.JaxWsDynamicClientFactory;
public class CxfDynamicClient {
    public static void main(String[] args) {
        // 方法1: 使用JaxWsProxyFactoryBean
        JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();
        factory.setServiceClass(MyService.class);
        factory.setAddress("http://example.com/service");
        MyService service = (MyService) factory.create();
        String result = service.sayHello("CXF Client");
        System.out.println(result);
        // 方法2: 使用JaxWsDynamicClientFactory
        JaxWsDynamicClientFactory dcf = JaxWsDynamicClientFactory.newInstance();
        Client client = dcf.createClient("http://example.com/service?wsdl");
        // 调用方法
        Object[] response = client.invoke("sayHello", "Dynamic CXF");
        System.out.println(response[0]);
    }
}

2 使用CXF的Dispatch API

import org.apache.cxf.endpoint.Client;
import org.apache.cxf.frontend.ClientProxy;
import org.apache.cxf.jaxws.JaxWsProxyFactoryBean;
import org.apache.cxf.jaxws.JaxWsDynamicClientFactory;
import javax.xml.namespace.QName;
import javax.xml.soap.MessageFactory;
import javax.xml.soap.SOAPMessage;
import javax.xml.ws.Dispatch;
import javax.xml.ws.Service;
import java.net.URL;
public class CxfDispatchClient {
    public static void main(String[] args) throws Exception {
        URL wsdlUrl = new URL("http://example.com/service?wsdl");
        QName serviceName = new QName("http://example.com/", "MyService");
        Service service = Service.create(wsdlUrl, serviceName);
        QName portName = new QName("http://example.com/", "MyPort");
        Dispatch<SOAPMessage> dispatch = service.createDispatch(portName, SOAPMessage.class, Service.Mode.MESSAGE);
        // 创建SOAP请求
        MessageFactory mf = MessageFactory.newInstance();
        SOAPMessage request = mf.createMessage();
        request.getSOAPBody().addBodyElement(new QName("http://example.com/", "sayHello"))
              .addTextNode("CXF Dispatch Client");
        // 发送请求
        SOAPMessage response = dispatch.invoke(request);
        response.writeTo(System.out);
    }
}

使用Axis 1.x动态调用

import org.apache.axis.client.Service;
import org.apache.axis.client.Call;
import javax.xml.namespace.QName;
import java.net.URL;
public class Axis1DynamicClient {
    public static void main(String[] args) throws Exception {
        String endpoint = "http://example.com/service";
        String serviceName = "MyService";
        String operationName = "sayHello";
        Service service = new Service();
        Call call = (Call) service.createCall();
        call.setTargetEndpointAddress(new URL(endpoint));
        call.setOperationName(new QName(serviceName, operationName));
        Object[] params = new Object[]{"Axis Client"};
        Object response = call.invoke(params);
        System.out.println(response);
    }
}

动态调用注意事项

  1. WSDL解析:动态调用通常需要WSDL文件来获取服务端点信息
  2. 性能考虑:动态调用比静态代理调用性能稍差,因为需要反射和动态解析
  3. 错误处理:需要妥善处理网络异常、SOAP异常等
  4. 安全性:考虑添加SOAP头信息处理认证等安全需求
  5. 复杂类型:对于复杂类型的参数,需要手动构造XML或使用JAXB进行转换

最佳实践建议

  1. 对于简单的WebService调用,优先考虑使用静态生成的客户端代码
  2. 当服务接口频繁变化或需要运行时动态选择服务时,使用动态调用
  3. 在生产环境中,建议使用成熟的框架如CXF或Spring-WS
  4. 考虑使用Spring的WebServiceTemplate来简化WebService调用

方法可以根据实际项目需求和技术栈选择合适的实现方式。

分享:
扫描分享到社交APP
上一篇
下一篇