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。该类代码简单表示如下:
User 和 Respond 以及服务类都写好了。通过命令行方式,我生成了 server-config.wsdd,内容如下:
要说明的是,深究上述配置文件具体含义不是本文的目的,要对其具体了解,请参考 Axis 文档。其中,只有下面的 XML 才是我们感兴趣的:
正如我们期望的,打印出“登陆成功”。通过上面的范例,我们发现,Axis 的自动序列化/反序列化机制还是很方便的,除了 bean 以外,其他类型的对象也可以让 Axis 来完成,具体参考 Axis 文档,如果要传递的对象 Axis 未提供自动序列化/反序列化支持,请考虑人工实现,参考: 深度编程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;
}
}
/**
* 验证用户名和密码
* @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 >
< 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();
}
}
}
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序列化/反序列化器开发指南。