因为即将在项目中使用到web service,所以,我提前学习了下这个东西。
不看不知道,一看吓一跳。
好久以前学习并使用过的XFire竟然已经和Celtix合并成了CXF,还出了几个版本。
看来,人还是需要经常关注技术发展的,否则,还真是要掉队了。
(废话太多了?那好吧,我开始演示我的小实验。)
首先,下载CXF,官网(http://cxf.apache.org/ ),解压后,得到以下目录。
其中,lib为jar包,在接下来的工作中需要用到。
下面,我们开始建立工程。
一、组建提供WebService的服务器端项目。
1. 在eclipse/myEclipse中建立web工程cxf2,将CXF_HOME/lib下的所有jar复制到工程的lib中,并添加到buildpath中。
2. 新建一个新POJO,为User.Java。
package server;
public class User {
String first;
String last;
public String getFirst() {
return first;
}
public void setFirst(String first) {
this.first = first;
}
public String getLast() {
return last;
}
public void setLast(String last) {
this.last = last;
}
}
3. 因为CXF提供的所有webservice都基于接口,所以,新建一个接口UserService。如下:
package server;
import javax.jws.WebService;
@WebService
public interface UserService {
void add(User user);
User[] findAllUsers();
}
其中,@WebService注解是CXF必须的,照搬吧。
4. 新建一个类UserServiceImpl.java,并实现接口UserService。如下:
package server;
import java.util.List;
import java.util.Vector;
import javax.jws.WebService;
import org.apache.log4j.Logger;
@WebService(endpointInterface = "server.UserService",serviceName = "UserService",portName="UserServicePort")
public class UserServiceImpl implements UserService {
static List<User> UserRepository= new Vector<User>();
private static Logger log = Logger.getLogger(UserServiceImpl.class);
{
log.info("CXF正在初始化 UserServiceImpl.");
}
public void add(User user) {
log.info("CXF正在添加一个用户: "+user.getFirst()+"."+user.getLast());
UserRepository.add(user);
}
public User[] findAllUsers() {
User[] users= new User[UserRepository.size()];
UserRepository.toArray(users);
return users;
}
}
这里,注解@WebService(endpointInterface = "server.UserService",serviceName = "UserService",portName="UserServicePort")与上面不一样,可以省略。
但在复杂的应用中,不能省略,如指定哪些方法可供远程调用时,需要用到注解。(个人愚见)
5.配置web.xml。
(1)在web.xml中添加CXF的配置文件定义。
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>WEB-INF/beans.xml</param-value>
</context-param>
(2)在web.xml中添加如下监听器和servlet。
<!-- 因为CXF3.0依赖于spring,需要添加这个listener-->
<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>/webServices/*</url-pattern>
</servlet-mapping>
6.建立CXF的配置文件,存放路径要与web.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">
<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="userService" implementor="server.UserServiceImpl" address="/userService" />
</beans>
经过上面步骤,我们已经完成配置了一个提供webservice的服务器。
启动tomcat,在浏览器中输入地址:http://localhost:8880/cxf2/webServices/userService,将返回一个wsdl文件(xml)。
(如果是IE,需要查看源文件来查看。如果是firefox,可以直接看到xml代码。)
更详细的访问地址为:http://localhost:8880/cxf2/webServices/userService?wsdl。
工程目录如图:
二、上面,我们已经成功配置了一个webservice服务器。接下来,我们建立另一个工程来模拟远程调用webservice。
1.新建一个工程testCxf,将上面服务器工程中的User.java和UserService.java复制到工程testCxf中。
2.新建一个类Client.java,代码如下:
package server;
import org.apache.cxf.jaxws.JaxWsProxyFactoryBean;
public class Client {
public static void main(String[] arg){
JaxWsProxyFactoryBean soapFactoryBean = new JaxWsProxyFactoryBean();
soapFactoryBean.setAddress("http://localhost:8880/cxf2/webServices/userService"); // 这个就是第一个工程完成后所测试的地址。
soapFactoryBean.setServiceClass(UserService.class);
Object o = soapFactoryBean.create();
UserService userService = (UserService) o;
User user= new User();
user.setFirst("James");
user.setLast("Bond");
userService.add(user);
User[] users= userService.findAllUsers();
for(User u : users){
System.out.println(u.getFirst()+"."+u.getLast());
}
}
}
执行这个java类,我们会看到控制台输出了相应信息。
CXF正在添加一个用户: James.Bond (这个信息为第一个工程输出)
James.Bond (这个信息为第二个工程输出)
如果运行多次,在最后一次运行后,将会看到有多个“James.Bond ”被输出。
由此,我们可以看到,服务器所提供的webservice已经被成功调用。
到此,两者的通信已经建立,你想做什么就做什么吧,尽情发挥你天马行空的创意。
工程目录如图:
需要两个工程的朋友,可以从这里下载。
http://download.csdn.net/source/2775877 (服务器端)
http://download.csdn.net/source/2775884 (客户端)
后记:
三、由于我们通常不知道提供Web Service的服务器接口及其相关类的代码,我们也不可能从他人那里获得。
对此,CXF提供了一些命令行工具,在CXF_HOME/bin下。
使用wsdl2java,可以根据从服务器返回的wsdl文件生成我们所需要的java接口和相关类。
在上面的工程中,我们可以用以下命令生成JAVA代码,而不是从第一个工程中复制过来。
wsdl2java -p client http://localhost:8880/cxf2/webServices/userService?wsdl (需要在cmd窗口中将路径切换至CXF_HOME/bin下)
(解释:wsdljava –p 包路径 –d 目标文件夹 wsdl 的url地址)
四、需要注意的是,对于接口类和相关类的包路径,一定要和服务器的一样,(可以通过第三个步骤知道包路径)
否则,会出现Unexpected wrapper element {****}addResponse found.……错误。