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进行编辑,在<deployment>标签下插入如下片断

<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的传输需要如何对它进行serializingde-serializing,说明的目的在于绑定JavaBean的对象类别。注意标签中说明的名字空间。这个标签其实是如下标签的一个简写:

<typeMapping qname="myNs:Student" xmlns:ns="urn:StudentInfoService"
             languageSpecificType="java: com.kevinGQ.service.axis.model.Student "
             serializer="org.apache.axis.encoding.ser.BeanSerializerFactory "
             deserializer=" org.apache.axis.encoding.ser.BeanDeserializerFactory "
             encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>

 

 

c. 把编译好的Student.class  GetStudentService.class(在它们各自的包内) 放到axis/WEB-INF/classes/.

 

4、启动Tomcat, 访问http://localhost:8080/axis/admin.html,查看你部署的服务

 

5、编写客户端

我是在Eclipse里完成代码的编写,编译及运行需要把axis-1_1/lib/ 除了axis_ant.jar7jar文件导入到classpath.

package com.kevinGQ.service.axis.client;
 
import java.net.URL;
 
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.XMLType;
import org.apache.axis.encoding.ser.BeanDeserializerFactory;
import org.apache.axis.encoding.ser.BeanSerializerFactory;
 
import com.kevinGQ.service.axis.model.Student;
 
public class GetAStudentClient {
       public static void main(String [] args) throws Exception
    {
              Service service = new Service();
        Call call = (Call) service.createCall();
        QName qn = new QName("urn:StudentInfoService","Student");
        call.registerTypeMapping(Student.class,qn,
                      new BeanSerializerFactory(Student.class, qn),
                            new BeanDeserializerFactory(Student.class, qn)
        );
        try{
               call.setTargetEndpointAddress(new URL("http://localhost:8080/axis/services/StudentService"));
               call.setOperationName(new QName("StudentInfoService","getAStudent"));
               call.addParameter("arg1",XMLType.XSD_STRING, ParameterMode.IN);
               call.setReturnClass(Student.class);
               Student a = (Student) call.invoke(new Object[]{"a"});
               System.out.println(a.getId());
        }catch(Exception e) {
            System.out.println( "Error : " + e.toString());
        }       
    }
}

 

红色代码部分表明任意的一个字符串,因为getAStudent方法的参数对返回的结果没有影响,这里只是象征性的传递一个参数。加粗的部分是需要在Client端说明要serializede-serializeJavaBean类别,参数的说明可参考axis api 文档。

要得到运行的结果,客户端这边需要得到Student.class文件,可是如果对于一个不在本机的服务,如何得到这个Student.class呢?——你需要阅读一下这个WebServicewsdl文档,里面有对这个JavaBean对象中各个域的说明,根据JavaBean的编码规范,你自己编写编译就得到了Student.class文件。

 

二、稍微深入

我想得到的是一个Student的数组怎么办呢?

你只有稍做修改:

1、服务端的一个新类 StudentLib.java

package com.kevinGQ.service.axis.model;
 
import java.util.ArrayList;
 
public class StudentLib {
       ArrayList studentLib = null;
      
       public StudentLib(){
              studentLib = new ArrayList();
       }
      
       public void addStudent(Student s){
              studentLib.add(s);
       }
      
       public ArrayList getStudents(String name, String id){
              ArrayList list = new ArrayList();
              for(int i = 0; i < studentLib.size(); i++){
                     if(this.get(i).getName().equals(name)
                            && this.get(i).getId().equals(id)){
                                   list.add(this.get(i));
                            }
              }
              return list;
       }
      
       public Student get(int index){
              return (Student)studentLib.get(index);
       }
}

 

这个类只不过是为了实现稍微复杂点的逻辑功能而写。注意getStudents方法返回的是ArrayList类型的引用。因为SOAP中支持的数据类型包含javaArrayList,所以用这个类型会方便很多。

 

2、扩展Service程序

package com.kevinGQ.service.axis.service;
 
import java.util.ArrayList;
 
import com.kevinGQ.service.axis.model.Student;
import com.kevinGQ.service.axis.model.StudentLib;
 
public class GetStudentService {
       public ArrayList getStudent(){
              ArrayList students = new ArrayList();
              Student a = new Student("a","10001","I'm A");
              Student b = new Student("a","10002","I'm B");
              Student c = new Student("a","10001","I'm A, I'm not C");
              StudentLib lib = new StudentLib();
              lib.addStudent(a);
              lib.addStudent(b);
              lib.addStudent(c);
             
              students = lib.getStudents("a","10001");
              return students;
       }
       public Student getAStudent(String name){
              Student a = new Student("a","10001","I'm A");
              return a;
       }
}

 

加粗的地方为添加的新的方法,我们接着要在服务端描述它

 

3、部署service

把刚才添加到server-config.wsdd的那个片断再拿出来看看,好像不用修改(只要你在allowedMethods的地方表明允许暴露的方法的是*

 

4、写个客户端看看

package com.kevinGQ.service.axis.client;
 
import java.net.URL;
import java.util.ArrayList;
 
import org.apache.axis.client.Call;
import org.apache.axis.client.Service;
import org.apache.axis.encoding.XMLType;
import org.apache.axis.encoding.ser.BeanDeserializerFactory;
import org.apache.axis.encoding.ser.BeanSerializerFactory;
 
import com.kevinGQ.service.axis.model.Student;
 
import javax.xml.namespace.QName;
import javax.xml.rpc.ParameterMode;
 
public class GetStudentClient {
      
       public static void main(String [] args) throws Exception
    {
              Service service = new Service();
        Call call = (Call) service.createCall();
        QName qn = new QName("urn:StudentInfoService","Student");
        call.registerTypeMapping(Student.class,qn,
                      new BeanSerializerFactory(Student.class, qn),
                            new BeanDeserializerFactory(Student.class, qn));
        try{
               call.setTargetEndpointAddress(new URL("http://localhost:8080/axis/services/StudentService"));
               call.setOperationName(new QName("StudentInfoService","getStudent"));
;
               call.setReturnClass(ArrayList.class);
               ArrayList result = (ArrayList) call.invoke(new Object[]{});
               for(int i = 0; i < result.size(); i++){
                      Student stu = (Student)result.get(i);
                      System.out.println(stu.getName()+" "+stu.getId()+" "+stu.getComment());
               }
        }catch(Exception e) {
            System.out.println( "Error : " + e.toString());
        }       
    }
}

 

和第一个客户端很相似吧。注意把Call返回的类型设为ArrayList,看代码中加粗部分!

结果输出了2条记录,和预期的一样。要不,你试试。

 

 

附:文中描述服务的wsdl.xml

<?xml version="1.0" encoding="UTF-8"?>
<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">
  <wsdl:types>
    <schema targetNamespace="urn:StudentInfoService" xmlns="http://www.w3.org/2001/XMLSchema">
      <import namespace="http://schemas.xmlsoap.org/soap/encoding/"/>
      <complexType name="Student">
         <sequence>
           <element name="comment" nillable="true" type="xsd:string"/>
           <element name="name" nillable="true" type="xsd:string"/>
           <element name="id" nillable="true" type="xsd:string"/>
         </sequence>
      </complexType>
    </schema>
  </wsdl:types>
  <wsdl:message name="getAStudentRequest">
    <wsdl:part name="name" type="xsd:string"/>
  </wsdl:message>
  <wsdl:message name="getAStudentResponse">
    <wsdl:part name="getAStudentReturn" type="tns1:Student"/>
  </wsdl:message>
  <wsdl:message name="getStudentResponse">
    <wsdl:part name="getStudentReturn" type="soapenc:Array"/>
  </wsdl:message>
  <wsdl:message name="getStudentRequest">
  </wsdl:message>
  <wsdl:portType name="GetStudentService">
    <wsdl:operation name="getStudent">
      <wsdl:input message="impl:getStudentRequest" name="getStudentRequest"/>
      <wsdl:output message="impl:getStudentResponse" name="getStudentResponse"/>
    </wsdl:operation>
    <wsdl:operation name="getAStudent" parameterOrder="name">
      <wsdl:input message="impl:getAStudentRequest" name="getAStudentRequest"/>
      <wsdl:output message="impl:getAStudentResponse" name="getAStudentResponse"/>
    </wsdl:operation>
  </wsdl:portType>
  <wsdl:binding name="StudentInfoServiceSoapBinding" type="impl:GetStudentService">
    <wsdlsoap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/>
    <wsdl:operation name="getStudent">
      <wsdlsoap:operation soapAction=""/>
      <wsdl:input name="getStudentRequest">
        <wsdlsoap:body encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" namespace="http://service.axis.service.kevinGQ.com" use="encoded"/>
      </wsdl:input>
      <wsdl:output name="getStudentResponse">
        <wsdlsoap:body encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" namespace="http://localhost:8080/axis/services/StudentInfoService" use="encoded"/>
      </wsdl:output>
    </wsdl:operation>
    <wsdl:operation name="getAStudent">
      <wsdlsoap:operation soapAction=""/>
      <wsdl:input name="getAStudentRequest">
        <wsdlsoap:body encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" namespace="http://service.axis.service.kevinGQ.com" use="encoded"/>
      </wsdl:input>
      <wsdl:output name="getAStudentResponse">
        <wsdlsoap:body encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" namespace="http://localhost:8080/axis/services/StudentInfoService" use="encoded"/>
      </wsdl:output>
    </wsdl:operation>
  </wsdl:binding>
  <wsdl:service name="GetStudentServiceService">
    <wsdl:port binding="impl:StudentInfoServiceSoapBinding" name="StudentInfoService">
      <wsdlsoap:address location="http://localhost:8080/axis/services/StudentInfoService"/>
    </wsdl:port>
  </wsdl:service>
</wsdl:definitions>

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值