一、環境準備
1 、從axis網站下載相關內容:http: //apache.justdn.org/ws/axis/1_3/
2 、解壓後,參考webapps\axis,爲了使你的web應用axis開發web service,需要做的事情如下:
a. 將webapps\axis\WEB- INF\lib下的相關jar包拷貝到你自己web應用的lib目錄下。另外需要activation.jar、 mail.jar兩個支持包。
b.修改web.xml,加載axis的servlet。
< listener>
< listener- class > org.apache.axis.transport.http.AxisHTTPSessionListener< / listener- class >
< / listener>
< servlet>
< servlet- name> AxisServlet< / servlet- name>
< display- name> Apache- Axis Servlet< / display- name>
< servlet- class >
org.apache.axis.transport.http.AxisServlet
< / servlet- class >
< / servlet>
< servlet- mapping>
< servlet- name> AxisServlet< / servlet- name>
< url- pattern> / servlet/ AxisServlet< / url- pattern>
< / servlet- mapping>
< servlet- mapping>
< servlet- name> AxisServlet< / servlet- name>
< url- pattern> * .jws< / url- pattern>
< / servlet- mapping>
< servlet- mapping>
< servlet- name> AxisServlet< / servlet- name>
< url- pattern> / services/* < / url- pattern>
< / servlet- mapping>
二、開發service
服務器端的service爲普通的java類:com.hnisi.axis.BookOrder
public class BookOrder {
public String getName(String name) {
System.out.println("start execute ..." );
return "book name: " + name;
}
public Book setPrice(Book book){
book.setPrice(10 );
return book;
}
}
com.hnisi.axis.Book爲簡單的值對象,包含兩個屬性name,price。
三、發佈service
1 、手工修改server- config.wsdd文件(在已有server- config.wsdd文件的情況下)
添加service:
< service name= "BookOrder" provider= "java:RPC" >
< parameter name= "allowedMethods" value= "*" / >
< parameter name= "className" value= "com.hnisi.axis.BookOrder" / >
< / service>
allowedMethods是調用的服務的方法,如果有多個方法的話可以用空格分開,當用* 的時候表示全部。
2 、寫deploy.wsdd文件,使用axis提供的AdminClient工具,自動生成server- config.wsdd。deploy.wsdd文件如下:
< deployment xmlns= "http://xml.apache.org/axis/wsdd/"
xmlns: java= "http://xml.apache.org/axis/wsdd/providers/java" >
< service name= "BookOrder" provider= "java:RPC" >
< parameter name= "className" value= "com.hnisi.axis.BookOrder" / >
< parameter name= "allowedMethods" value= "*" / >
< / service>
< / deployment>
deploy.wsdd文件位於/ web- inf目錄下。
使用AdminClient發佈該service,在/ web- inf目錄下新建deploy.bat文件:
set LIB_HOME= ./ lib
set CPATH= .;% LIB_HOME% \axis.jar;% LIB_HOME% \jaxrpc.jar;% LIB_HOME% \commons- logging- 1 .0 .2 .jar;% LIB_HOME%\commons- discovery- 0 .2 .jar;% LIB_HOME% \saaj.jar;% LIB_HOME% \activation.jar;% LIB_HOME% \mail.jar
java - classpath % CPATH% org.apache.axis.client.AdminClient - lhttp: //localhost:8080/test/services/AdminService deploy.wsdd
pause
執行deploy.bat,會生成server- config.wsdd文件。成功生成的幾個必要條件:
a. axis相關jar包存在於/ web- inf/ lib下
b. 你的tomcat必須啓動,同時留意deploy.bat文件的第三行"http://localhost:8080/test/services/AdminService" ,根據具體情況修改。
否則會報"java.net.ConnectException: Connection refused: connect" 異常。
綜合上述,在第一次發佈service的情況下,需用方式2 生成server- config.wsdd,後續開發過程中,使用方式1 直接修改server-config.wsdd文件。
發佈後,執行http: //localhost:8080/test/services,能看到當前web應用的所有web service.
http: //localhost:8080/test/services/BookOrder?wsdl 爲ServerService對應WSDL.
還可以通過IE瀏覽器直接調用服務,方法是在服務URL後加"method=xxx" ,其中xxx是要調用的方法名稱:
http: //localhost:8080/test/services/BookOrder?method=getName&name=HH
四、調用service
有兩種方式可以調用service。
1 、使用org.apache.axis.client.Call直接調用
package com.hnisi.axis;
import org.apache.axis.client.Call;
import org.apache.axis.client.Service;
public class CallService {
public static void main(String[] args) {
try {
String endpoint = "http://localhost:8080/test/services/BookOrder" ;
Service service = new Service();
Call call = (Call) service.createCall();
call.setTargetEndpointAddress( new java.net.URL(endpoint) );
call.setOperationName("getName" );
String ret = (String) call.invoke(new Object[] {"yehailong" });
System.out.println("return value is " + obj[0 ]);
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
2 、根據wsdl生成客戶端java代碼
在/ web- inf目錄下新建make.bat文件:
set LIB_HOME= ./ lib
set CPATH= .;% LIB_HOME% \axis.jar;% LIB_HOME% \jaxrpc.jar;% LIB_HOME% \commons- logging- 1 .0 .2 .jar;% LIB_HOME%\commons- discovery- 0 .2 .jar;% LIB_HOME% \saaj.jar;% LIB_HOME% \activation.jar;% LIB_HOME% \mail.jar;% LIB_HOME%\wsdl4j- 1 .5 .1 .jar;% LIB_HOME% \log4j- 1 .2 .6 .jar;./ classes
java - classpath % CPATH% org.apache.axis.wsdl.WSDL2Java - p com.hnisi.axis.client http://192.168.3.42:8080/test/services/BookOrder?wsdl
pause
生成java代碼在包com.hnisi.axis.client下面,封裝了調用的接口。
然後,使用以上生成的java代碼,編寫調用service的測試類com.hnisi.axis.client.CallService:
package com.hnisi.axis.client;
public class CallService {
public static void main(String[] args) {
try {
BookOrderService service = new BookOrderServiceLocator();
BookOrder_PortType client = service.getBookOrder();
String retValue = client.getName("zhangsan" );
System.out.println(retValue);
} catch (Exception e) {
System.err.println("Execution failed. Exception: " + e);
}
}
}
五、對象的序列化和返序列化
在以上代碼的基礎上,試圖調用BookOrder的setPrice服務,會報這樣的異常:
faultString: java.io.IOException: No serializer found for class com.hnisi.axis.Book in registry
由於SOAP中值的類型就是XML Schema中的基本類型,默認只支持簡單類型和數組。所以在進行對象傳遞的過程中,需要進行序列化和反序列化。
Axis爲提供了大量的序列化/ 反序列化器,能夠基本滿足大部分應用:
1 、基本類型,如int 、double 等,轉換成基本對象類型java.lang.Integer、java.lang.Double。
2 、常用集合對象的轉換
java.util.List == > java.lang.Object[]
java.util.Vector == > java.util.Vector
3 、普通JavaBean(簡單值對象)的序列化和反序列化
首先,在web service部署端,修改server- config.wsdd文件,在具體的service配置,增加如下代碼:
< beanMapping languageSpecificType= "java:com.hnisi.axis.Book" qname= "ns1:Book"
xmlns: ns1= "urn:BeanService" / >
languageSpecificType屬性指定JavaBean類文件位置,qname屬性指定JavaBean類的名字。當然,一個service可以綁定多個bean對象。
其次,在客戶端,完成對象的註冊。
對於調用方法一中,需要新增如下代碼以完成註冊:
QName qn = new QName("urn:BeanService" ,"Book" );
call.registerTypeMapping(Book.class , qn,
new BeanSerializerFactory(Book.class , qn),
new BeanDeserializerFactory(Book.class , qn));
而對於調用方法二,重新根據wsdl生成java代碼,已完成必要的對象註冊過程,CallService中可以直接傳遞Book對象了。
4 、複雜java對象的序列化
需要自行開發一個序列化/ 反序列化器,請參考http: //kb.csdn.net/java/Articles/200506/73d6aea4-0d38-4e21-a188-473790c9ef57.html
六、axis和spring的集成
spring容器管理的業務層服務bean,可以做爲web service發佈。整合的方法有兩種:
1 、直接發佈
將spring容器中預定義的service直接做爲web service對外發布。
爲此,web服務的提供類必須有spring管理,在調用web服務時需要從web應用環境(ServletContext)中去獲取服務類的bean實例。
具體的實現原理請參考http: //blog.csdn.net/liumyong/archive/2004/12/09/210043.aspx
2 、間接發佈
spring業務層servcie不直接做爲web service對外發布,提供一箇中間的接口(類)來調用spring service。
對外發布成web service的接口需要從Axis的contextAxis得到Spring的contextSpring:
HttpServlet servlet = (HttpServlet) MessageContext.getCurrentContext().getProperty(HTTPConstants.MC_HTTP_SERVLET);
ApplicationContext context = WebApplicationContextUtils.getWebApplicationContext(servlet.getServletContext());
以上兩種方式各有優缺點:
方式1 :
需要繼承擴展axis的相關代碼,重載實現org.apache.axis.transport.http.AxisServlet,並提供一個 SpringBeanProvider類來處理web service bean與spring service bean的關聯。
優點是,spring service直接做爲web service發佈,直接配置,無需任何附加中間接口。
方式2 :
需要爲每個web service提供一箇中間接口來調用spring service。
在單一的spring service不能滿足web服務需求時,可使用中間接口類綜合調用多個spring service,然後集中做爲一個web service發佈出去。
綜合上述,在實際的開發過程中,結合具體的應用靈活採取
七、Document/ Literal 樣式
前文所使用的都是RPC/ ENCODED樣式發佈service,axis根據一定的規則完成JAVA對象和XML文件的轉化,即序列化和反序列化過程。
採用此方式,發佈和調用的過程都很簡單,服務發佈方和調用方都是直接面向JAVA對象,而其缺點也相當明顯:
客戶端需要使用服務器端的輔助JAVA對象(儘管這些JAVA代碼可以自動根據WSDL生成),服務提供者和客戶之間的緊密耦合,任何對接口的更改都會導致服務和客戶間聯繫的中斷。
Document樣式和上面的RPC樣式最主要的不同就是,前者中客戶在一個規範的XML文檔中向服務器發送服務參數,而代替了後者中的一組離散的方法的參數值。這使得Document樣式比RPC樣式有更加鬆散的耦合關係。
Web服務提供者處理規範的XML文檔,執行操作並向客戶端作出響應,返回的也是一個規範的XML文檔。在服務器對象(參數,方法調用等)和XML數據值之間並沒有一種直接的映射關係。應用程序負責映射XML數據值。
Document樣式中SOAP消息在它的SOAP體中包含了一個或者更多的XML文檔。協議並沒有約束文檔需要如何組織構成;這完全是在程序級處理的。另外,Document樣式web服務遵循異步處理範例。
八、安全性問題
參考《實現安全的AXIS Web服務》。
九、開發工具
1 、ant支持
2 、eclipse wtp
http://yangzb.iteye.com/blog/256890