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

时间:2012-09-17 13:09:53

标签: cxf java webservice-client proxy-classes

在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服务方法并且我想在客户端程序中使用它时,我需要重新生成代理类

所以我找到了 CXF DynamicClientFactory ,这种技术避免了使用代理类:

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并且不生成“静态”代理类?也许有一个不同的图书馆?谢谢!

2 个答案:

答案 0 :(得分:1)

我知道这是一个非常古老的问题,但如果您仍然感兴趣,可以使用 soap-ws github项目: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);

你可以看到它真的很简单。

答案 1 :(得分:0)

使用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;
    }