这是篇好文章,好就好在有二个对象,不会误解
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(); //进行数据库验证 //.. // 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序列化/反序列化器开发指南。