在Java中实现webservice有两种常用的方式,一种是cxf,另一种是axis。这两种方式的区别大家可以自己在网上找找参考一下。cxf可以与spring进行整合,是一款不错的webservice产品。今天给大家讲解一下使用spring整合cxf实现webservice的方法。
1 创建服务器端程序
1.1 新建一个web工程
1.1.1 工程环境所依赖的各软件的版本
首先需要新建一个web工程,工程运行环境为:
-
java:1.7.0_65
-
tomcat:apache-tomcat-6.0.47
-
eclipse:Luna Service Release 2 (4.4.2)
-
cxf:3.1.8
-
操作系统:win7
先给大家看一下eclipse中生成的服务器端程序:
注意将下载之后的cxf的3.1.8版本lib里的所有jar包都拷贝到项目中,并建立引用关系,笔者这里就是上图“Libraries”中的“WebServiceServer”库。
1.1.2 创建pojo
先写一个pojo,即文件Person.java:
package com.yhd.webservice.cxf.server.poto;/**
* 类名称:Persion.java<br>
* 类描述:<br>
* 创建时间:2016年11月11日, 下午2:48:45
*
* @version 1.0
* @since JDK1.7.0_65
* @author yhd
*/public class Person {
private String name; private int age; public Person() {
} public Person(String name, int age) { this.name = name; this.age = age;
} public String getName() { return name;
} public void setName(String name) { this.name = name;
} public int getAge() { return age;
} public void setAge(int age) { this.age = age;
}
1.1.3 创建接口
定义一个接口,即文件PersonService.java:
package com.yhd.webservice.cxf.server.service;
import java.util.List;
import javax.jws.WebParam;
import javax.jws.WebService;
import com.yhd.webservice.cxf.server.poto.Person;
/**
* 类名称:PersonService.java<br>
* 类描述:<br>
* 创建时间:2016年11月11日, 下午2:43:36
*
* @version 1.0
* @since JDK1.7.0_65
* @author yhd
*/
@WebService
public interface PersonService {
public List<Person> findAll(@WebParam(name = "arg0") String name);
}
1.1.4 接口实现类
接口类的实现,即文件PersonServiceImp.java:
package com.yhd.webservice.cxf.server.service.impl;
import java.util.ArrayList;
import java.util.List;
import javax.jws.WebService;
import com.yhd.webservice.cxf.server.poto.Person;
import com.yhd.webservice.cxf.server.service.PersonService;
/**
* 类名称:PersonServiceImp.java<br>
* 类描述:<br>
* 创建时间:2016年11月11日, 下午2:47:53
*
* @version 1.0
* @since JDK1.7.0_65
* @author yhd
*/
@WebService(endpointInterface="com.yhd.webservice.cxf.server.service.PersonService",serviceName="person")
public class PersonServiceImp implements PersonService {
@Override
public List<Person> findAll(String name){
ArrayList<Person> persons = new ArrayList<Person>();
Person p1 = new Person();
p1.setName(name + "3");
p1.setAge(18);
Person p2 = new Person();
p2.setName(name + "4");
p2.setAge(20);
persons.add(p1);
persons.add(p2);
return persons;
}
}
1.1.5 spring配置文件application-context.xml
<?xml version="1.0" encoding="UTF-8"?>
<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.5.xsd http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd"
xmlns="http://www.springframework.org/schema/beans">
<bean id="jaxWsServiceFactoryBean" class="org.apache.cxf.jaxws.support.JaxWsServiceFactoryBean">
<property name="wrapped" value="true" />
</bean>
<jaxws:endpoint id="serviceimp" address="/person"
implementor="com.yhd.webservice.cxf.server.service.impl.PersonServiceImp">
<jaxws:serviceFactory>
<ref bean="jaxWsServiceFactoryBean" />
</jaxws:serviceFactory>
</jaxws:endpoint>
</beans>
这里要注意,网上很多配置cxf的参考文章都提到要将三个配置信息放到spring的配置文件中:
<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" />
但是对于这里使用到的cxf最新版3.1.8,如果加上:
<import resource="classpath:META-INF/cxf/cxf-extension-soap.xml" />
反而会报错:
严重: Context initialization failed
org.springframework.beans.factory.parsing.BeanDefinitionParsingException: Configuration problem: Failed to import bean definitions from URL location [classpath:META-INF/cxf/cxf-extension-soap.xml]
网上说cxf3.0之后可能已经不需要这个文件了,将这个文件去掉就可以了。或者将这三个配置都去掉也可以。笔者将这三者都去掉了,可以使用。
1.1.6 配置web.xml
<?xml version="1.0" encoding="UTF-8"?><web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
<display-name>WebServiceServer</display-name>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>
<display-name>cxfTest</display-name>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/application-context.xml</param-value>
</context-param>
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
<servlet>
<servlet-name>CXFServlet</servlet-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>/hello/*</url-pattern>
</servlet-mapping></web-app>
这里面配置了spring的监听器,又配置了一个cxf的servlet。
1.2 启动web工程
笔者这里在tomcat中配置了web工程的端口号为8081,并且将8081直接指向eclipse中工程的地址,所以访问该工程时就不用再输入工程名了。
启动tomcat。在浏览器里输入:
如上所示,没有再输入工程名“WebServiceServer”。
这时浏览器页面会出现:
能看到“person”前有一个倒过来的类包的名称。
这说明服务器端已经创建成功!
2 生成服务器端接口类
2.1 安装cxf
在cxf官网下载cxf的3.1.8版本,笔者下载的zip版。将文件解压缩并放到一个合适的目录下。在环境变量中加入变量“CXF_HOME”,值就是安装路径;再在“PATH”变量中加入:
%CXF_HOME%\bin
这样cxf的命令就可以使用了。
2.2 使用“wsdl2java”命令生成接口类
wsdl2java的用法如下:
wsdl2java –p 包名 –d 目录名 wsdl路径
具体的意义如下:
-
-p:指定其wsdl的命名空间,也就是要生成代码的包名
-
-d:指定要产生代码所在目录
-
-client 生成客户端测试web service的代码
-
-server:生成服务器启动web service的代码
-
-impl:生成web service的实现代码
-
-ant:生成build.xml文件
-
-compile:生成代码后编译
-
-quient:静默模式,不输出警告与错误信息
-
-all:生成所有开始端点代码:types,service proxy,service interface, server mainline, client mainline, implementation object, and an Ant build.xml file.
笔者这里的命令为:
wsdl2java -p com.yhd.webservice.cxf.client.info -d D:\test http://localhost:8081/hello/person?wsdl
执行之后就会在-d后面的路径下生成相应的类。
2.3 将接口类拷贝到客户端项目中
将这些类拷贝到后面新创建的客户端项目中。
有的时候生成了类之后,将这些类拷贝到客户端项目,类中的某些super()会报错。这就需要再加上“-frontend jaxws21”命令,也就是将命令写为:
wsdl2java -frontend jaxws21 -p com.yhd.webservice.cxf.client.info -d D:\test http://localhost:8081/hello/person?wsdl
再生成的类就不会报错了。
3 创建客户端程序
客户端我们就做一个简单的程序。
依然创建一个web项目(其实创建一个java项目就可以了),依赖的类与服务器端一样,将cxf的jar包都拷贝进去,程序如下:
将服务器端生成的接口类拷贝过来,然后再创建一个“ClientTest.jar”文件,内容如下:
package com.yhd.webservice.cxf.client.main;import java.util.List;import org.apache.cxf.jaxws.JaxWsProxyFactoryBean;import com.yhd.webservice.cxf.client.info.Person;import com.yhd.webservice.cxf.client.info.PersonService;/**
* 类名称:ClientTest.java<br>
* 类描述:<br>
* 创建时间:2016年11月15日, 上午10:04:16
*
* @version 1.0
* @since JDK1.7.0_65
* @author yhd
*/public class ClientTest {
public static void main(String[] args) {
JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();
factory.setServiceClass(PersonService.class);
factory.setAddress("http://localhost:8081/hello/person");
PersonService service = (PersonService)factory.create();
List<Person> list = (List<Person>)service.findAll("张"); for(Person person : list) {
System.out.println("name=" + person.getName());
System.out.println("age=" + person.getAge());
System.out.println("-------------------");
}
4 运行客户端程序
在服务器端保持运行的状态下,运行客户端程序。正常的话,会打印出:
name=张3age=18
-------------------name=张4age=20
-------------------
有一点要注意,一方面,一定要保持客户端和服务器端使用的jdk版本是一致的,另一方面,cxf从3.1开始已经不支持jdk的1.6版本了,而至少是jdk的1.7或者是以上的版本。所以我们的项目里的jdk至少需要使用jdk的1.7版本,否则比如使用1.6,有可能会报错:
Caused by: java.lang.UnsupportedClassVersionError: org/apache/cxf/jaxws/spring/NamespaceHandler : Unsupported major.minor version 51.0
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClassCond(Unknown Source)
at java.lang.ClassLoader.defineClass(Unknown Source)
at java.security.SecureClassLoader.defineClass(Unknown Source)
at java.NET.URLClassLoader.defineClass(Unknown Source)
at java.Net.URLClassLoader.access000(UnknownSource)atjava.net.URLClassLoader 1.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(Unknown Source)
at org.apache.catalina.loader.WebappClassLoader.findClass(WebappClassLoader.java:1191)
at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1669)
at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1547)
at org.springframework.util.ClassUtils.forName(ClassUtils.java:266)
at org.springframework.beans.factory.xml.DefaultNamespaceHandlerResolver.resolve(DefaultNamespaceHandlerResolver.java:124)
这一点大家要注意。
5 关于附件源代码
文章中服务器端程序和客户端程序的源代码都放在了笔者github的网站里面,其中:
服务器端程序位于:
https://github.com/yuhaidong/WebServiceServer
客户端程序位于:
https://github.com/yuhaidong/WebServiceClient
文章来源:飞利信软件中心于海东
文章评论