與 Axis 1.x 同行

    很久沒寫原創文章了。今天奉獻給大家的是關於 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();
        
//進行數據庫驗證
        
//dot.gifdot.gif..
        
//dot.gifdot.gif
        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 29344.html

Rosen 2006-01-28 20:37 發表評論

























發佈了0 篇原創文章 · 獲贊 0 · 訪問量 859
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章