cxf 版本 2.7.2
服务端工程:CXFThirdServer
IHelloWorld
import java.util.List;
import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebResult;
import javax.jws.WebService;
@WebService
public interface IHelloWorld {
@WebMethod
public @WebResult(name="returnStr")String sayHello(@WebParam(name="name")String name);
@WebMethod
public @WebResult(name="returnUser")User sayHello2(@WebParam(name="name")String name, @WebParam(name="age")String age);
@WebMethod
public @WebResult(name="returnList")List<User> sayHello3(@WebParam(name="name")String name, @WebParam(name="age")String age);
}
实现类HelloWorld:
package bean;
import java.util.ArrayList;
import java.util.List;
import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebResult;
import javax.jws.WebService;
@WebService
public class HelloWorld implements IHelloWorld {
@Override
@WebMethod
public @WebResult(name="name")String sayHello(@WebParam(name="name")String name){
System.out.println("CXFThirdServer sayHello called...");
return "Hello " + name;
}
@Override
@WebMethod
public @WebResult(name="returnUser")User sayHello2(@WebParam(name="name")String name, @WebParam(name="age")String age) {
// TODO Auto-generated method stub
System.out.println("CXFThirdServer sayHello2 called...");
User user = new User();
user.name = name;
user.age = age;
return user;
}
@WebMethod
public @WebResult(name="returnList")List<User> sayHello3(@WebParam(name="name")String name, @WebParam(name="age")String age){
List<User> returnList = new ArrayList<User>();
for(int i =0; i < 3; i++){
User u = new User();
u.name = name+i;
u.age = age+i;
returnList.add(u);
}
return returnList;
}
}
返回javabean:
User
package bean;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement(name="User")
@XmlAccessorType(value=XmlAccessType.FIELD)
public class User {
public String name;
public String age;
}
webservice 在网络上传输对象是用jaxb将对象序列化为xml。
main类 MainServer:
package main;
import javax.xml.ws.Endpoint;
import bean.HelloWorld;
public class MainServer {
public static void main(String[] args){
HelloWorld hello = new HelloWorld();
}
}
//Endpoint.publish("http://localhost:9001/HelloWorld", hello);将hello发布成webservice到jdk内嵌的容器中;也可以发布到tomcat中,写配置文件cxfconfig.xml和web.xml,然后在tomcat的webapps文件夹下new一个文件,名称是工程名,我这里是CXFThirdServer,然后再把该工程的WEB-INFO拷贝到CXFThirdServer文件夹下,就算再tomcat里面部署好了,在浏览器里打开http://localhost:8080/CXFThirdServer/HelloWorld?wsdl,得到wsdl文件的内容,那么在tomcat里面该服务就算发布好了。
cxfconfig.xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jaxws="http://cxf.apache.org/jaxws"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://cxf.apache.org/jaxws
http://cxf.apache.org/schemas/jaxws.xsd">
<import resource="classpath:META-INF/cxf/cxf.xml"/>
<import resource="classpath:META-INF/cxf/cxf-extension-soap.xml"/>
<import resource="classpath:META-INF/cxf/cxf-servlet.xml"/>
<jaxws:endpoint address="/HelloWorld" implementor="bean.HelloWorld"><!--利用相对路径将服务发布到http://localhost:8080/CXFThirdServer/HelloWorld-->
<jaxws:inInterceptors>
<bean class="org.apache.cxf.interceptor.LoggingInInterceptor"/><!--利用cxf的日志拦截器打印收到的soap消息和发送的soap消息-->
</jaxws:inInterceptors>
<jaxws:outInterceptors>
<bean class="org.apache.cxf.interceptor.LoggingOutInterceptor"/>
</jaxws:outInterceptors>
</jaxws:endpoint>
</beans>
web.xml:
<!DOCTYPE web-app
PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
<!-- Spring Config Location -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/cxfconfig.xml</param-value>
</context-param>
<!-- Spring ContextLoaderListener -->
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
<servlet>
<servlet-name>CXFServlet</servlet-name>
<display-name>CXF Servlet</display-name>
<servlet-class>
org.apache.cxf.transport.servlet.CXFServlet
</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<!-- CXFServlet Mapping -->
<servlet-mapping>
<servlet-name>CXFServlet</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
</web-app>
下面是创建客户端工程:CXFThirdClient
利用wsdl2java命令生成对应的接口和javabean:wsdl2java -d F:\cxftest http://localhost:8080/CXFThirdServer/HelloWorld?wsdl
将得到的IHelloWorld接口和User对象拷贝到CXFThirdClient工程下面的bean包中,
然后在main包中创建主类MainClient:
package main;
import java.io.IOException;
import java.io.OutputStream;
import java.io.StringReader;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.Future;
import javax.xml.namespace.QName;
import javax.xml.soap.AttachmentPart;
import javax.xml.soap.MimeHeaders;
import javax.xml.soap.SOAPElement;
import javax.xml.soap.SOAPException;
import javax.xml.soap.SOAPMessage;
import javax.xml.soap.SOAPPart;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.sax.SAXSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
import javax.xml.ws.AsyncHandler;
import javax.xml.ws.Dispatch;
import javax.xml.ws.Response;
import javax.xml.ws.Service;
import org.xml.sax.InputSource;
import bean.IHelloWorld;
import bean.User;
public class MainClient {
/**
* @param args
* @throws MalformedURLException
*/
public static void main(String[] args) throws MalformedURLException {
// TODO Auto-generated method stub
QName serviceQName = new QName("http://bean/","HelloWorldService");//对应wsdl:service name="HelloWorldService"
Service service = Service.create(new URL("http://localhost:8080/CXFThirdServer/HelloWorld?wsdl"), serviceQName);//
//GET http://localhost:8080/CXFThirdServer/HelloWorld?wsdl,对应URL地址http://localhost:8080/CXFThirdServer/HelloWorld?wsdl
System.out.println("service = " + service);
QName portQName = new QName("http://bean/","HelloWorldPort");
sayHelloSync(service,portQName);
// sayHelloAsync(service,portQName);
}
private static void sayHelloSync(Service service,QName portQName){//同步方法调用sayHello
/*IHelloWorld hello = service.getPort(portQName,IHelloWorld.class);
System.out.println(hello.sayHello("text!"));*/
/* IHelloWorld hello = service.getPort(portQName,IHelloWorld.class);
User user = hello.sayHello2("D Wade", " 31");
System.out.println("name:"+user.getName()+" age:"+user.getAge());*/
IHelloWorld hello = service.getPort(portQName,IHelloWorld.class);//对应<wsdl:port binding="tns:HelloWorldServiceSoapBinding" name="HelloWorldPort">
List<User> returnList = hello.sayHello3("D Wade", " 31");//GET http://localhost:8080/CXFThirdServer/HelloWorld 报文体是发送过去的soap消息
for(User user: returnList){
System.out.println("name:"+user.getName()+" age:"+user.getAge());
}
}
private static void sayHelloAsync(Service service,QName portQName){//利用回调方法异步调用sayHello
final Dispatch<Source> dispatch = service.createDispatch(portQName, Source.class, Service.Mode.PAYLOAD);
String payload = "<ns2:sayHello xmlns:ns2=\"http://bean/\"><name>BBBBBBBBBBB!</name></ns2:sayHello>";
final Source payloadMsg = new StreamSource(new StringReader(payload));
System.out.println("msg = " + payloadMsg);
Future f = dispatch.invokeAsync(payloadMsg, new AsyncHandler<Source>() {
//GET http://localhost:8080/CXFThirdServer/HelloWorld 报文体是发送过去的soap消息
@Override
public void handleResponse(Response<Source> res) {
// TODO Auto-generated method stub
try{
System.out.println("in handleResponse");
Source source = res.get();
Transformer transformer = TransformerFactory.newInstance().newTransformer();
transformer.transform(source, new StreamResult(System.out));
}catch(Exception e){
e.printStackTrace();
}
}
});
// System.out.println("isDone = " + f.isDone());
System.out.println("after dispatch.invokeAsync");
}
}
回调方法异步调用sayHello有些问题,有时候可以调用成功,有时候失败。debug了半天,发现dispatch.invokeAsync有时候发送过去的soap报文体丢失了,具体原因不明。
顺便提一句,soapui是模拟soap消息发送给webservice服务方的,貌似很好用!
再补个图先: