從客戶端除了傳遞字符串以外還可以傳遞復雜對象(對象必須序列化了),List,Map,數組和文件。
(1)定義一個對象實現了serializable 接口
package cn.com.chenlly.ssh.webservice.axis;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
public class Address implements Serializable { //復雜類型的類要序列化
private Integer identifier;
private String address;
private String city;
private String province;
private String country;
private String []array; //javabean里的復雜類型
private List<Integer> list;(基本類型)
private boolean isExst;
//constructor
public Address(){
list = new ArrayList<Integer>();
list.add(1);
list.add(2);
list.add(3);
}
public Integer getIdentifier() {
return identifier;
}
public void setIdentifier(Integer identifier) {
this.identifier = identifier;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public String getProvince() {
return province;
}
public void setProvince(String province) {
this.province = province;
}
public String getCountry() {
return country;
}
public void setCountry(String country) {
this.country = country;
}
public String[] getArray() {
return array;
}
public void setArray(String[] array) {
this.array = array;
}
public List<Integer> getList() {
return list;
}
public void setList(List<Integer> list) {
this.list = list;
}
public boolean isExst() {
return isExst;
}
public void setExst(boolean isExst) {
this.isExst = isExst;
}
}
(2)定義server-config.wsdd文件
<deployment xmlns="http://xml.apache.org/axis/wsdd/"
xmlns:java="http://xml.apache.org/axis/wsdd/providers/java">
<handler name="URLMapper" //定義了兩個handler(非必須),類似於過濾器
type="java:org.apache.axis.handlers.http.URLMapper" />
<handler name="wsTestHandler"
type="java:cn.com.chenlly.ssh.webservice.axis.WSTestServiceHandle">
<parameter name="status" value="success" />
</handler>
<!-- 自定義服務 -->
<service name="ws" provider="java:RPC">
<parameter name="className"
value="cn.com.chenlly.ssh.webservice.axis.WSTestServiceImpl" />
<parameter name="allowedMethods" value="*" />
<parameter name="scope" value="request" />
<responseFlow>
<handler type="wsTestHandler" /> //響應時使用上面的handler
</responseFlow>
<requestFlow>//請求時使用上面的handler
<handler type="wsTestHandler" />
</requestFlow>
<beanMapping qname="myNSD:Address" //復雜類型javabean(用於傳送的序列化對象)
xmlns:myNSD="urn:AddressManager"
languageSpecificType="java:cn.com.chenlly.ssh.webservice.axis.Address">
</beanMapping>
</service>
<transport name="http">
<requestFlow>
<handler type="URLMapper" />
</requestFlow>
</transport>
</deployment>
//主要是<beanMapping>標簽中名字空間和qname寫法 |
生成的WSDL有如下一段
- <schema targetNamespace="urn:AddressManager" xmlns="http://www.w3.org/2001/XMLSchema">
<import namespace="http://192.168.1.98:8082/SSHProject/services/ws" />
<import namespace="http://xml.apache.org/xml-soap" />
<import namespace="http://schemas.xmlsoap.org/soap/encoding/" />
- <complexType name="Address">
- <sequence>
<element name="address" nillable="true" type="soapenc:string" />
<element name="array" nillable="true" type="impl:ArrayOf_soapenc_string" />
<element name="city" nillable="true" type="soapenc:string" />
<element name="country" nillable="true" type="soapenc:string" />
<element name="exst" type="xsd:boolean" />
<element name="identifier" nillable="true" type="soapenc:int" />
<element name="list" nillable="true" type="impl:ArrayOf_xsd_anyType" />
<element name="province" nillable="true" type="soapenc:string" />
</sequence>
</complexType>
</schema>
這個新的schema就是把對象序列化以后生成了xml流文件。
(3) webService 服務方法
public Address dealAddress(Address address) {
System.out.println("service exst:"+address.isExst());
//客戶端對象傳遞過來設置標志為true
address.setExst(true);
return address;
}
(4) 客戶端
package cn.com.chenlly.ssh.webservice.axis;
import java.util.ArrayList;
import java.util.List;
import javax.xml.namespace.QName;
import javax.xml.rpc.ParameterMode;
import org.apache.axis.client.Call;
import org.apache.axis.client.Service;
import org.apache.axis.encoding.ser.BeanDeserializerFactory;
import org.apache.axis.encoding.ser.BeanSerializerFactory;
public class WSTestServiceClient {
public static void main(String[] args) {
Service service = new Service();
try {
Call call = (Call) service.createCall();
String url = "http://192.168.1.98:8082/SSHProject/services/ws?wsdl";
call.setTargetEndpointAddress(new java.net.URL(url));
//定義對象
Address address = new Address();
address.setIdentifier(1);
address.setProvince("湖南");
address.setCity("長沙");
address.setExst(false);
QName qn = new QName("urn:AddressManager", "Address");//第一個參數名字空間URI,第二個參數本地部分,注意這兩部分在server-config.wsdd文件中標簽beanMapping配置
call.registerTypeMapping(Address.class, qn,
new BeanSerializerFactory(Address.class, qn),//序列化
new BeanDeserializerFactory(Address.class, qn));
call.setOperationName(new QName(url,"dealAddress"));
call.addParameter("arg0", qn, ParameterMode.IN);//定義一個參數類型,如果是String類型的參數可以不需要這句話
call.setReturnClass(Address.class);//指定返回類型
Address result = (Address) call.invoke(new Object[]{address});//這里傳遞給service的是一個對象
System.out.println(result.isExst());
} catch (Exception e) {
e.printStackTrace();
}
}
}
//在服務器端打印的isExst()方法是false;然后設置address的exst為true;最后又傳送到客戶端打印的result結果為true
<beanMapping/> 需要說明的是: 1 如果服務中不需要傳遞對象,是不需要<beanMapping/>對的.而且這里面的對象必須要是符合javaBean模式的對象,最起碼要符合get/set方法對. 2 qname xmlns:xx languageSpecificType分別用於指定參數對象的命名空間.用於在客戶端調用. |
二、開發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>
原因: 由於SOAP中值的類型就是XML Schema中的基本類型,默認只支持簡單類型和數組。所以在進行對象傳遞的過程中,需要進行序列化和反序列化。 Axis為提供了大量的序列化/反序列化器,能夠基本滿足大部分應用: 其次,在客戶端,完成對象的注冊。
|
1)axis1.2內在支持的幾種對象類型。 2)簡單的javabean對象類型。所有的field都是上面提到的基本類型 由於MyBean是一個自定義的JavaBean對象, 所以在server-config.wsdd中就必須加上<beanMapping ...../>的聲明, 讓axis知道怎么把request中xml數據deserialize為MyBean對象,又如何把MyBean對象serialize為xml數據作為response.用wtp自動為JavaInputService生成的wsdl中, MyBean是作為一個complexType在wsdl中定義的。 3)復雜一點的JavaBean對象。 4)java中的數組 在webservice中把List, Map作為service的input, output的做法都是不可行的。至少在jdk1.4的版本中是這樣的。 要注意的是,數組參數在server-config.wsdd中需要配置<arrayMapping.../> 似乎List, Map的問題用數組就可以解決了。事實上就是如此。但是還得注意的是: |
例子:
<service name="StudentInfoService" provider="java:RPC">
<parameter name="className" value="com.kevinGQ.service.axis.service.GetStudentService"/>
<parameter name="allowedMethods" value="*"/>
<beanMapping qname="myNS:Student" xmlns:myNS="urn:StudentInfoService" languageSpecificType="java:com.kevinGQ.service.axis.model.Student"/>
</service>
片斷中StudentInfoService是這個web service的名字,在客戶端編碼的時候需要用到。
<parameter name="className" value="com.kevinGQ.service.axis.service.GetStudentService"/>
中說明了這個服務提供的類,包括package的完整類名。
<parameter name="allowedMethods" value="*"/>中說明這個服務中可供給外部調用的方法有哪些,*表示全部函數,現在也可以把*改成getAStudent.
<beanMapping qname="myNS:Student" xmlns:myNS="urn:StudentInfoService" languageSpecificType="java:com.kevinGQ.service.axis.model.Student"/>中說明對於這個JavaBean的傳輸需要如何對它進行serializing和de-serializing,說明的目的在於綁定JavaBean的對象類別。注意標簽中說明的名字空間。這個標簽其實是如下標簽的一個簡寫:
Java代碼
1 <typeMapping qname="myNs:Student" xmlns:ns="urn:StudentInfoService"
2 languageSpecificType="java: com.kevinGQ.service.axis.model.Student "
3 serializer="org.apache.axis.encoding.ser.BeanSerializerFactory "
4 deserializer=" org.apache.axis.encoding.ser.BeanDeserializerFactory "
5 encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
特別說明: A、 如果你調用的方法有返回值,一定要設置返回值的類型。call.setReturnClass B、 如果你調用的方法有參數,一定要設置參數的類型call.addParameter C、 記得添加wsdl4j.jar,序列化轉換的時候需要用到,否則會出現找不到類型異常 如: call.addParameter("i", XMLType.XSD_INT, ParameterMode.IN); |