首先到CXF官网及spring官网下载相关jar架包,这个不多说。webservice是干嘛用的也不多说。
模拟新增一个用户,并返回新增结果,成功还是失败。
大概的目录如上,很简单。
ResultInfo.java
package com.fei.webservice.user.bean;
import java.text.MessageFormat;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlType;
import javax.xml.bind.annotation.XmlAccessType;
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "ResultInfo", namespace = "http://bean.user.webservice.fei.com/")
public class ResultInfo {
@XmlAttribute(required = true)
private String code;
@XmlAttribute
private String message;
public ResultInfo(){
super();
}
public ResultInfo(String code,String message){
super();
this.code = code;
this.message = message;
}
public String getCode() {
return code;
}
public String getMessage() {
return message;
}
public void setCode(String code) {
this.code = code;
}
public void setMessage(String message) {
this.message = message;
}
@Override
public String toString() {
return MessageFormat
.format("[code={0},message={1}]",
code,
message);
}
}
package com.fei.webservice.user;
import javax.jws.WebParam;
import javax.jws.WebService;
import com.fei.webservice.user.bean.ResultInfo;
@WebService
public interface IUserService {
ResultInfo createUser(
@WebParam(name = "name") String name,
@WebParam(name = "password") String password);
}
UserService.java
package com.fei.webservice.user;
import javax.jws.WebService;
import com.fei.webservice.user.bean.ResultInfo;
@WebService(
endpointInterface = "com.fei.webservice.user.IUserService",
targetNamespace = "http://user.webservice.fei.com/",
serviceName = "IUserService")
public class UserService implements IUserService{
public final String SUCCESS = "0000";
public final String FAIL = "1001";
@Override
public ResultInfo createUser(String name, String password) {
//做业务
System.out.println("新增用户:name="+name+",password="+password);
//通知第三方操作结果
return new ResultInfo(SUCCESS,"用户新增成功!");
}
}
package com.fei;
import javax.xml.ws.Endpoint;
import com.fei.webservice.user.UserService;
public class ServerStart {
public static void deployService() {
System.out.println("Server start ……");
UserService service = new UserService();
String address = "http://localhost:9000/userService";
Endpoint.publish(address, service);
}
public static void main(String[] args) throws InterruptedException {
//发布WebService
deployService();
System.out.println("server ready ……");
}
}
ServerStart.java是用来发布接口的,可以理解为像tomcat那样启动后,浏览器就可以访问了。
ClientTest.java
package com.fei;
import org.apache.cxf.jaxws.JaxWsProxyFactoryBean;
import com.fei.webservice.user.IUserService;
public class ClientTest {
public static void main(String[] args) {
//调用WebService
JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();
factory.setServiceClass(IUserService.class);
factory.setAddress("http://localhost:9000/userService");
IUserService service = (IUserService) factory.create();
System.out.println("[result]" + service.createUser("张三", "1111"));
}
}
ClientTest.java模拟第三方调用接口。也就是对服务端(ServerStart.java启动的那个)是否成功,客户端和服务端的通讯是否OK。
执行ServerStart.java,看到这样的信息:
启动OK。接下来,用浏览器访问,看看是否有xml格式的内容。
访问地址:http://localhost:9000/userService?wsdl
好了,服务端OK了,我们用客户端来调用服务端的接口,看看效果。
测试方法一:
执行ClientTest.java,控制台显示如下信息:
可以看到服务端返回了一个结果对象ResultInfo给客户端,告诉客户服务端新增用户成功了。
测试方法二
使用SOUP-UI来测试,自己网上下载。
在WEB-INF下新增一个spring-cxf.xml文件(和web.xml同目录)。
contextConfigLocation
/WEB-INF/spring-cxf.xml
org.springframework.web.context.ContextLoaderListener
CXFServlet
org.apache.cxf.transport.servlet.CXFServlet
1
CXFServlet
/cxf/*
index.jsp
浏览器访问:http://localhost:8080/cxfwebserviceserver/cxf/userService?wsdl
测试也有2种方法,和上面一样,只是改变访问地址而已,这里就不重复了。
服务端代码完成,并发布之后,我们需要将接口的信息生成一个wsdl文件,给第三方,第三方拿到wsdl文件后,通过工具生成代码。
方法一:
最方便,最快捷的办法。服务端启动后,浏览器访问时,得到的信息,将网页另存为,文件的后缀用.wsdl,这样就得到wsdl文件了。
注意:用这种方法,浏览器使用IE,本人试过百度浏览器,360浏览器,网页另存时,它会将一些html的标签也搞出来了。wsdl文件是一个xml格式的文件。
推荐使用方法一,方法二生成的wsdl文件有点问题,不知道是工具的问题还是代码写漏了哪些注解配置。
方法二:
使用cxf的java2wsdl.bat工具来生成。
简单点的:
将classes文件下的com全部copy到cxf工具的bin目录下。cmd打开DOS窗口切换到bin目录下,然后使用命令
java2wsdl -cp ./com com.fei.webservice.user.IUserService
自动生成了IUserServiceService.wsdl文件。
麻烦点的:
1.打包,将代码打包成jar
在桌面上生成一个userservice.jar包,把该包copy到java2wsdl.bat的同目录下.cmd开打DOS窗口,切换到java2wsdl.bat目录下。执行命令:
java2wsdl -cp .\userservice.jar com.fei.webservice.user.IUserService
然后在目录下,会生成一个IUserService.wsdl文件。
生成了wsdl文件,交给第三方之前,最好验证一下,使用它能否正确生成代码。
1.
用记事本或者浏览器打开查看wsdl文件,拉到最后,看看wsdl:port name那里是否和通过
http://localhost:8080/cxfwebserviceserver/cxf/userService?wsdl访问得到的一致。
上面介绍wsdl文件的生成用了2中方法。方法一通过IE浏览器的另存为得到wsdl文件,我命名为userService.wsdl.方法二通过java2wsdl自动生成的wsdl文件为IUserServiceService.wsdl.
查看userService.wsdl
上面红色框圈住的部分是我们期待的。
接下来查看IUserServiceService.wsdl文件
发现居然不是我们期待的,本人暂时找不到原因,为何导致这样。我们就暂时使用方法一来生成wsdl文件吧
2.
通过wsdl2java.bat工具,生成客户端源码,看看能否正确生成。
cmd打开DOS窗口,切换到wsdl2java.bat目录下,使用命令:
wsdl2java -client -server -impl .\userService.wsdl
在同目录下,会生成代码
为了方便,查看生成的代码的结构,我新建一个java项目,把新生成的代码copy进去。
我们来看看图上用箭头指向的那个类。
package com.fei.webservice.user;
import java.net.MalformedURLException;
import java.net.URL;
import javax.xml.namespace.QName;
import javax.xml.ws.Service;
import javax.xml.ws.WebEndpoint;
import javax.xml.ws.WebServiceClient;
import com.fei.webservice.user.IUserService;
/**
* This class was generated by Apache CXF (incubator) 2.0.4-incubator
* Sat Jun 28 15:05:37 CST 2014
* Generated source version: 2.0.4-incubator
*
*/
@WebServiceClient(name = "IUserService", targetNamespace = "http://user.webservice.fei.com/", wsdlLocation = "file:./userService.wsdl")
public class IUserService_Service extends Service {
public final static URL WSDL_LOCATION;
public final static QName SERVICE = new QName("http://user.webservice.fei.com/", "IUserService");
public final static QName UserServicePort = new QName("http://user.webservice.fei.com/", "UserServicePort");
static {
URL url = null;
try {
url = new URL("file:./userService.wsdl");
} catch (MalformedURLException e) {
System.err.println("Can not initialize the default wsdl from file:./userService.wsdl");
// e.printStackTrace();
}
WSDL_LOCATION = url;
}
public IUserService_Service(URL wsdlLocation) {
super(wsdlLocation, SERVICE);
}
public IUserService_Service(URL wsdlLocation, QName serviceName) {
super(wsdlLocation, serviceName);
}
public IUserService_Service() {
super(WSDL_LOCATION, SERVICE);
}
/**
*
* @return
* returns UserServicePort
*/
@WebEndpoint(name = "UserServicePort")
public IUserService getUserServicePort() {
return (IUserService)super.getPort(UserServicePort, IUserService.class);
}
}
@WebServiceClient(name = "IUserService", targetNamespace = "http://user.webservice.fei.com/"
@WebEndpoint(name = "UserServicePort")
特别是UserServicePort一定要和用浏览器访问服务端时界面显示的那个一样(上面截图中用红色框圈住的那个wsdl:port name = "UserServicePort")
把wsdl文件给第三方之前,一定要确保wsdl文件是没问题的,生成出来的代码也是OK的。所以把wsdl文件给第三方之前还有最后一步要做。验证wsdl生成的代码是否可用.
看到上面给的目录结构图了吗?我新曾了org.fei.service.UserService.java以及UserServiceTest.java
UserService.java
package org.fei.service;
import java.net.URL;
import com.fei.webservice.user.IUserService;
import com.fei.webservice.user.IUserService_Service;
import com.fei.webservice.user.bean.ResultInfo;
public class UserService {
private final static String _URL = "http://localhost:8080/cxfwebserviceserver/cxf/userService?wsdl";
//wsdl生成的接口
private IUserService userService;
public UserService() {
try {
userService = new IUserService_Service(new URL(_URL)).getUserServicePort();
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException("用户接口初始化连接出错!",e);
}
}
public boolean addUser(String name,String password){
boolean isSuccess = false;
try {
ResultInfo result = userService.createUser(name, password);
if("0000".equals(result.getCode())){
isSuccess = true;
System.out.println("新增用户操作结果:成功!");
}else{
isSuccess = false;
System.out.println("新增用户操作结果:失败!");
}
} catch (Exception e) {
e.printStackTrace();
isSuccess = false;
}
return isSuccess;
}
}
package org.fei.service;
public class UserServiceTest {
public static void main(String[] args) {
UserService userService = new UserService();
userService.addUser("张三", "123");
}
}
到这一步,就可以放心把wsdl文件给对方了。
作为服务端,我们需要把wsdl文件给第三方,并告知我们的访问地址,如本例访问地址:http://localhost:8080/cxfwebserviceserver/cxf/userService?wsdl
例子源码下载
CXF代码生成wsdl,wsdl生成代码工具下载