成都心情

  BlogJava :: 首页 ::  :: 联系 :: 聚合  :: 管理 ::
  98 随笔 :: 2 文章 :: 501 评论 :: 1 Trackbacks
    很久没写原创文章了。今天奉献给大家的是关于 Web Service 方面的文章。说起来惭愧,关于 Web Service,我从大二的时候就开始关注了,那时在做一套学生管理系统,可能是好奇,可能是图新鲜,可能是被跨平台所吸引,在还没弄得很清楚的情况下就迷恋上了这种技术,抱着李维的《Delphi 6/Kylix 2 SOAP/Web Service程序设计篇》狂啃,到了大三也没作出个像样的东西:(。大四上学期,签到 AUO 实习,并在 AUO 做毕设,毕设选题还是 Web Service 方面,论文洋洋洒洒写了一大篇,结果,到了最后的程序实现时,仅仅是以 XML 格式进行数据库和 Web 页面的交互而已。(再惭愧一次)
   
    重新捡起 Web Service 是去年的事情,当时评估了多种开源 SSO 实现,总觉得不是很方便,遂打算自己实现。为了使通用性更高,决定让 Web Service 完成。并很自然的选到了 Axis。
   
    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>

    为了完成自动序列化/反序列化,我们使用“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序列化/反序列化器开发指南


请注意!引用、转贴本文应注明原作者:Rosen Jiang 以及出处:http://www.blogjava.net/rosen
posted on 2006-01-28 20:37 Rosen 阅读(3066) 评论(6)  编辑  收藏 所属分类: Java EE 服务器端

评论

# re: 与 Axis 1.x 同行 2006-02-13 09:59 david.turing
AXIS很不错,我倒是在XML签名的时候用到它。
呵呵,你的SSO方案似乎对WS情有独钟,兄弟有没有搞过SAML,似乎很多j2ee厂商都将或者已经支持它了:)  回复  更多评论
  

# re: 与 Axis 1.x 同行 2006-02-13 23:28 Rosen
呵呵,图灵兄光临寒舍,热烈欢迎!是的,我对 WS 很关心,这也算是历史原因造成的:) SAML 是什么我还没了解,不过 SAML 看样子还很受欢迎。  回复  更多评论
  

# re: 与 Axis 1.x 同行[未登录] 2007-05-14 10:28 aa
搂主能讲讲<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>每一项的具体含义吗?  回复  更多评论
  

# re: 与 Axis 1.x 同行 2007-05-14 11:43 Rosen
@aa
第一行说明了暴露的服务名和调用方式。
第二行是暴露的可调用的方法,*代表服务中所有方法都可调用。
第三行是服务的具体类路径。
第四、五行是要自动序列化的对象(JavaBean、Bean、VO),用于传输。  回复  更多评论
  

# re: 与 Axis 1.x 同行 2007-10-25 15:18 有猫相伴的日子
楼主的做法,我不敢赞同!!!!!!!!!!!!!!!
第一:axis对象序列化是一个非常麻烦的消耗时间的问题。
第二:我不提倡用命令来生成wsdd的配置,wsdd的配置相对来说简单可以自己编写。
第三:webservice最终目的是跨平台,我认为应该使用不同平台的公共类型。
第四:我认为webservice加上json的结合效率会非常高。

有不同意见者,可以找我讨论

  回复  更多评论
  

# re: 与 Axis 1.x 同行 2007-10-25 17:25 Rosen
@有猫相伴的日子
就这几个问题,我做一解释。
1、耗时,我同意,你的意思是利用json做序列化吧?
2、这个怎么说呢,如果一直在从事WS开发的人肯定很熟悉,但我不是这样的人。
3、这个观点我同意,不过在这个应用中,当时并没有牵涉到跨平台。
4、json在写作本文的时候,我还不知道这个格式。
另外,axis绝对不是java实现WS的唯一途径,但对于xFire,我尚未评估。  回复  更多评论
  


只有注册用户登录后才能发表评论。


网站导航: