基于Axis的自定义对象序列化

时间:2022-10-13 15:57:43

这是篇好文章,好就好在有二个对象,不会误解

SOAP、WSDL、UDDI,这些名词相信只要了解过 Web Service 的都不陌生,根据 Apache 的定义,Axis 是一种 W3C SOAP 实现,国内有些介绍还特别注明了:Axis 并不完全是 SOAP 引擎,它还包括独立的 SOAP 服务器、嵌入 Servlet 引擎的服务器、支持 WSDL 并提供转化 WSDL 为 Java 类的工具、例子程序、TCP/IP 数据包监视工具,等等。Axis 部署 Web Serive 有两种方式,最简单的是拷贝 java 源代码文件到 web 文件夹下把扩展名改为 .jws 直接调用,可参考这篇文章: 用Axis 1.1 for Java进行Web Services开发(1)。另一种方式是通过 WSDD(Web Services描述文档)部署,可参考: 使用Axis发布简单的Web服务。在我的应用中,使用的是后者,以便 Axis 进行自动序列化/反序列化处理。        实现一次 SSO 登陆验证,最少要传入用户名、密码。为了达到这种目的,在客户端我们构造 User 对象(本文中 User 对象仅包含用户名和密码),并通过 Axis 自动序列化传递出去;到了 SSO 端,Axis 自动反序列化之后还原成 User 对象;最后返回给客户端说明本次登陆的结果,返回的结果不仅仅包含例如“登陆成功”之类的简单信息,也许还有很多其他信息,看来创建一个叫做 Respond 的对象(本文中 Respond 对象仅包含登陆 ID 和结果描述)很有必要了,把 Respond 传回给客户端说明登陆结果。        暴露给客户端供登陆验证的服务类是 AuthService。该类代码简单表示如下: public class AuthService {    /**       * 验证用户名和密码       * @param String userName    用户名       * @param String passWord    密码       * @return Respond        登陆验证后返回           */    public Respond login(User user){            String name = user.getName();            String password = user.password();        //进行数据库验证        //基于Axis的自定义对象序列化基于Axis的自定义对象序列化..        //基于Axis的自定义对象序列化基于Axis的自定义对象序列化        Respond respond = new Respond();        respond.setId("123");        respond.setDesc("登陆成功");        return respond;    }}    User 和 Respond 以及服务类都写好了。通过命令行方式,我生成了 server-config.wsdd,内容如下: <?xml version="1.0" encoding="UTF-8"?><deployment xmlns="http://xml.apache.org/axis/wsdd/" xmlns:java="http://xml.apache.org/axis/wsdd/providers/java"> <globalConfiguration>  <parameter name="sendMultiRefs" value="true"/>  <parameter name="disablePrettyXML" value="true"/>  <parameter name="adminPassword" value="admin"/>  <parameter name="attachments.Directory" value="D:/workspace/SSO/web/WEB-INF/attachments"/>  <parameter name="dotNetSoapEncFix" value="true"/>  <parameter name="enableNamespacePrefixOptimization" value="true"/>  <parameter name="sendXMLDeclaration" value="true"/>  <parameter name="sendXsiTypes" value="true"/>  <parameter name="attachments.implementation" value="org.apache.axis.attachments.AttachmentsImpl"/>  <requestFlow>   <handler type="java:org.apache.axis.handlers.JWSHandler">    <parameter name="scope" value="session"/>   </handler>   <handler type="java:org.apache.axis.handlers.JWSHandler">    <parameter name="scope" value="request"/>    <parameter name="extension" value=".jwr"/>   </handler>  </requestFlow> </globalConfiguration> <handler name="LocalResponder" type="java:org.apache.axis.transport.local.LocalResponder"/> <handler name="URLMapper" type="java:org.apache.axis.handlers.http.URLMapper"/> <handler name="Authenticate" type="java:org.apache.axis.handlers.SimpleAuthenticationHandler"/> <service name="AuthService" provider="java:RPC">  <parameter name="allowedMethods" value="*"/>  <parameter name="className" value="com.cdmcs.sso.AuthService"/>  <beanMapping languageSpecificType="java:sso.Respond" qname="ns:resp" xmlns:ns="urn:BeanService"/>  <beanMapping languageSpecificType="java:sso.User" qname="ns:user" xmlns:ns="urn:BeanService"/> </service> <service name="AdminService" provider="java:MSG">  <parameter name="allowedMethods" value="AdminService"/>  <parameter name="enableRemoteAdmin" value="false"/>  <parameter name="className" value="org.apache.axis.utils.Admin"/>  <namespace>http://xml.apache.org/axis/wsdd/</namespace> </service> <service name="Version" provider="java:RPC">  <parameter name="allowedMethods" value="getVersion"/>  <parameter name="className" value="org.apache.axis.Version"/> </service> <transport name="http">  <requestFlow>   <handler type="URLMapper"/>   <handler type="java:org.apache.axis.handlers.http.HTTPAuthHandler"/>  </requestFlow>  <parameter name="qs:list" value="org.apache.axis.transport.http.QSListHandler"/>  <parameter name="qs:wsdl" value="org.apache.axis.transport.http.QSWSDLHandler"/>  <parameter name="qs.list" value="org.apache.axis.transport.http.QSListHandler"/>  <parameter name="qs.method" value="org.apache.axis.transport.http.QSMethodHandler"/>  <parameter name="qs:method" value="org.apache.axis.transport.http.QSMethodHandler"/>  <parameter name="qs.wsdl" value="org.apache.axis.transport.http.QSWSDLHandler"/> </transport> <transport name="local">  <responseFlow>   <handler type="LocalResponder"/>  </responseFlow> </transport></deployment>     要说明的是,深究上述配置文件具体含义不是本文的目的,要对其具体了解,请参考 Axis 文档。其中,只有下面的 XML 才是我们感兴趣的:

 <service name="AuthService" provider="java:RPC">  <parameter name="allowedMethods" value="*"/>  <parameter name="className" value="com.cdmcs.sso.AuthService"/>  <beanMapping languageSpecificType="java:sso.Respond" qname="ns:resp" xmlns:ns="urn:BeanService"/>

  <beanMapping languageSpecificType="java:sso.bo.User" qname="ns:user" xmlns:ns="urn:BeanService"/> </service>

注:sso.Respond   为要注册的类,全路径和类名

为了完成自动序列化/反序列化,我们使用“beanMapping”元素指定要进行处理的 bean 文件。只有在 WSDD 中定义了这些,才能享受到 Axis 带来的自动序列化/反序列化优势。        客户端代码:

public class TestClient {    public static void main(String[] args) {        try {            String endpoint = "http://127.0.0.1:8080/services/AuthService?wsdl";            Service service = new Service();            Call call = (Call) service.createCall();            QName qn = new QName("urn:BeanService","resp");            QName qx = new QName("urn:BeanService","user");            //注册 bean            call.registerTypeMapping(Respond.class,qn,new BeanSerializerFactory(Respond.class, qn),new BeanDeserializerFactory(Respond.class, qn));            call.registerTypeMapping(User.class,qx,new BeanSerializerFactory(User.class, qx),new BeanDeserializerFactory(User.class, qx));            call.setTargetEndpointAddress(new java.net.URL(endpoint));            call.setOperationName(new QName("http://soapinterop.org/","login"));            User user = new User();            mul.setName("test");            mul.setPassword("test");            Respond respond = (Reopond) call.invoke(new Object[] {user});            System.out.println("登陆,返回'" + respond.getDesc() + "'。");        } catch (Exception e) {                e.printStackTrace();        }    }}     正如我们期望的,打印出“登陆成功”。通过上面的范例,我们发现,Axis 的自动序列化/反序列化机制还是很方便的,除了 bean 以外,其他类型的对象也可以让 Axis 来完成,具体参考 Axis 文档,如果要传递的对象 Axis 未提供自动序列化/反序列化支持,请考虑人工实现,参考: 深度编程Axis序列化/反序列化器开发指南