在前一篇转载的关于cxf webservice的实现思路中向大家介绍了实现webservice的思路,但并没有给出具体的实现代码,在本文中我将通过介绍借助于spring实现webservice的方式,在本文中同时将向大家介绍在我实现的过程中遇到的一些问题。
1.搭建webservice服务端:
(1.1)新建java web工程,同时在web.xml中进行spring的相关配置,如下:
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
<servlet>
<servlet-name>cxfService</servlet-name>
<servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>cxfService</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/classes/spring/spring.xml
</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
</web-app>
(1.2)相关spring文件的具体内容,spring.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:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<import resource="spring-util-cxf-server.xml" />
</beans>
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:jaxws="http://cxf.apache.org/jaxws" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.1.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" />
<bean id="personService" class="server.WSServiceImpl" />
<bean id="inMessageInterceptor" class="com.tgb.lk.util.cxf.server.CxfMessageInterceptor">
<constructor-arg value="receive" />
</bean>
<bean id="outLoggingInterceptor" class="org.apache.cxf.interceptor.LoggingOutInterceptor" />
<!-- 注意下面的address,这里的address的名称就是访问的WebService的name -->
<jaxws:server id="personWsServer" serviceClass="server.WSService"
address="/changshou">
<jaxws:serviceBean>
<!-- 要暴露的 bean 的引用 -->
<ref bean="personService" />
</jaxws:serviceBean>
<jaxws:inInterceptors>
<ref bean="inMessageInterceptor" />
</jaxws:inInterceptors>
<jaxws:outInterceptors>
<ref bean="outLoggingInterceptor" />
</jaxws:outInterceptors>
</jaxws:server>
</beans>
(1.3)创建相关类,自定义拦截器MyInterceptor.java
package interceptor;
import org.apache.cxf.interceptor.Fault;
import org.apache.cxf.message.Message;
import org.apache.cxf.phase.AbstractPhaseInterceptor;
public class MyInterceptor extends AbstractPhaseInterceptor<Message> {
// 至少要一个带参的构造函数
public MyInterceptor(String phase) {
super(phase);
}
/**
* 自定义消息拦截器
*/
public void handleMessage(Message message) throws Fault {
System.out.println("############handleMessage##########");
System.out.println(message);
if (message.getDestination() != null) {
System.out.println(message.getId() + "#"
+ message.getDestination().getMessageObserver());
}
if (message.getExchange() != null) {
System.out.println(message.getExchange().getInMessage() + "#"
+ message.getExchange().getInFaultMessage());
System.out.println(message.getExchange().getOutMessage() + "#"
+ message.getExchange().getOutFaultMessage());
}
}
}
实体对象User:
package com.hoo.entity;
import java.io.Serializable;
public class User implements Serializable {
private static final long serialVersionUID = 677484458789332877L;
private int id;
private String name;
private String email;
private String address;
@Override
public String toString() {
return this.id + "#" + this.name + "#" + this.email + "#" + this.address;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public static long getSerialversionuid() {
return serialVersionUID;
}
}
实体对象Users
package com.hoo.entity;
import java.util.HashMap;
import java.util.List;
public class Users {
private List<User> users;
private User[] userArr;
private HashMap<String, User> maps;
public List<User> getUsers() {
return users;
}
public void setUsers(List<User> users) {
this.users = users;
}
public User[] getUserArr() {
return userArr;
}
public void setUserArr(User[] userArr) {
this.userArr = userArr;
}
public HashMap<String, User> getMaps() {
return maps;
}
public void setMaps(HashMap<String, User> maps) {
this.maps = maps;
}
}
创建Webservice接口,WSService.java:
package server;
import javax.jws.WebParam;
import javax.jws.WebService;
import javax.jws.soap.SOAPBinding;
import javax.jws.soap.SOAPBinding.Style;
import com.hoo.entity.User;
import com.hoo.entity.Users;
@WebService
@SOAPBinding(style = Style.RPC)
public interface WSService {
public void sayHello(String username);
/*********传递复杂对象begin***********/
public User getUserByName(@WebParam(name = "name") String name);
public void setUser(User user);
public Users getUsers(int i);
public void setUsers(Users users);
/**********传递复杂对象end*************/
}
创建Webservice接口的实现类,WSServiceImpl.java
package server;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import javax.jws.WebParam;
import javax.jws.WebService;
import javax.jws.soap.SOAPBinding;
import javax.jws.soap.SOAPBinding.Style;
import com.hoo.entity.User;
import com.hoo.entity.Users;
@WebService
@SOAPBinding(style = Style.RPC)
public class WSServiceImpl implements WSService {
@Override
public void sayHello(String username) {
System.out.println(username);
}
public User getUserByName(@WebParam(name = "name") String name) {
User user = new User();
user.setId(new Date().getSeconds());
user.setName(name);
user.setAddress("cangzhou");
user.setEmail(name + "@163.com");
return user;
}
public void setUser(User user) {
System.out.println("############Server setUser###########");
System.out.println("setUser:" + user);
}
public Users getUsers(int i) {
List<User> users = new ArrayList<User>();
for (int j = 0; j <= i; j++) {
User user = new User();
user.setId(new Date().getSeconds());
user.setName("jack#" + j);
user.setAddress("china");
user.setEmail("jack" + j + "@hoo.com");
users.add(user);
}
Users u = new Users();
u.setUsers(users);
return u;
}
public void setUsers(Users users) {
System.out.println("############Server setUsers###########");
for (User u : users.getUsers()) {
System.out.println("setUsers:" + u);
}
}
}
将此项目放在tomcat中进行发布,然后通过发布地址测试该webservice是否发布成功,结果如下:
看到此图片证明我们的webservice发布成功,接下来的就让我们搭建客户端对这个webservice进行访问。
2.搭建webservice客户端,如果想在客户端对webservice进行访问我们需要得到webservice发布的接口,这个类我们可以通过jdk自带的命令通过wsdl地址进行导入,具体操作如下:
打开命令窗口,输入如下命令:wsimport -d h: -keep -verbose http://localhost:8080/YCHWebServiceServer/changshou?wsdl,回车即可生成webservice中的相关类(本命令将导出的类放在h盘下的server文件夹中),然后将这些类放入到客户端中,生成的类如下:
新建一个普通的java项目,新建类Client.java,代码如下:
package client;
import org.apache.cxf.jaxws.JaxWsProxyFactoryBean;
import client.WSService;
public class Client {
public static void main(String[] args){
JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();
factory.setServiceClass(WSService.class);
//factory.setAddress("http://localhost:8080/YCHWebServiceServer/changshou/changshou");
factory.setAddress("http://localhost:8080/YCHWebServiceServer/changshou");
WSService service = (WSService) factory.create();
/*******sayHello()*******/
//service.sayHello("xxxx");
/*******getUserByName()方法********/
User user = service.getUserByName("yangchangshou");
// System.out.println(user.getAddress());
// System.out.println(user.getEmail());
// System.out.println(user.getId());
// System.out.println(user.getName());
// System.out.println(user.getClass());
/*******setUser()方法********/
// user.setAddress("China-Guangzhou");
// service.setUser(user);
/*******getUsers()方法********/
Users users = service.getUsers(4);
for(User u : users.getUsers()){
System.out.println(u.getName());
}
}
}
然后将通过wsdl生成的类放入到与Client.java类同目录下:
注意无论是在服务端还是在客户端都要导入与CXF相关的jar包,运行Client类中的main()方法,我们可以看到输出结果如下:
通过输出结果我们就完成了对webservice的调用。在做本实例的过程中遇到了一个很让人头疼的问题,其实也算不上是什么大问题,由于我在刚开始的时候将web.xml文件中的cxfservice的url-pattern设置成了/changshou/*,而在spring-util-cxf-server.xml文件中我将访问webservice的name定义成了/changshou,实际的放我那地址应该是:http://http://localhost:8080/YCHWebServiceServer/changshou/changshou,而我在客户端的代码中一直使用http://localhost:8080/YCHWebServiceServer/changshou,这样总是报错,错误信息如下:
导致我找了很长时间才找到解决办法,原来真正的访问地址应该是web.xml文件中配置的cxfservice的url-pattern + spring-util-cxf-server.xml文件中的<jaxws:server>标签中的address属性值,也就是如果在web.xml文件中配置的是/*, spring-util-cxf-server.xml文件中配置的是/changshou,那么webservice的地址应该是:http://localhost:8080/YCHWebServiceServer/changshou,而如果web.xml文件中配置的是/changshou/*,那么webservice的地址则应该是:http://localhost:8080/YCHWebServiceServer/changshou/changshou,希望能对遇到同样问题的兄弟有所帮助。