之前使用Dubbo搞过WebService,不过鉴于Dubbo在其他公司使用不频繁,于是开始学习目前比较流程的WebService框架,备选是Axis2,CXF。。,最后还是选择了CXF,据说CXF在某些方面比Axis2效率高些,不管啦,反正都是apache的,一通百通。
好啦,废话不多说,正式开始,个人总结而已。
首先CXF版本问题,一般来说,都是选择比较稳定的版本,公司目前JDK用的1.6,所以不能使用3.0以上的版本,3.0以上的CXF不支持1.7以下的了。
所以开发版本选择的是2.7.17,下载链接 http://www.apache.org/dyn/closer.lua/cxf/2.7.17/apache-cxf-2.7.17.zip
电脑Maven抽风了,所以用的Web Project,使用Maven的无视上面链接,去找maven依赖
一,导入所以jar(或加入CXF,Spring的maven依赖)
二、目录结构如下(本机测试:客户端和服务端都在一个工程下面,有时间的可以搞两个项目依赖来访问)
User:实体类
HelloWorld:webService提供的接口
HelloWorldImpl:接口实现类
User.java
package com.test.domain;
import java.io.Serializable;
public class User implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
private String id;
private String name;
private String age;
private String description;
public User() {
super();
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAge() {
return age;
}
public void setAge(String age) {
this.age = age;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
}
HelloWorld.java
package com.test.service;
import java.util.List;
import javax.jws.WebParam;
import javax.jws.WebService;
import com.test.domain.User;
@WebService(targetNamespace = "http://service.test.com/", name = "HelloWorld")
public interface HelloWorld {
String sayHi(@WebParam(name="text")String text);
String sayHiToUser(@WebParam(name="user")User user);
String[] SayHiToUserList(@WebParam(name="userList")List<User> userList);
}
@WebService:表示这个是Webservice接口, 通过这个注解,后面cxf框架才会将这个普通的Java接口类发布为webservice服务
targetNamespace : 指定你想要的命名空间,默认是http://该接口包名的反缀,如上所示,不写效果一样
name : 默认是该类的类名,同样可以不写
@WebParam:参数的别名,不用该注解的话,wsdl2java自动生成的代码,默认参数名是arg0,arg1….(可能只是为了别人看名字就能看懂你的参数而已)
HelloWorldService.java
package com.test.service.impl;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import javax.jws.WebParam;
import javax.jws.WebService;
import com.test.domain.User;
import com.test.service.HelloWorld;
@WebService(
serviceName = "HelloWorld",
portName = "HelloWorldImplPort",
targetNamespace = "http://impl.service.test.com/",
endpointInterface = "com.test.client.HelloWorld")
public class HelloWorldImpl implements HelloWorld {
Map<Integer, User> users = new LinkedHashMap<Integer, User>();
public String sayHi(@WebParam(name = "text") String text) {
return "Hello,"+text;
}
public String sayHiToUser(@WebParam(name = "user")User user) {
users.put(users.size()+1, user);
return "Hello,"+user.getName();
}
public String[] SayHiToUserList(@WebParam(name = "userList")List<User> userList) {
String[] result = new String[userList.size()];
int i = 0;
for(User u:userList){
result[i] = "Hello " + u.getName();
i++;
}
return result;
}
}
serviceName=”HelloWorld” 对外发布的服务名,指定 Web Service 的服务名称:wsdl:service。缺省值为 Java 类的简单名称 + Service。(字符串)
portName : 默认是name+Port,这里没有加name=”“,因为name的默认值就是该类类名,所以其实name=HelloWorldImpl
targetNamespace : 命名空间,默认值上面有提到
endpointInterface=”com.test.service.HelloWorld” 表示该实现webservice实现类指定的接口, 服务接口全路径, 指定做SEI(Service EndPoint Interface)服务端点接口
一般实现类只需配置endpointInterface即可
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"
xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">
<display-name>cxf</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>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>WEB-INF/applicationContext.xml</param-value>
</context-param>
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
<!-- CXF servlet -->
<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>/webservice/*</url-pattern>
</servlet-mapping>
</web-app>
applicationContext.xml
<?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/jaxws
http://cxf.apache.org/schemas/jaxws.xsd">
<!-- 引入了cxf的一些框架配置,注意上面beans里面也有cxf特定的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"/>
<!-- 相当于使用Endpoint.publish()进行服务发布 -->
<jaxws:endpoint id="helloWorld" implementorClass="com.test.service.impl.HelloWorldImpl" address="/helloWorld" />
<!-- 相当于使用JaxWsServerFactoryBean进行服务发布 -->
<jaxws:server id="helloWorld2" address="/helloWorld2" serviceClass="com.test.service.impl.HelloWorldImpl"/>
</beans>
上面例举了两种发布webservice的方式,任选一种即可。
部署到tomcat,启动…
进入链接 http://localhost:8080/CXFTest/webservice/helloWorld?wsdl 或者 http://localhost:8080/CXFTest/webservice/helloWorld2?wsdl 都可以,因为两个都发布了。
如图:
webservice服务到此就发布完成了。。。
接下来就是客户端调用服务了。。。这里就采用cxf自带的命令自动生成客户端代码
首先进入cxf的bin目录,然后输入命令:
wsdl2java -frontend jaxws21 -p com.test.client -d e:\ -all http://localhost:8080/CXFTest/webservice/helloWorld?wsdl
解析一下命令:
wsdl2java 不用说,就是调用cxf命令,类似于javac
-frontend jaxws21 : jdk6最高只支持ws2.1规范版本,所以在jdk6下面生成的时候,要加上-frontend jaxws21
-p : 后面接生成类的包名
-d:后面接生成类的路径
-client 生成客户端测试web service的代码.
-server 生成服务器启动web service的代码.
-impl 生成web service的实现代码.
-ant 生成build.xml文件.
-all 生成上面-client -server -impl -ant 对应的所有文件.
最后就是webservice wsdl的路径了
建立一个工程,将e:\中的代码复制到工程src下,如图
将HelloWorld…cilent.java里面的参数改造一下,如下
package com.test.client;
/**
* Please modify this class to meet your needs
* This class is not complete
*/
import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import javax.xml.namespace.QName;
/**
* This class was generated by Apache CXF 2.7.17
* 2015-09-18T15:36:52.802+08:00
* Generated source version: 2.7.17
*
*/
public final class HelloWorld_HelloWorldImplPort_Client {
private static final QName SERVICE_NAME = new QName("http://impl.service.test.com/", "HelloWorld");
private HelloWorld_HelloWorldImplPort_Client() {
}
public static void main(String args[]) throws java.lang.Exception {
URL wsdlURL = HelloWorld_Service.WSDL_LOCATION;
if (args.length > 0 && args[0] != null && !"".equals(args[0])) {
File wsdlFile = new File(args[0]);
try {
if (wsdlFile.exists()) {
wsdlURL = wsdlFile.toURI().toURL();
} else {
wsdlURL = new URL(args[0]);
}
} catch (MalformedURLException e) {
e.printStackTrace();
}
}
HelloWorld_Service ss = new HelloWorld_Service(wsdlURL, SERVICE_NAME);
HelloWorld port = ss.getHelloWorldImplPort();
{
System.out.println("Invoking sayHiToUserList...");
java.util.List<com.test.client.User> _sayHiToUserList_userList = new ArrayList<com.test.client.User>();
for (int i = 0; i <5; i++)
{
User user = new User();
user.setName("zhangsan"+i);
_sayHiToUserList_userList.add(user);
}
java.util.List<java.lang.String> _sayHiToUserList__return = port.sayHiToUserList(_sayHiToUserList_userList);
System.out.println("sayHiToUserList.result=" + _sayHiToUserList__return);
}
{
System.out.println("Invoking sayHiToUser...");
com.test.client.User _sayHiToUser_user = new User();
_sayHiToUser_user.setName("lisi");
java.lang.String _sayHiToUser__return = port.sayHiToUser(_sayHiToUser_user);
System.out.println("sayHiToUser.result=" + _sayHiToUser__return);
}
{
System.out.println("Invoking sayHi...");
java.lang.String _sayHi_text = "wangwu";
java.lang.String _sayHi__return = port.sayHi(_sayHi_text);
System.out.println("sayHi.result=" + _sayHi__return);
}
System.exit(0);
}
}
运行,调用结果如下
说明webservice接口调用成功!
另外,自动生成的调用webservice的客户端代码有空可以研究下!
最后贴上Demo的下载地址:http://pan.baidu.com/s/1pJP6eXd