SOAP 中复杂类型 (JavaBean) 调用实例实践
使用工具: axis-1_1
Tomcat 5.2.x
IDE: Eclipse 3.1
一、 简单开始:
1 、创建一个 JavaBean 类 Student.java
package com.kevinGQ.service.axis.model;
import java.io.Serializable;
public class Student implements Serializable{
private String _name;
private String _id;
private String _comment;
public Student(){}
public Student(String name, String id, String comment){
_name = name;
_id = id;
_comment = comment;
}
public String getName(){
return _name;
}
public void setName(String name){
_name = name;
}
public String getId(){
return _id;
}
public void setId(String id){
_id = id;
}
public String getComment(){
return _comment;
}
public void setComment(String comment){
_comment = comment;
}
}
2 、写 Service 程序
package com.kevinGQ.service.axis.service;
import com.kevinGQ.service.axis.model.Student;
public class GetStudentService {
public Student getAStudent(String name){
Student a = new Student("a","10001","I'm A");
return a;
}
}
3 、部署 axis 及部署 service
a. 从 axis-1_1.zip 中将 axis-1_1/webapps/axis 文件夹拷贝到 Tomcat 5.0.x/webapps/
b. 打开 webapps/axis/WEB-INF/server-config.wsdd 进行编辑,在
1<deployment> 标签下插入如下片断
2
3<service name="StudentInfoService" provider="java:RPC">
4<parameter name="className" value="com.kevinGQ.service.axis.service.GetStudentService"></parameter>
5<parameter name="allowedMethods" value="*"></parameter>
6<beanmapping languagespecifictype="java:com.kevinGQ.service.axis.model.Student" qname="myNS:Student" xmlns:myns="urn:StudentInfoService"></beanmapping>
7</service>
8
9片断中 StudentInfoService 是这个 web service 的名字,在客户端编码的时候需要用到。
10
11<parameter name="className" value="com.kevinGQ.service.axis.service.GetStudentService"></parameter>
12
13中说明了这个服务提供的类,包括 package 的完整类名。
14
15<parameter name="allowedMethods" value="*"></parameter> 中说明这个服务中可供给外部调用的方法有哪些, * 表示全部函数,现在也可以把 * 改成 getAStudent.
16
17<beanmapping languagespecifictype="java:com.kevinGQ.service.axis.model.Student" qname="myNS:Student" xmlns:myns="urn:StudentInfoService"></beanmapping> 中说明对于这个 JavaBean 的传输需要如何对它进行 serializing 和 de-serializing ,说明的目的在于绑定 JavaBean 的对象类别。注意标签中说明的名字空间。这个标签其实是如下标签的一个简写:
18
19<typemapping deserializer=" ` ` ` org.apache.axis.encoding.ser.BeanDeserializerFactory ` " encodingstyle="http://schemas.xmlsoap.org/soap/encoding/" languagespecifictype="java: com.kevinGQ.service.axis.model.Student " qname="myNs:Student" serializer=" ` org.apache.axis.encoding.ser.BeanSerializerFactory ` " xmlns:ns="urn:StudentInfoService"></typemapping>
20
21c. 把编译好的 Student.class 和 GetStudentService.class (在它们各自的包内) 放到 axis/WEB-INF/classes/.
22
234 、启动 Tomcat, 访问 http://localhost:8080/axis/admin.html ,查看你部署的服务
24
255 、编写客户端
26
27我是在 Eclipse 里完成代码的编写,编译及运行需要把 axis-1_1/lib/ 除了 axis_ant.jar 外 7 个 jar 文件导入到 classpath.
28
29package com.kevinGQ.service.axis.client;
30
31import java.net.URL;
32
33import javax.xml.namespace.QName;
34
35import javax.xml.rpc.ParameterMode;
36
37import org.apache.axis.client.Call;
38
39import org.apache.axis.client.Service;
40
41import org.apache.axis.encoding.XMLType;
42
43import org.apache.axis.encoding.ser.BeanDeserializerFactory;
44
45import org.apache.axis.encoding.ser.BeanSerializerFactory;
46
47import com.kevinGQ.service.axis.model.Student;
48
49public class GetAStudentClient {
50
51public static void main(String [] args) throws Exception
52
53{
54
55Service service = new Service();
56
57Call call = (Call) service.createCall();
58
59QName qn = new QName("urn:StudentInfoService","Student");
60
61**call.registerTypeMapping(Student.class,qn, **
62
63** new BeanSerializerFactory(Student.class, qn), **
64
65** new BeanDeserializerFactory(Student.class, qn) **
66
67** ); **
68
69try{
70
71call.setTargetEndpointAddress(new URL("http://localhost:8080/axis/services/StudentService"));
72
73call.setOperationName(new QName("StudentInfoService","getAStudent"));
74
75call.addParameter("arg1",XMLType.XSD_STRING, ParameterMode.IN);
76
77call.setReturnClass(Student.class);
78
79Student a = (Student) call.invoke( new Object[]{"a"} );
80
81System.out.println(a.getId());
82
83}catch(Exception e) {
84
85System.out.println( "Error : " + e.toString());
86
87}
88
89}
90
91}
92
93红色代码部分表明任意的一个字符串,因为 getAStudent 方法的参数对返回的结果没有影响,这里只是象征性的传递一个参数。加粗的部分是需要在 Client 端说明要 serialize 和 de-serialize 的 JavaBean 类别,参数的说明可参考 axis api 文档。
94
95要得到运行的结果,客户端这边需要得到 Student.class 文件,可是如果对于一个不在本机的服务,如何得到这个 Student.class 呢?——你需要阅读一下这个 WebService 的 wsdl 文档,里面有对这个 JavaBean 对象中各个域的说明,根据 JavaBean 的编码规范,你自己编写编译就得到了 Student.class 文件。
96
97二、 稍微深入
98
99我想得到的是一个 Student 的数组怎么办呢?
100
101你只有稍做修改:
102
1031 、服务端的一个新类 StudentLib.java
104
105package com.kevinGQ.service.axis.model;
106
107import java.util.ArrayList;
108
109public class StudentLib {
110
111ArrayList studentLib = null;
112
113public StudentLib(){
114
115studentLib = new ArrayList();
116
117}
118
119public void addStudent(Student s){
120
121studentLib.add(s);
122
123}
124
125public ArrayList getStudents(String name, String id){
126
127ArrayList list = new ArrayList();
128
129for(int i = 0; i < studentLib.size(); i++){
130
131if(this.get(i).getName().equals(name)
132
133&& this.get(i).getId().equals(id)){
134
135list.add(this.get(i));
136
137}
138
139}
140
141return list;
142
143}
144
145public Student get(int index){
146
147return (Student)studentLib.get(index);
148
149}
150
151}
152
153这个类只不过是为了实现稍微复杂点的逻辑功能而写。注意 getStudents 方法返回的是 ArrayList 类型的引用。因为 SOAP 中支持的数据类型包含 java 中 ArrayList ,所以用这个类型会方便很多。
154
1552 、扩展 Service 程序
156
157package com.kevinGQ.service.axis.service;
158
159import java.util.ArrayList;
160
161import com.kevinGQ.service.axis.model.Student;
162
163import com.kevinGQ.service.axis.model.StudentLib;
164
165public class GetStudentService {
166
167**public ArrayList getStudent(){ **
168
169** ArrayList students = new ArrayList(); **
170
171** Student a = new Student("a","10001","I'm A"); **
172
173** Student b = new Student("a","10002","I'm B"); **
174
175** Student c = new Student("a","10001","I'm A, I'm not C"); **
176
177** StudentLib lib = new StudentLib(); **
178
179** lib.addStudent(a); **
180
181** lib.addStudent(b); **
182
183** lib.addStudent(c); **
184
185** **
186
187** students = lib.getStudents("a","10001"); **
188
189** return students; **
190
191** } **
192
193public Student getAStudent(String name){
194
195Student a = new Student("a","10001","I'm A");
196
197return a;
198
199}
200
201}
202
203加粗的地方为添加的新的方法,我们接着要在服务端描述它
204
2053 、部署 service
206
207把刚才添加到 server-config.wsdd 的那个片断再拿出来看看,好像不用修改(只要你在 allowedMethods 的地方表明允许暴露的方法的是 * )
208
2094 、写个客户端看看
210
211package com.kevinGQ.service.axis.client;
212
213import java.net.URL;
214
215import java.util.ArrayList;
216
217import org.apache.axis.client.Call;
218
219import org.apache.axis.client.Service;
220
221import org.apache.axis.encoding.XMLType;
222
223import org.apache.axis.encoding.ser.BeanDeserializerFactory;
224
225import org.apache.axis.encoding.ser.BeanSerializerFactory;
226
227import com.kevinGQ.service.axis.model.Student;
228
229import javax.xml.namespace.QName;
230
231import javax.xml.rpc.ParameterMode;
232
233public class GetStudentClient {
234
235public static void main(String [] args) throws Exception
236
237{
238
239Service service = new Service();
240
241Call call = (Call) service.createCall();
242
243QName qn = new QName("urn:StudentInfoService","Student");
244
245call.registerTypeMapping(Student.class,qn,
246
247new BeanSerializerFactory(Student.class, qn),
248
249new BeanDeserializerFactory(Student.class, qn));
250
251try{
252
253call.setTargetEndpointAddress(new URL("http://localhost:8080/axis/services/StudentService"));
254
255call.setOperationName(new QName("StudentInfoService","getStudent"));
256
257;
258
259**call.setReturnClass(ArrayList.class); **
260
261ArrayList result = (ArrayList) call.invoke(new Object[]{});
262
263for(int i = 0; i < result.size(); i++){
264
265Student stu = (Student)result.get(i);
266
267System.out.println(stu.getName()+" "+stu.getId()+" "+stu.getComment());
268
269}
270
271}catch(Exception e) {
272
273System.out.println( "Error : " + e.toString());
274
275}
276
277}
278
279}
280
281和第一个客户端很相似吧。注意把 Call 返回的类型设为 ArrayList ,看代码中加粗部分!
282
283结果输出了 2 条记录,和预期的一样。要不,你试试。
284
285附:文中描述服务的 wsdl.xml
286<?xml version="1.0" encoding="UTF-8"?>
287<wsdl:definitions targetnamespace=" http://localhost:8080/axis/services/StudentInfoService " xmlns:apachesoap=" http://xml.apache.org/xml-soap " xmlns:impl=" http://localhost:8080/axis/services/StudentInfoService " xmlns:intf=" http://localhost:8080/axis/services/StudentInfoService " xmlns:soapenc=" http://schemas.xmlsoap.org/soap/encoding/ " xmlns:tns1="urn:StudentInfoService" xmlns:wsdl=" http://schemas.xmlsoap.org/wsdl/ " xmlns:wsdlsoap=" http://schemas.xmlsoap.org/wsdl/soap/ " xmlns:xsd=" http://www.w3.org/2001/XMLSchema ">
288<wsdl:types>
289<schema targetnamespace="urn:StudentInfoService" xmlns=" http://www.w3.org/2001/XMLSchema ">
290<import namespace=" http://schemas.xmlsoap.org/soap/encoding/">
291<complextype name="Student">
292<sequence>
293<element name="comment" nillable="true" type="xsd:string"></element>
294<element name="name" nillable="true" type="xsd:string"></element>
295<element name="id" nillable="true" type="xsd:string"></element>
296</sequence>
297</complextype>
298</import></schema>
299</wsdl:types>
300<wsdl:message name="getAStudentRequest">
301<wsdl:part name="name" type="xsd:string"></wsdl:part>
302</wsdl:message>
303<wsdl:message name="getAStudentResponse">
304<wsdl:part name="getAStudentReturn" type="tns1:Student"></wsdl:part>
305</wsdl:message>
306<wsdl:message name="getStudentResponse">
307<wsdl:part name="getStudentReturn" type="soapenc:Array"></wsdl:part>
308</wsdl:message>
309<wsdl:message name="getStudentRequest">
310</wsdl:message>
311<wsdl:porttype name="GetStudentService">
312<wsdl:operation name="getStudent">
313<wsdl:input message="impl:getStudentRequest" name="getStudentRequest"></wsdl:input>
314<wsdl:output message="impl:getStudentResponse" name="getStudentResponse"></wsdl:output>
315</wsdl:operation>
316<wsdl:operation name="getAStudent" parameterorder="name">
317<wsdl:input message="impl:getAStudentRequest" name="getAStudentRequest"></wsdl:input>
318<wsdl:output message="impl:getAStudentResponse" name="getAStudentResponse"></wsdl:output>
319</wsdl:operation>
320</wsdl:porttype>
321<wsdl:binding name="StudentInfoServiceSoapBinding" type="impl:GetStudentService">
322<wsdlsoap:binding style="rpc" transport=" http://schemas.xmlsoap.org/soap/http">
323<wsdl:operation name="getStudent">
324<wsdlsoap:operation soapaction=""></wsdlsoap:operation>
325<wsdl:input name="getStudentRequest">
326<wsdlsoap:body encodingstyle=" http://schemas.xmlsoap.org/soap/encoding/ " namespace=" http://service.axis.service.kevinGQ.com " use="encoded"></wsdlsoap:body>
327</wsdl:input>
328<wsdl:output name="getStudentResponse">
329<wsdlsoap:body encodingstyle=" http://schemas.xmlsoap.org/soap/encoding/ " namespace=" http://localhost:8080/axis/services/StudentInfoService " use="encoded"></wsdlsoap:body>
330</</wsdl:output></wsdl:operation></wsdlsoap:binding></wsdl:binding></wsdl:definitions></deployment>