大概花费了一周的时间来了解web service 这个东东,从开始的axis2 ,到xFire ,到最后选择了CXF,一切的资料都是来自于网络资料,由于要和spring整合,因此最后选择了CXF,
我是用的是myeclipse6.5版本,导入cxf的jar包开发的时候出现了众多的问题,网上说的是java EE里面的javaee.jar里面jar包的问题,最后整个删掉了java EE lib,可是在myeclipse7.5就没问题, 有意思的是最后我又把这个java EE 的LIB导入了,嘿嘿 没有报错了。这东西应该还是有用的,还是不删为好啊,所以到这里建议大家使用7.5版本的,似乎6.5版本有bug。
1. 首先确定下来使用CXF 需要哪些jar包:
以上两幅图,左图是最终使用的,右图是开始开发时,遇到问题后加入的,但最后测试,使用左图即可。
2.控制台报错整理:
严重: Servlet.service() for servlet CXFServlet threw exception
java.lang.NoClassDefFoundError: org/apache/xml/serializer/TreeWalker
解决:导入serializer-2.7.1.jar 。
严重: Exception sending context initialized event to listener instance of class org.springframework.web.context.ContextLoaderListener
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'helloWorld': Invocation of init method failed; nested exception is java.lang.NoClassDefFoundError: javax/wsdl/extensions/ElementExtensible
Related cause: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'org.apache.cxf.binding.soap.SoapTransportFactory' defined in class path resource [META-INF/cxf/cxf-extension-soap.xml]: Unsatisfied dependency expressed through constructor argument with index 2 of type [java.lang.String]: Ambiguous constructor argument types - did you specify the correct bean references as constructor arguments?
解决:导入:neethi-3.0.1.jar 。
涉及到的配置文件修改:
1.web.xml :
在web.xml中增加如下代码:(我的spring容器配置文件是applicationContext.xml 放置在src下面。)
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
WEB-INF/classes/applicationContext.xml
</param-value>
</context-param>
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
<servlet>
<servlet-name>CXFServlet</servlet-name>
<display-name>CXFServlet</display-name>
<servlet-class>
org.apache.cxf.transport.servlet.CXFServlet
</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>CXFServlet</servlet-name>
<url-pattern>/webservice/*</url-pattern>
</servlet-mapping>
2. applicationContext.xml:
最终的该文件完整内容为:(当然这里没有其他bean的配置, 只是个实例而已 ,该实例的名称为:cxf_Demo1)
<?xml version="1.0" encoding="UTF-8"?>
<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.xsd
http://cxf.apache.org/jaxwshttp://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 id="helloWorld"
implementor="com.demo.HelloWorldImpl" address="/helloWorld" />
<bean id="client" class="com.demo.HelloWorld"
factory-bean="clientFactory" factory-method="create" />
<bean id="clientFactory"
class="org.apache.cxf.jaxws.JaxWsProxyFactoryBean">
<property name="serviceClass" value="com.demo.HelloWorld" />
<property name="address"
value="http://localhost:8080/cxf_Demo1/webservice/helloWorld" />
</bean>
</beans>
3.思路:
建立webservice 接口:普通java接口,在建立该接口的实现类。然后暴露该接口。详细代码如下:
package com.demo;
public class User {
private String name;
private String description;
/**
* @return the name
*/
public String getName() {
return name;
}
/**
* @param name the name to set
*/
public void setName(String name) {
this.name = name;
}
/**
* @return the description
*/
public String getDescription() {
return description;
}
/**
* @param description the description to set
*/
public void setDescription(String description) {
this.description = description;
}
}
package com.demo;
import java.util.List;
import javax.jws.WebParam;
import javax.jws.WebService;
@WebService
public interface HelloWorld {
String sayHi(@WebParam(name="text")String text);
String sayHiToUser(User user);
String[] SayHiToUserList(List<User> userList);
}
package com.demo;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import javax.jws.WebService;
@WebService(endpointInterface = "com.demo.HelloWorld", serviceName = "HelloWorld")
public class HelloWorldImpl implements HelloWorld {
Map<Integer, User> users = new LinkedHashMap<Integer, User>();
public String sayHi(String text) {
return "Hello " + text;
}
public String sayHiToUser(User user) {
users.put(users.size() + 1, user);
return "Hello " + user.getName();
}
public String[] SayHiToUserList(List<User> userList) {
String[] result = new String[userList.size()];
int i = 0;
for (User u : userList) {
result[i] = "Hello " + u.getName();
i++;
}
return result;
}
}
package com.demo;
import javax.xml.ws.Endpoint;
public class webServiceApp {
/**
* @author zhangxiaojun
* @version Sep 19, 2011 9:10:25 AM
* @param args
* TODO:
*/
public static void main(String[] args) {
System.out.println("web service start");
HelloWorldImpl implementor = new HelloWorldImpl();
String address = "http://localhost:8080/helloWorld";
Endpoint.publish(address, implementor);
System.out.println("web service started");
}
}
package com.demo;
import java.util.ArrayList;
import java.util.List;
import org.apache.cxf.jaxws.JaxWsProxyFactoryBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class HelloWorldClient {
/**
* @author zhangxiaojun
* @version Sep 19, 2011 10:42:49 AM
* @param args
* TODO:
*/
public static void main(String[] args) {
// JaxWsProxyFactoryBean svr = new JaxWsProxyFactoryBean();
// svr.setServiceClass(HelloWorld.class);
// svr.setAddress("http://localhost:8080/helloWorld");
// HelloWorld hw = (HelloWorld) svr.create();
// User user = new User();
// user.setName("Tony");
// user.setDescription("test");
// System.out.println(hw.sayHiToUser(user));
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
HelloWorld client = (HelloWorld)context.getBean("client");
User user1 = new User();
user1.setName("Tony");
user1.setDescription("test");
User user2 = new User();
user2.setName("freeman");
user2.setDescription("test");
List<User> userList= new ArrayList<User>();
userList.add(user1);
userList.add(user2);
String[] res = client.SayHiToUserList(userList);
System.out.println(res[0]);
System.out.println(res[1]);
}
}
在没有整合到spring的时候,通过以上代码段的客户端和服务器端代码,先启动服务器端代码:com.demo.webServiceApp.java ,在启动客户端代码:com.demo.HelloWorldClient.java 可以查看到控制台输出的结果。
当整合到spring后,部署到tomcat之后,启动浏览器 输入:http://localhost:8080/cxf_Demo1/webservice/helloWorld?wsdl 就可以 看到如下内容:
<?xml version="1.0" encoding="UTF-8" ?>
- <wsdl:definitions name="HelloWorld" targetNamespace="http://demo.com/" xmlns:ns1="http://schemas.xmlsoap.org/soap/http" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="http://demo.com/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
- <wsdl:types>
- <xs:schema targetNamespace="http://jaxb.dev.java.net/array" version="1.0" xmlns:xs="http://www.w3.org/2001/XMLSchema">
+ <xs:complexType final="#all" name="stringArray">
- <xs:sequence>
<xs:element maxOccurs="unbounded" minOccurs="0" name="item" nillable="true" type="xs:string" />
</xs:sequence>
</xs:complexType>
</xs:schema>
- <xs:schema attributeFormDefault="unqualified" elementFormDefault="unqualified" targetNamespace="http://demo.com/" xmlns="http://demo.com/" xmlns:xs="http://www.w3.org/2001/XMLSchema">
- <xs:complexType name="user">
- <xs:sequence>
<xs:element minOccurs="0" name="description" type="xs:string" />
<xs:element minOccurs="0" name="name" type="xs:string" />
</xs:sequence>
</xs:complexType>
<xs:element name="SayHiToUserList" type="SayHiToUserList" />
- <xs:complexType name="SayHiToUserList">
- <xs:sequence>
<xs:element maxOccurs="unbounded" minOccurs="0" name="arg0" type="user" />
</xs:sequence>
</xs:complexType>
<xs:element name="SayHiToUserListResponse" type="SayHiToUserListResponse" />
- <xs:complexType name="SayHiToUserListResponse">
- <xs:sequence>
<xs:element maxOccurs="unbounded" minOccurs="0" name="return" type="xs:string" />
</xs:sequence>
</xs:complexType>
<xs:element name="sayHi" type="sayHi" />
- <xs:complexType name="sayHi">
- <xs:sequence>
<xs:element minOccurs="0" name="text" type="xs:string" />
</xs:sequence>
</xs:complexType>
<xs:element name="sayHiResponse" type="sayHiResponse" />
- <xs:complexType name="sayHiResponse">
- <xs:sequence>
<xs:element minOccurs="0" name="return" type="xs:string" />
</xs:sequence>
</xs:complexType>
<xs:element name="sayHiToUser" type="sayHiToUser" />
- <xs:complexType name="sayHiToUser">
- <xs:sequence>
<xs:element minOccurs="0" name="arg0" type="user" />
</xs:sequence>
</xs:complexType>
<xs:element name="sayHiToUserResponse" type="sayHiToUserResponse" />
- <xs:complexType name="sayHiToUserResponse">
- <xs:sequence>
<xs:element minOccurs="0" name="return" type="xs:string" />
</xs:sequence>
</xs:complexType>
</xs:schema>
</wsdl:types>
- <wsdl:message name="sayHiToUserResponse">
<wsdl:part element="tns:sayHiToUserResponse" name="parameters" />
</wsdl:message>
- <wsdl:message name="SayHiToUserList">
<wsdl:part element="tns:SayHiToUserList" name="parameters" />
</wsdl:message>
- <wsdl:message name="sayHiResponse">
<wsdl:part element="tns:sayHiResponse" name="parameters" />
</wsdl:message>
- <wsdl:message name="sayHi">
<wsdl:part element="tns:sayHi" name="parameters" />
</wsdl:message>
- <wsdl:message name="sayHiToUser">
<wsdl:part element="tns:sayHiToUser" name="parameters" />
</wsdl:message>
- <wsdl:message name="SayHiToUserListResponse">
<wsdl:part element="tns:SayHiToUserListResponse" name="parameters" />
</wsdl:message>
- <wsdl:portType name="HelloWorld">
- <wsdl:operation name="SayHiToUserList">
<wsdl:input message="tns:SayHiToUserList" name="SayHiToUserList" />
<wsdl:output message="tns:SayHiToUserListResponse" name="SayHiToUserListResponse" />
</wsdl:operation>
- <wsdl:operation name="sayHi">
<wsdl:input message="tns:sayHi" name="sayHi" />
<wsdl:output message="tns:sayHiResponse" name="sayHiResponse" />
</wsdl:operation>
- <wsdl:operation name="sayHiToUser">
<wsdl:input message="tns:sayHiToUser" name="sayHiToUser" />
<wsdl:output message="tns:sayHiToUserResponse" name="sayHiToUserResponse" />
</wsdl:operation>
</wsdl:portType>
- <wsdl:binding name="HelloWorldSoapBinding" type="tns:HelloWorld">
<soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http" />
- <wsdl:operation name="SayHiToUserList">
<soap:operation soapAction="" style="document" />
- <wsdl:input name="SayHiToUserList">
<soap:body use="literal" />
</wsdl:input>
- <wsdl:output name="SayHiToUserListResponse">
<soap:body use="literal" />
</wsdl:output>
</wsdl:operation>
- <wsdl:operation name="sayHi">
<soap:operation soapAction="" style="document" />
- <wsdl:input name="sayHi">
<soap:body use="literal" />
</wsdl:input>
- <wsdl:output name="sayHiResponse">
<soap:body use="literal" />
</wsdl:output>
</wsdl:operation>
- <wsdl:operation name="sayHiToUser">
<soap:operation soapAction="" style="document" />
- <wsdl:input name="sayHiToUser">
<soap:body use="literal" />
</wsdl:input>
- <wsdl:output name="sayHiToUserResponse">
<soap:body use="literal" />
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
- <wsdl:service name="HelloWorld">
- <wsdl:port binding="tns:HelloWorldSoapBinding" name="HelloWorldImplPort">
<soap:address location="http://localhost:8080/cxf_Demo1/webservice/helloWorld" />
</wsdl:port>
</wsdl:service>
</wsdl:definitions>
然后再启动客户端:com.demo.HelloWorldClient.java 则在控制台能够看到输出的结果:Hello Tony Hello freeman
最后发现,如果执行该客户端的话, 还得删除 java EE 的lib。晕。否则报如下错:
信息: Creating Service {http://demo.com/}HelloWorldService from class com.demo.HelloWorld
Exception in thread "main" java.lang.NoClassDefFoundError: com/sun/activation/registries/LogSupport
并且需要导入如下cxf 的三个包,否则也要报错:
报错内容:
信息: Creating Service {http://demo.com/}HelloWorld from class com.demo.HelloWorld
Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'helloWorld': Invocation of init method failed; nested exception is java.lang.NoClassDefFoundError: javax/wsdl/extensions/ElementExtensible
Related cause: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'org.apache.cxf.binding.soap.SoapTransportFactory' defined in class path resource [META-INF/cxf/cxf-extension-soap.xml]: Unsatisfied dependency expressed through constructor argument with index 2 of type [java.lang.String]: Ambiguous constructor argument types - did you specify the correct bean references as constructor arguments?
===============================================
总算一周时间没有白费,基本搞定啦。在努力!