动态调用web服务的简单方法(无需JDK或代理类)



在Python中,我可以很容易地使用web服务:

from suds.client import Client
client = Client('http://www.example.org/MyService/wsdl/myservice.wsdl') #create client
result = client.service.myWSMethod("Bubi", 15)  #invoke method
print result    #print the result returned by the WS method

我想用Java实现如此简单的用法

使用Axis或CXF,您必须创建一个web服务客户端,即一个复制所有web服务方法的包,以便我们可以像调用正常方法一样调用它们。让我们称之为代理类;它们通常由wsdl2java工具生成。

实用且用户友好。但是,每当我添加/修改web服务方法并希望在客户端程序中使用它时,我都需要重新生成代理类

所以我发现CXFDynamicClientFactory,这种技术避免了使用代理类:

import org.apache.cxf.endpoint.Client;
import org.apache.cxf.endpoint.dynamic.DynamicClientFactory;
//...
//create client
DynamicClientFactory dcf = DynamicClientFactory.newInstance();
Client client = dcf.createClient("http://www.example.org/MyService/wsdl/myservice.wsdl");
//invoke method
Object[] res = client.invoke("myWSMethod", "Bubi");
//print the result
System.out.println("Response:n" + res[0]);

但不幸的是,它在运行时创建和编译代理类,因此需要在生产机器上使用JDK。我必须避免这种情况,或者至少我不能依赖它

我的问题

有没有其他方法可以在Java中日常调用web服务的任何方法,而无需在运行时使用JDK,也无需生成"静态"代理类?也许去另一个图书馆?谢谢

我知道这是一个很老的问题,但如果你仍然感兴趣,你可以使用soap-wsgithub项目:https://github.com/reficio/soap-ws

这里有一个非常简单的用法示例:

Wsdl wsdl = Wsdl.parse("http://www.webservicex.net/CurrencyConvertor.asmx?WSDL");
SoapBuilder builder = wsdl.binding()
.localPart("CurrencyConvertorSoap")
.find();
SoapOperation operation = builder.operation()
.soapAction("http://www.webserviceX.NET/ConversionRate")
.find();
Request request = builder.buildInputMessage(operation)
SoapClient client = SoapClient.builder()
.endpointUrl("http://www.webservicex.net/CurrencyConvertor.asmx")
.build();
String response = client.post(request);

正如你所看到的,这真的很简单。

使用CXF 3.x,StaxDataBinding可以实现这一点。按照以下步骤学习基本知识。当然,这可以根据您的需要进行增强。

  1. 创建StaxDataBinding,如下所示。请注意,下面的代码可以根据您的复杂程度进行增强。

    class StaxDataBinding extends AbstractInterceptorProvidingDataBinding {
    private XMLStreamDataReader xsrReader;
    private XMLStreamDataWriter xswWriter;
    public StaxDataBinding() {
    super();
    this.xsrReader = new XMLStreamDataReader();
    this.xswWriter = new XMLStreamDataWriter();
    inInterceptors.add(new StaxInEndingInterceptor(Phase.POST_INVOKE));
    inFaultInterceptors.add(new StaxInEndingInterceptor(Phase.POST_INVOKE));
    inInterceptors.add(RemoveStaxInEndingInterceptor.INSTANCE);
    inFaultInterceptors.add(RemoveStaxInEndingInterceptor.INSTANCE);
    }
    static class RemoveStaxInEndingInterceptor
    extends AbstractPhaseInterceptor<Message> {
    static final RemoveStaxInEndingInterceptor INSTANCE = new RemoveStaxInEndingInterceptor();
    public RemoveStaxInEndingInterceptor() {
    super(Phase.PRE_INVOKE);
    addBefore(StaxInEndingInterceptor.class.getName());
    }
    public void handleMessage(Message message) throws Fault {
    message.getInterceptorChain().remove(StaxInEndingInterceptor.INSTANCE);
    }
    }
    public void initialize(Service service) {
    for (ServiceInfo serviceInfo : service.getServiceInfos()) {
    SchemaCollection schemaCollection = serviceInfo.getXmlSchemaCollection();
    if (schemaCollection.getXmlSchemas().length > 1) {
    // Schemas are already populated.
    continue;
    }
    new ServiceModelVisitor(serviceInfo) {
    public void begin(MessagePartInfo part) {
    if (part.getTypeQName() != null
    || part.getElementQName() != null) {
    return;
    }
    part.setTypeQName(Constants.XSD_ANYTYPE);
    }
    }.walk();
    }
    }
    @SuppressWarnings("unchecked")
    public <T> DataReader<T> createReader(Class<T> cls) {
    if (cls == XMLStreamReader.class) {
    return (DataReader<T>) xsrReader;
    }
    else {
    throw new UnsupportedOperationException(
    "The type " + cls.getName() + " is not supported.");
    }
    }
    public Class<?>[] getSupportedReaderFormats() {
    return new Class[] { XMLStreamReader.class };
    }
    @SuppressWarnings("unchecked")
    public <T> DataWriter<T> createWriter(Class<T> cls) {
    if (cls == XMLStreamWriter.class) {
    return (DataWriter<T>) xswWriter;
    }
    else {
    throw new UnsupportedOperationException(
    "The type " + cls.getName() + " is not supported.");
    }
    }
    public Class<?>[] getSupportedWriterFormats() {
    return new Class[] { XMLStreamWriter.class, Node.class };
    }
    public static class XMLStreamDataReader implements DataReader<XMLStreamReader> {
    public Object read(MessagePartInfo part, XMLStreamReader input) {
    return read(null, input, part.getTypeClass());
    }
    public Object read(QName name, XMLStreamReader input, Class<?> type) {
    return input;
    }
    public Object read(XMLStreamReader reader) {
    return reader;
    }
    public void setSchema(Schema s) {
    }
    public void setAttachments(Collection<Attachment> attachments) {
    }
    public void setProperty(String prop, Object value) {
    }
    }
    public static class XMLStreamDataWriter implements DataWriter<XMLStreamWriter> {
    private static final Logger LOG = LogUtils
    .getL7dLogger(XMLStreamDataWriter.class);
    public void write(Object obj, MessagePartInfo part, XMLStreamWriter writer) {
    try {
    if (!doWrite(obj, writer)) {
    // WRITE YOUR LOGIC HOW you WANT TO HANDLE THE INPUT DATA
    //BELOW CODE JUST CALLS toString() METHOD
    if (part.isElement()) {
    QName element = part.getElementQName();
    writer.writeStartElement(element.getNamespaceURI(),
    element.getLocalPart());
    if (obj != null) {
    writer.writeCharacters(obj.toString());
    }
    writer.writeEndElement();
    }
    }
    }
    catch (XMLStreamException e) {
    throw new Fault("COULD_NOT_READ_XML_STREAM", LOG, e);
    }
    }
    public void write(Object obj, XMLStreamWriter writer) {
    try {
    if (!doWrite(obj, writer)) {
    throw new UnsupportedOperationException("Data types of "
    + obj.getClass() + " are not supported.");
    }
    }
    catch (XMLStreamException e) {
    throw new Fault("COULD_NOT_READ_XML_STREAM", LOG, e);
    }
    }
    private boolean doWrite(Object obj, XMLStreamWriter writer)
    throws XMLStreamException {
    if (obj instanceof XMLStreamReader) {
    XMLStreamReader xmlStreamReader = (XMLStreamReader) obj;
    StaxUtils.copy(xmlStreamReader, writer);
    xmlStreamReader.close();
    return true;
    }
    else if (obj instanceof XMLStreamWriterCallback) {
    ((XMLStreamWriterCallback) obj).write(writer);
    return true;
    }
    return false;
    }
    public void setSchema(Schema s) {
    }
    public void setAttachments(Collection<Attachment> attachments) {
    }
    public void setProperty(String key, Object value) {
    }
    }
    }
    
  2. 准备好你的输入以匹配预期的输入,比如下面的

    private Object[] prepareInput(BindingOperationInfo operInfo, String[] paramNames,
    String[] paramValues) {
    List<Object> inputs = new ArrayList<Object>();
    List<MessagePartInfo> parts = operInfo.getInput().getMessageParts();
    if (parts != null && parts.size() > 0) {
    for (MessagePartInfo partInfo : parts) {
    QName element = partInfo.getElementQName();
    String localPart = element.getLocalPart();
    // whatever your input data you need to match data value for given element
    // below code assumes names are paramNames variable and value in paramValues
    for (int i = 0; i < paramNames.length; i++) {
    if (paramNames[i].equals(localPart)) {
    inputs.add(findParamValue(paramNames, paramValues, localPart));
    }
    }
    }
    }
    return inputs.toArray();
    }
    
  3. 现在设置正确的数据绑定并传递数据

    Bus bus = CXFBusFactory.getThreadDefaultBus();
    WSDLServiceFactory sf = new WSDLServiceFactory(bus, wsdl);
    sf.setAllowElementRefs(false);
    Service svc = sf.create();
    Client client = new ClientImpl(bus, svc, null,
    SimpleEndpointImplFactory.getSingleton());
    StaxDataBinding databinding = new StaxDataBinding();
    svc.setDataBinding(databinding);
    bus.getFeatures().add(new StaxDataBindingFeature());
    BindingOperationInfo operInfo = ...//find the operation you need (see below)
    Object[] inputs = prepareInput(operInfo, paramNames, paramValues);
    client.invoke("operationname", inputs);
    
  4. 如果需要,你可以在下面匹配操作名称

    private BindingOperationInfo findBindingOperation(Service service,
    String operationName) {
    for (ServiceInfo serviceInfo : service.getServiceInfos()) {
    Collection<BindingInfo> bindingInfos = serviceInfo.getBindings();
    for (BindingInfo bindingInfo : bindingInfos) {
    Collection<BindingOperationInfo> operInfos = bindingInfo.getOperations();
    for (BindingOperationInfo operInfo : operInfos) {
    if (operInfo.getName().getLocalPart().equals(operationName)) {
    if (operInfo.isUnwrappedCapable()) {
    return operInfo.getUnwrappedOperation();
    }
    return operInfo;
    }
    }
    }
    }
    return null;
    }
    

相关内容

最新更新