CXF客户端调用N种方式
方式一:
配置CXF环境变量,用wsdl2java工具自动产生代码。项目结构目录如下:
其中com.yq.webservice下面的所有的java类都是wsdl2java工具自动产生的。
JaxWsProxyFactoryBean factoryBean = new JaxWsProxyFactoryBean(); factoryBean.getInInterceptors().add(new LoggingInInterceptor()); factoryBean.getOutInterceptors().add(new LoggingOutInterceptor()); factoryBean.setServiceClass(HelloWorldDao.class); factoryBean.setAddress(":8080/WebServiceTest/webservice/helloworld?wsdl"); HelloWorldDao impl = (HelloWorldDao) factoryBean.create(); impl.sayHello("zhengmo");
其中:
http//:8080/WebServiceTest/webservice/helloworld?wsdl是服务端提供的web service的端口地址。
上面的代码就是WebServiceClient.java中main方法里面的代码。
方式二:
任然需要先用wsdl2java工具生成相应的java代码。
HelloWorldDaoService factory = new HelloWorldDaoService();
HelloWorldDao helloWorldDao = factory.getHelloWorldDaoPort();
helloWorldDao.sayHello("zhengmo");
方式三:
最后一种方式不需要使用wsdl2java工具在客户端产生代码。
JaxWsDynamicClientFactory dcf = JaxWsDynamicClientFactory.newInstance(); String wsUrl = "http//:8080/WebServiceTest/webservice/helloworld?wsdl"; Client client = dcf.createClient(wsUrl); String method = "sayHello";//webservice的方法名 Object[] result = null; try { result = client.invoke(method, "zhengmo");//调用webservice } catch (Exception e) { e.printStackTrace(); }
CXF提供了很多client端的调用方法。这里让你快速了解这些选择,帮助你判断使用哪种。
参见:
http://cxf.apache.org/docs/how-do-i-develop-a-client.html
源代码主体使用PacktPub.Apache.CXF.Web.Service.Development.Dec.2009书中的代码。本例中,将5种调用方式集中在一个工程中,并使用Maven重组的调用方式。
本例下载地址:
http://dl.iteye.com/topics/download/c647dae6-de86-3eec-9590-7fcf83e9def4
-
WSDL2Java generated Client
-
JAX-WS Proxy
-
JAX-WS Dispatch APIs
-
JAX-WS Client Proxy
-
Dynamic Client
-
Reflection API
-
Service Model API
-
在这里Dispatch本节内容不做介绍。
WSDL2Java generated Client
也就是依据wsdl文件生成java客户端,直接调用。查看调用方式,也就是OrderProcessService的getOrderProcessPort方法,获得服务的引用。
启动服务端
mvn test –Pserver
在启动服务端时,通过maven-compiler-plugin编译class,通过cxf-codegen-plugin依据src/main/resources/OrderProcess.wsdl生成存根类OrderProcessService
<plugins> <plugin> <artifactId>maven-compiler-plugin</artifactId> <configuration> <source>1.5</source> <target>1.5</target> </configuration> </plugin> <plugin> <groupId>org.apache.cxf</groupId> <artifactId>cxf-codegen-plugin</artifactId> <version>${cxf.version}</version> <executions> <execution> <id>generate-sources</id> <phase>generate-sources</phase> <configuration> <wsdlOptions> <wsdlOption> <wsdl>src/main/resources/OrderProcess.wsdl</wsdl> </wsdlOption> </wsdlOptions> </configuration> <goals> <goal>wsdl2java</goal> </goals> </execution> </executions> </plugin> </plugins>
启动客户端
mvn test -PStubClient
JAX-WS Proxy
和生成存根类的方式相反,proxy是不需要执行wsdl2java的。但是在编译环境中需要接口类和VO类。这里,通过指定WSDL_LOCATION和PORT_NAME,使用Service.create创建service,使用service.getPort获得服务引用。
package demo.order.client; import java.net.URL; import javax.xml.namespace.QName; import javax.xml.ws.Service; import demo.order.Order; import demo.order.OrderProcess; public class ProxyClient { private static final QName SERVICE_NAME = new QName("http://order.demo/", "OrderProcessService"); private static final QName PORT_NAME = new QName("http://order.demo/", "OrderProcessPort"); private static final String WSDL_LOCATION = "http://localhost:8080/OrderProcess?wsdl"; public static void main(String args[]) throws Exception { URL wsdlURL = new URL(WSDL_LOCATION); Service service = Service.create(wsdlURL, SERVICE_NAME); OrderProcess port = service.getPort(PORT_NAME, OrderProcess.class); Order order = new Order(); order.setCustomerID("C001"); order.setItemID("I001"); order.setPrice(100.00); order.setQty(20); String result = port.processOrder(order); System.out.println("The order ID is " + result); } }
启动服务端
mvn test –Pserver
启动客户端
mvn test -PProxyClient
Client Proxy
使用JaxWsProxyFactoryBean 类简化Proxy。
package demo.order.client; import demo.order.Order; import demo.order.OrderProcess; import org.apache.cxf.jaxws.JaxWsProxyFactoryBean; public class ClientProxyClient { public static void main(String args[]) throws Exception { JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean(); factory.setServiceClass(OrderProcess.class); factory.setAddress("http://localhost:8080/OrderProcess"); OrderProcess service = (OrderProcess)factory.create(); Order order = new Order(); order.setCustomerID("C001"); order.setItemID("I001"); order.setPrice(100.00); order.setQty(20); String result = service.processOrder(order); System.out.println("The order ID is " + result); } }
启动服务端
mvn test –Pserver
启动客户端
mvn test -PClientProxyClient
Dynamic Client
甚至不需要SEI接口类,
Reflection API
JaxWsDynamicClientFactory.newInstance获得JaxWsDynamicClientFactory实例。通过dcf.createClient获得Client客户端引用。
package demo.order.client; import org.apache.cxf.jaxws.endpoint.dynamic.JaxWsDynamicClientFactory; import org.apache.cxf.endpoint.Client; import java.lang.reflect.Method; public class OrderProcessJaxWsDynamicClient { public OrderProcessJaxWsDynamicClient() { } public static void main(String str[]) throws Exception { JaxWsDynamicClientFactory dcf = JaxWsDynamicClientFactory.newInstance(); Client client = dcf.createClient("http://localhost:8080/OrderProcess?wsdl"); Object order = Thread.currentThread().getContextClassLoader().loadClass("demo.order.Order").newInstance(); Method m1 = order.getClass().getMethod("setCustomerID", String.class); Method m2 = order.getClass().getMethod("setItemID", String.class); Method m3 = order.getClass().getMethod("setQty", Integer.class); Method m4 = order.getClass().getMethod("setPrice", Double.class); m1.invoke(order, "C001"); m2.invoke(order, "I001"); m3.invoke(order, 100); m4.invoke(order, 200.00); Object[] response = client.invoke("processOrder", order); System.out.println("Response is " + response[0]); } }
启动服务端
mvn test –Pserver
启动客户端
mvn test -POrderProcessJaxWsDynamicClient
Service Model API
最后,Service Model是CXF内置的获取Service的信息。
package demo.order.client; import java.beans.PropertyDescriptor; import java.util.List; import javax.xml.namespace.QName; import org.apache.cxf.endpoint.Client; import org.apache.cxf.endpoint.Endpoint; import org.apache.cxf.jaxws.endpoint.dynamic.JaxWsDynamicClientFactory; import org.apache.cxf.service.model.BindingInfo; import org.apache.cxf.service.model.BindingMessageInfo; import org.apache.cxf.service.model.BindingOperationInfo; import org.apache.cxf.service.model.MessagePartInfo; import org.apache.cxf.service.model.ServiceInfo; public class OrderProcessJaxWsDynClient { public OrderProcessJaxWsDynClient() { } public static void main(String str[]) throws Exception { JaxWsDynamicClientFactory dcf = JaxWsDynamicClientFactory.newInstance(); Client client = dcf.createClient("http://localhost:8080/OrderProcess?wsdl"); Endpoint endpoint = client.getEndpoint(); // Make use of CXF service model to introspect the existing WSDL ServiceInfo serviceInfo = endpoint.getService().getServiceInfos().get(0); QName bindingName = new QName("http://order.demo/", "OrderProcessServiceSoapBinding"); BindingInfo binding = serviceInfo.getBinding(bindingName); QName opName = new QName("http://order.demo/", "processOrder"); BindingOperationInfo boi = binding.getOperation(opName); // Operation name is processOrder BindingMessageInfo inputMessageInfo = null; if (!boi.isUnwrapped()) { //OrderProcess uses document literal wrapped style. inputMessageInfo = boi.getWrappedOperation().getInput(); } else { inputMessageInfo = boi.getUnwrappedOperation().getInput(); } List<MessagePartInfo> parts = inputMessageInfo.getMessageParts(); MessagePartInfo partInfo = parts.get(0); // Input class is Order // Get the input class Order Class<?> orderClass = partInfo.getTypeClass(); Object orderObject = orderClass.newInstance(); // Populate the Order bean // Set customer ID, item ID, price and quantity PropertyDescriptor custProperty = new PropertyDescriptor("customerID", orderClass); custProperty.getWriteMethod().invoke(orderObject, "C001"); PropertyDescriptor itemProperty = new PropertyDescriptor("itemID", orderClass); itemProperty.getWriteMethod().invoke(orderObject, "I001"); PropertyDescriptor priceProperty = new PropertyDescriptor("price", orderClass); priceProperty.getWriteMethod().invoke(orderObject, Double.valueOf(100.00)); PropertyDescriptor qtyProperty = new PropertyDescriptor("qty", orderClass); qtyProperty.getWriteMethod().invoke(orderObject, Integer.valueOf(20)); // Invoke the processOrder() method and print the result // The response class is String Object[] result = client.invoke(opName, orderObject); System.out.println("The order ID is " + result[0]); } }
//这种方法动态获取服务端对象也可以(亲测成功,jar版本cxf3.0.3)
JaxWsDynamicClientFactory dcf = JaxWsDynamicClientFactory.newInstance();
Client client = dcf.createClient("http://localhost:8080/cxfservice/services/getZdxmlist?wsdl");
Object[] result = client.invoke("getZdxmlist", "在建","2016","zd_ctx");
System.out.println("Echo response: " + result[0]);
JSONArray ja=JSONArray.fromObject(result[0]);
Object objs[]=ja.toArray();
for (int i = 0; i < objs.length; i++) {
System.out.println(JSONObject.fromObject(objs[i]).get("mc"));//输出各个对象的名称属性
}
有可能汇报这个错误:
CXF 异常 Caused by: org.apache.cxf.binding.soap.SoapFault: Unexpected wrapper element
解决 方法:将客户端中的Service的包名改成与服务端中的一致,问题解决。
http://bbs.csdn.net/topics/390797587
感谢您的阅读,您的支持是我写博客动力。