因爲即將在項目中使用到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.……錯誤。