复杂对象类型的WebService高级部分
2013-08-03 12:26
441 查看
从客户端除了传递字符串以外还可以传递复杂对象(对象必须序列化了),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>
生成的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
二、开发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>
例子:
<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/"/>
(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写法 第一个你自定义的命名空间和第二个节点本地部分会组成一个新的QName。 |
- <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为普通的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、基本类型,如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对象了。 |
1)axis1.2内在支持的几种对象类型。 这几种内在支持的对象包括: java基本类型 : int, float,,,, 基本类型包装类 : Integer, Float, Long... 还有String, Date, Calendar, BigDecimal, BigInteger, List, Map. 凡是这些内在支持的对象, 不管他们作为某个Service的input 还是 output, 我们在服务端的axis1.2的WEB-INF/server-config.wsdd的该Service的定义中都不需要加入 <beanMapping>或者是<typeMapping>的声明。 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对象。 比如JavaBean对象中的一些field又是自定义的JavaBean, 这种情况下, wsdl中生成的complextype会有多个(webservice接口最好不用定义多层的结构),而在wsdd定义的<beanMapping .../>也会有多个, axis1.2支持起来都是易如反掌。 4)java中的数组 在webservice中把List, Map作为service的input, output的做法都是不可行的。至少在jdk1.4的版本中是这样的。 要注意的是,数组参数在server-config.wsdd中需要配置<arrayMapping.../> 似乎List, Map的问题用数组就可以解决了。事实上就是如此。但是还得注意的是: javabean里边也不能含有List?. 如果MyBean跟其它某个对象是1:n的关系,那么也只能写成数组的形式,而不能是List的形式 |
<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); call.setReturnClass(User[].class); |
相关文章推荐
- 三、 复杂对象类型的WebService
- WebService-AXIS高级特性 传递复杂对象
- 三、CXF WebService中传递复杂类型对象
- 四、CXF WebService中传递复杂类型对象
- 三、 复杂对象类型的WebService
- 四、CXF WebService中传递复杂类型对象
- 四、CXF WebService中传递复杂类型对象
- 三、 复杂对象类型的WebService
- 四、CXF WebService中传递复杂类型对象
- CXF WebService中传递复杂类型对象
- CXF WebService中传递复杂类型对象 .
- WebService(3)-AXIS高级特性 传递复杂对象
- CXF WebService中传递复杂类型对象
- 四、CXF WebService中传递复杂类型对象
- 四、CXF WebService中传递复杂类型对象
- 通讯转换工具开发_webservice储值卡项目总结之webservice复杂对象类型
- JavaScript高级程序设计之引用类型之单体内置对象之Math对象第5.7.2讲笔记
- Javascript高级程序设计第3章回顾总结部分--数据类型
- 掌握 Ajax,第 3 部分: Ajax 中的高级请求和响应 全面理解 HTTP 的状态代码、就绪状态和 XMLHttpRequest 对象
- 【转】【翻译】实体框架中的POCO支持 - 第二部分 - 复杂类型,延迟装载和显式装载