blog.Toby

            BlogJava :: 首頁 :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理 ::
            130 隨筆 :: 2 文章 :: 150 評論 :: 0 Trackbacks
          本文首先討論了Web服務(wù)會話狀態(tài)的保持方法,然后著重結(jié)合J2EE平臺中Web服務(wù)核心技術(shù)--JAX-RPC來介紹怎么在Web服務(wù)調(diào)用過程中保持客戶端的會話狀態(tài),并且提供了服務(wù)端和不同類型客戶端的調(diào)用實例。

          本文是J2EE Web服務(wù)開發(fā)系列文章的第九篇,本文首先討論了Web服務(wù)會話狀態(tài)的保持方法,然后著重結(jié)合J2EE平臺中Web服務(wù)核心技術(shù)--JAX-RPC來介紹怎么在Web服務(wù)調(diào)用過程中保持客戶端的會話狀態(tài),并且提供了服務(wù)端和不同類型客戶端的調(diào)用實例。

          閱讀本文前您需要以下的知識和工具:

          • J2EESDK1.4(Sun已經(jīng)發(fā)布了正式版),并且會初步使用;

          • 了解JAX-RPC的基本概念;
          • 能夠使用JAX-RPC技術(shù)開發(fā)Web服務(wù);
          • 一般的Java編程知識。

          本文的參考資料見 參考資料

          本文的全部代碼在這里 下載

          Web服務(wù)與會話


          Web服務(wù)大多基于HTTP協(xié)議,而HTTP協(xié)議是一種無狀態(tài)的協(xié)議。Web服務(wù)規(guī)范并沒有定義客戶端和服務(wù)端之間會話的保持方法。所以要在多個Web服務(wù)調(diào)用之間保持一些狀態(tài),需要使用一些額外的技術(shù)或者方法。

          我們知道,基于HTTP的應(yīng)用開發(fā)中,要在多個調(diào)用之間保持會話狀態(tài),通常可以采用以下幾種方式:

          • URL重寫,把要傳遞的參數(shù)重寫在URL中;

          • 使用Cookie,把要傳遞的參數(shù)寫入到客戶端cookie中;

          • 使用隱含表單,把要傳遞的參數(shù)寫入到隱含的表單中;

          • 使用Session,把要傳遞的參數(shù)保存在session對象中(其實Session機制基于cookie或者URL重寫)。

          上面幾個方式有一個共同點:把要傳遞的參數(shù)保存在兩個頁面都能共享的對象中,前一個頁面在這個對象中寫入狀態(tài)、后一個頁面從這個對象中讀取狀態(tài)。特別是對于使用session方式,每個客戶端在服務(wù)端都對應(yīng)了一個sessionid,服務(wù)端維持了由sessionid標識的一系列session對象,而session對象用于保持共享的信息。

          我們似乎從上面得到一些啟發(fā),是否可以在服務(wù)端標識每個Web服務(wù)客戶端,并且把它們的狀態(tài)保持在某個可以共享的位置,比如內(nèi)存、文件系統(tǒng)、數(shù)據(jù)庫。是的,許多Web服務(wù)開發(fā)工具正是這樣實現(xiàn)的。如果使用Weblogic Workshop開發(fā)Web服務(wù),它可以把Web服務(wù)的狀態(tài)保持在實體Bean中。

          如果Web服務(wù)的服務(wù)端能夠訪問HTTP會話對象,那么就可以通過HTTP會話來支持Web服務(wù)的會話。JAX-RPC就是采用了這種方式。

          如果Web服務(wù)技術(shù)或者開發(fā)工具沒有提供任何的支持,那么我們可以在服務(wù)端維持一個客戶端狀態(tài)池,這個狀態(tài)池中的對象由客戶端的id標識,客戶端在每次調(diào)用時,都使用以下格式的SOAP消息:

          												
          														<soapenv:Envelope 
          xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" 
          xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
           <soapenv:Body>
             ...
             <client-id>001sf3242x-234234</client-id>
             <call-params>… </call-param>
             <call-method>
              getLogCount
             </call-method>
           </soapenv:Body>
          </soapenv:Envelope>
          
          												
          										

          服務(wù)端接收到這個SOAP消息時,可以通過這個<client-id>來獲得對應(yīng)狀態(tài)池中的對象,然后進一步獲得客戶端預(yù)先設(shè)置的狀態(tài)信息。

          下面結(jié)合JAX-RPC技術(shù)來討論具體的實現(xiàn)方法。





          回頁首


          JAX-RPC和Web服務(wù)會話


          概念回顧:在J2EE平臺中,要開發(fā)Web服務(wù),可以使用兩種技術(shù):JAX-RPC和JAXM。而對于JAX-RPC,又有兩種不同類型的服務(wù)端點:Servlet服務(wù)端點和EJB服務(wù)端點。基于Servlet的服務(wù)端點運行在Servlet容器中,基于EJB的服務(wù)端點運行在EJB容器中。

          我們知道,Servlet可以在客戶端的多個調(diào)用之間保持會話狀態(tài),所以基于Servlet的JAX-RPC Web服務(wù)端點要保持客戶的會話狀態(tài)是可行的。但如果是EJB服務(wù)端點,由于這里的EJB是無狀態(tài)會話Bean,所以要在多個調(diào)用之間保持狀態(tài)必須通過其它機制實現(xiàn),這里不討論。

          下面從JAX-RPC的生命周期和ServletEndpointContext接口來說明怎么保持和訪問客戶端的會話狀態(tài)。

          JAX-RPC的生命周期

          根據(jù)JAX-RPC的規(guī)范,如果Web服務(wù)端點實現(xiàn)javax.xml.rpc.server.ServiceLifecycle接口,那么基于Servlet容器的JAX-RPC運行環(huán)境將管理這個端點的生命周期。javax.xml.rpc.server.ServiceLifecycle接口定義如下:

          												
          														例程1 ServiceLifecycle
          package javax.xml.rpc.server;
          public interface ServiceLifecycle {
          void init(Object context) throws ServiceException;
          void destroy();
          }
          
          												
          										

          JAX-RPC運行環(huán)境負責(zé)裝載并實例化服務(wù)端點實例,裝載和實例化可以在JAX-RPC運行環(huán)境啟動時進行,也可以在服務(wù)端點處理SOAP RPC請求時進行。JAX-RPC運行環(huán)境使用Java類裝載機制來裝載服務(wù)端點,當(dāng)成功裝載目標類后,將實例化這個類。

          當(dāng)服務(wù)端點實例化后,在RPC請求到達之前JAX-RPC運行環(huán)境將初始化它們,這個初始化通過ServiceLifecycle.init方法來進行的。在初始化的過程中,可能需要設(shè)置一些訪問外部資源的方法。在init方法中,有一個context參數(shù),它用來訪問由JAX-RPC運行環(huán)境提供的端點上下文(ServletEndpoint Context)。當(dāng)初始化服務(wù)端點后,JAX-RPC運行環(huán)境就可以把多個遠程調(diào)用派發(fā)到服務(wù)端點。在遠程方法調(diào)用的過程中,JAX-RPC服務(wù)端點并不維持任何客戶端的狀態(tài)。所以JAX-RPC服務(wù)端點實例能夠被池化(Pooling)。

          當(dāng)JAX-RPC運行環(huán)境決定移除服務(wù)端點實例時,它將調(diào)用服務(wù)端點實例的destroy方法。比如在系統(tǒng)關(guān)閉或者實例池中實例過多時,就可能發(fā)生這種操作。在destroy方法中,服務(wù)端點將釋放占用的資源。當(dāng)成功調(diào)用了destroy方法后,服務(wù)端點實例將被垃圾收集器收集。此時它不能處理任何遠程方法調(diào)用。

          ServletEndpointContext接口

          在ServiceLifecycle.init(Object context)方法中,其中參數(shù)context就是ServletEndpointContext實例,ServletEndpointContext是由JAX-RPC運行環(huán)境維持的端點上下文。JAX-RPC規(guī)范規(guī)定了基于Servlet的服務(wù)端點的編程模型,但并沒有為服務(wù)端點上下文(Endpoint Context)或者會話(Session)定義與組件模型、容器、綁定協(xié)議更通用的抽象,也就是說這些通用的抽象在JAX-RPC規(guī)范之外。

          下面是ServletEndpointContext接口的代碼。

          												
          														例程2 ServletEndpointContext接口
          package javax.xml.rpc.server;
          public interface ServletEndpointContext {
          public java.security.Principal getUserPrincipal();
          public javax.xml.rpc.handler.MessageContext getMessageContext();
          public javax.servlet.http.HttpSession getHttpSession();
          public javax.servlet.ServletContext getServletContext();
          }
          
          												
          										

          ServletEndpointContext接口對于會話的保持非常關(guān)鍵,因為它定義了getHttpSession方法,這個方法返回了和當(dāng)前活動的客戶端調(diào)用相關(guān)的HTTP會話。客戶端的會話由JAX-RPC運行環(huán)境維持。如果沒有相關(guān)的HTTP會話,那么這個方法返回null。

          除了getHttpSession方法外,這個接口還定義了或者SOAP消息上下文,Servlet上下文方法,在這里不討論了。

          有了上面的理論,下面我們來開發(fā)一個能夠使用HTTP會話的Web服務(wù)。





          回頁首


          開發(fā)服務(wù)端


          首先定義一個端點接口,它擁有幾個交互操作的方法,如例程3所示。

          												
          														例程3 定義服務(wù)端點接口
          package com.hellking.study.webservice.session;
          
          import java.rmi.Remote;
          import java.rmi.RemoteException;
          /**
           *Web服務(wù)端點接口,它定義了三個服務(wù)方法。
           */
          public interface SessionTestIF extends Remote {
              public String login(String id,String password) throws RemoteException;
              public String getLoginCount() throws RemoteException;    
              public void logout() throws RemoteException;
          }
          
          												
          										

          要想在Web服務(wù)中訪問HTTP會話,那么必須擁有ServletEndpointContext實例,而這個實例必須通過ServiceLifecycle接口的init方法獲得。也就是說,要使用HTTP會話,Web服務(wù)端點必須實現(xiàn)ServiceLifecycle接口。Web服務(wù)實現(xiàn)類如例程4所示。

          												
          														例程4 服務(wù)實現(xiàn)類
          package com.hellking.study.webservice.session;
          
          import java.rmi.Remote.*;
          import javax.xml.rpc.server.ServiceLifecycle;
          import javax.xml.rpc.server.ServletEndpointContext;
          import javax.xml.rpc.handler.soap.SOAPMessageContext;
          import java.util.Properties;
          import java.io.FileInputStream;
          import javax.servlet.http.HttpSession;
          /**
           *SessionTestImpl是Web服務(wù)實現(xiàn)類,用于測試Web服務(wù)中Session的使用。
           *由于要使用Session,需要實現(xiàn)ServiceLifecycle接口。
           */
          public class SessionTestImpl implements SessionTestIF,ServiceLifecycle{
           
           //服務(wù)端點上下文
           private ServletEndpointContext serviceContext;
              
              /**
               *ServiceLifecycle方法:初始化服務(wù)端點,或者要使用的資源。
               */
              public void init(java.lang.Object context)
              {
            serviceContext=(ServletEndpointContext)context;
           }
           /**
               *ServiceLifecycle方法:銷毀服務(wù)端點實例。
               */
              public void destroy() 
              {
               this.serviceContext=null;
              //可能還有其它釋放資源的方法。
              }
           /**
            *Web服務(wù)方法:登錄,并且保存一些信息到HTTP會話中。
            */
              public String login(String id,String password) 
              {
               String ret=null;//返回值。
               Properties users=new Properties();
               try
               {
                //獲得用戶名、密碼屬性,一般是在數(shù)據(jù)庫中,這里簡化,把這些信息保存在一個文件中。
                  users.load(com.hellking.study.webservice.session.SessionTestImpl.class
                    .getResourceAsStream("password.properties"));
               }
               catch(java.io.FileNotFoundException e)
               {
                e.printStackTrace();
               }
               catch(java.io.IOException e)
               {
                e.printStackTrace();
               }
               try
               {
                String passwd=(String)users.getProperty(id);
                if(password.equals(passwd))
                {
                 ret="登錄成功,你可以執(zhí)行其它操作!";
              HttpSession session = serviceContext.getHttpSession();
              //保存用戶會話狀態(tài),它和一般的HTTP會話一樣,都使用HttpSession來進行。
              session.setAttribute("isLogin",new Boolean(true));
              session.setAttribute("userId",id);    
              //更新登錄次數(shù),在這里省略。
                }
               }
               catch(Exception e)
               {
                ret="登錄失敗,請確認用戶名和密碼正確!";
                e.printStackTrace();
               } 
               return ret;
              }
              
              /**
               *Web服務(wù)方法:獲得登錄的次數(shù),需要使用HTTP會話來獲得當(dāng)前user的id。
               */
              public String getLoginCount() 
              {
               String ret=null;//返回值
               HttpSession session = serviceContext.getHttpSession();
                  Properties logcount=new Properties();
               try
               {
                //獲得用戶登錄次數(shù)。
                logcount.load(com.hellking.study.webservice.session.SessionTestImpl.class
                .getResourceAsStream("login.properties"));
               }
               catch(java.io.FileNotFoundException e)
               {
                e.printStackTrace();
               }
               catch(java.io.IOException e)
               {
                e.printStackTrace();
               }
               try
               {
                //從HTTP會話中獲得是否登錄的屬性。
                Boolean isLogin=(Boolean)session.getAttribute("isLogin");
                String userId=(String)session.getAttribute("userId");
                //如果已經(jīng)登錄,那么返回logcount屬性值。
                if(isLogin.equals(Boolean.TRUE))
                {      
                 ret=logcount.getProperty(userId);
                }
               }
               catch(Exception e)
               {
                e.printStackTrace();
               }
               return ret;     
              }
              /**
               *注銷,使會話無效。
               */    
              public void logout() 
              {
               HttpSession session = serviceContext.getHttpSession();
               session.invalidate();
              }        
          }
          
          												
          										

          在上面代碼中,SessionTestImpl 擁有一個ServletEndpointContext成員變量,這個成員變量在init方法初始化:

          												
          														serviceContext=(ServletEndpointContext)context;
          
          												
          										

          在login方法中,通過:

          												
          														HttpSession session = serviceContext.getHttpSession();
          
          												
          										

          方法來獲得和當(dāng)前客戶端關(guān)聯(lián)的HTTP會話,然后可以把一些交互的信息保存在session中,如:

          												
          														session.setAttribute("isLogin", new Boolean(true));
          
          												
          										

          把用戶已經(jīng)登錄的信息保存起來。在其它的Web服務(wù)方法中,如getLoginCount,可以通過:

          												
          														Boolean isLogin=(Boolean)session.getAttribute("isLogin");
          
          												
          										

          之類的方法來獲得原來保存的屬性值。





          回頁首


          編寫描述符、部署


          開發(fā)好以上兩個類后,需要進行一些相關(guān)的描述,編寫以下腳本:

          												
          														例程5 service-config.xml 
          <?xml version="1.0" encoding="UTF-8"?>
          <configuration 
            xmlns="http://java.sun.com/xml/ns/jax-rpc/ri/config">
            <service 
                name="MySessionTestService" 
                targetNamespace="urn:SessionTest" 
                typeNamespace="urn:SessionTest" 
                packageName="sessionTest">
                <interface name="com.hellking.study.webservice.session.SessionTestIF"/>
            </service>
          </configuration>
          
          												
          										

          通過:

          												
          														wscompile -define -d . -nd . -classpath . service-config.xml
          
          												
          										

          命令生成一個名為MySessionTestService.wsdl的Web服務(wù)描述文件。再通過:

          												
          														wscompile -gen -classpath . -d . -nd . -mapping mapping.xml service-config.xml
          
          												
          										

          生成一個映射文件。另外,還需要編寫幾個描述符,如webservices.xml、web.xml等,在這里就不介紹了(這些描述符可以通過部署工具自動生成,見本文代碼)。由于這個服務(wù)端點需要維持會話,所以在web.xml中特別描述了會話的保持時間,如例程6所示。

          												
          														例程6 web.xml描述符
          <?xml version="1.0" encoding="UTF-8"?>
          
          <!DOCTYPE web-app
              PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
              "http://java.sun.com/j2ee/dtds/web-app_2_3.dtd">
          
          <web-app>
            <display-name>sessionTest-jaxrpc</display-name>
            <description>A web application containing a simple JAX-RPC endpoint</description>
            <servlet>
              <servlet-name>SessionTestServletImpl</servlet-name>
              <servlet-class>com.hellking.study.webservice.session.SessionTestImpl</servlet-class>
              <load-on-startup>0</load-on-startup>
            </servlet>
            <servlet-mapping>
              <servlet-name>SessionTestServletImpl</servlet-name>
              <url-pattern>/mysessionTest</url-pattern>
            </servlet-mapping>
            <session-config>
              <session-timeout>60</session-timeout>
            </session-config>
          </web-app>
          
          												
          										

          可以看出,SessionTestServletImpl是作為Servlet運行的。為了在JAX-RPC環(huán)境啟動時就實例化這個服務(wù)端點,需要設(shè)置<load-on-startup>元素值為0。另外,<session-config>元素值指定了客戶端和JAX-RPC運行環(huán)境之間會話保持的時間。

          關(guān)于打包和部署方法在這里就不贅述了,您可以參考本系列文章《使用EJB2.1無狀態(tài)會話Bean作為Web服務(wù)端點》一文。





          回頁首


          開發(fā)客戶端


          我們知道,JAX-RPC有三種不同類型的客戶端:

          • 基于Stub;
          • 動態(tài)代理;
          • 動態(tài)調(diào)用。

          下面討論怎么在基于Stub和基于動態(tài)調(diào)用的客戶端使用Web服務(wù)會話。

          基于Stub的客戶端

          我們不得不從Stub接口的SESSION_MAINTAIN_PROPERTY屬性說起,如果在客戶端設(shè)置這個屬性為Boolean.TRUE,那么在Web服務(wù)交互過程中,服務(wù)端將維持一個HTTP會話,否則不會維持HTTP會話。基于Stub的客戶端代碼如例程7所示。

          												
          														例程7 基于Stub的客戶端
          package com.hellking.study.webservice.session;
          import javax.xml.rpc.Stub;
          /**
           *Web服務(wù)調(diào)用客戶端,測試Web服務(wù)會話。基于Stub的調(diào)用。
           */
          public class SessionTestClientUseStub
          {
            
             Stub stub;
             SessionTestIF sessionTest;
             //初始化Stub。
             public SessionTestClientUseStub()
             {
                 stub = (Stub)(new MySessionTestService_Impl().getSessionTestIFPort());
                 stub._setProperty(javax.xml.rpc.Stub.ENDPOINT_ADDRESS_PROPERTY, 
                          "http://127.0.0.1:8080/sessionTest/mysessionTest"); 
                 stub._setProperty(Stub.SESSION_MAINTAIN_PROPERTY,Boolean.TRUE);
                 sessionTest = (SessionTestIF)stub;
              }
             
              public static void main(String[] args) 
              {
            SessionTestClientUseStub test=new SessionTestClientUseStub();
            test.login();
            test.getLoginCount();
            test.logout();
                  
              }
              /**
               *登錄。
               */
              public void login()
              {
               try {           
                       System.out.println("正在登錄...");
                      System.out.println(sessionTest.login("userid-001","abc"));
                  } catch (Exception ex) {
                      ex.printStackTrace();
                  }  
             }
             /**
              *獲得logincount屬性值。
              */
             public void getLoginCount()
             {
                try
                {
                 System.out.println("LoginCount的值為:");
                 System.out.println(sessionTest.getLoginCount());
                }
                catch (Exception ex) {
                      ex.printStackTrace();
                  }
              }
              /**
               *注銷。
               */
              public void logout()
              {
             …//省略代碼
              }
          }
          
          												
          										

          在服務(wù)調(diào)用之前,通過:

          												
          														stub._setProperty(Stub.SESSION_MAINTAIN_PROPERTY,Boolean.TRUE);
          
          												
          										

          方法來設(shè)置SESSION_MAINTAIN_PROPERTY屬性。

          部署好服務(wù)端后,運行這個代碼將獲得如圖1所示的結(jié)果。



          圖1 使用會話的測試結(jié)果

          可以看出,上面的調(diào)用達到了預(yù)期的效果。因為在getLoginCount方法中并沒有傳入任何參數(shù),但獲得了前一個方法中登錄id的LoginCount值。

          如果我們屏蔽:

          												
          														stub._setProperty(Stub.SESSION_MAINTAIN_PROPERTY,Boolean.TRUE);
          
          												
          										

          代碼,或者更改為以下代碼:

          												
          														stub._setProperty(Stub.SESSION_MAINTAIN_PROPERTY,Boolean.FALSE);
          
          												
          										

          編譯后再運行這個客戶端,將獲得如圖2所示的結(jié)果。



          圖2 不使用會話的測試結(jié)果

          可以看出,這里返回的LoginCount為null,說明客戶端的會話并沒有保持。

          基于動態(tài)調(diào)用客戶端

          基于動態(tài)調(diào)用客戶端主要是通過javax.xml.rpc.Call接口來進行的。和基于Stub的客戶端一樣,也必須先設(shè)置一個屬性(Call.SESSION_MAINTAIN_PROPERTY)為Boolean.TRUE時才能使用HTTP會話。

          我們看這個客戶端的部分代碼,如例程8所示。

          												
          														例程8 基于Call的客戶端
          package com.hellking.study.webservice.session;
          
          … // imports
          /**
           *測試Web服務(wù)會話的使用
           */
          public class SessionTestClient {
              //一些調(diào)用參數(shù)。
              private static String qnameService = "MySessionTestService";
              private static String qnamePort = "SessionTestIFPort";
          
              private static String BODY_NAMESPACE_VALUE =   "urn:SessionTest";
              private static String ENCODING_STYLE_PROPERTY =
                   "javax.xml.rpc.encodingstyle.namespace.uri"; 
              private static String NS_XSD =   "http://www.w3.org/2001/XMLSchema";
              private static String URI_ENCODING =  "http://schemas.xmlsoap.org/soap/encoding/";
                   
              ServiceFactory factory;
              Service service; 
              Call call;
              QName port;
             //初始化。 
             public SessionTestClient()
             {
                  try
                  {
                    factory = ServiceFactory.newInstance();
                    service =  factory.createService(new QName(qnameService));
                    port = new QName(qnamePort);
                    call = service.createCall(port);
                    call.setTargetEndpointAddress("http://127.0.0.1:8000/sessionTest/mysessionTest");
                    …//省略部分代碼
              }
              catch(Exception e)
              {
               e.printStackTrace();
              }       
              
             }
             /**
              *測試login操作。
              */
             
             public void login()
              {
               try {
                 
                      QName QNAME_TYPE_STRING = new QName(NS_XSD, "string");
                      call.setReturnType(QNAME_TYPE_STRING);
                      call.setProperty(Call.SESSION_MAINTAIN_PROPERTY,Boolean.TRUE);
                      call.setOperationName(new QName(BODY_NAMESPACE_VALUE,"login"));
                      call.addParameter("String_1", QNAME_TYPE_STRING, 
                          ParameterMode.IN);
                      call.addParameter("String_2", QNAME_TYPE_STRING, 
                          ParameterMode.IN);    
                      String[] params = {new String("userid-001"),new String("abc")};
                      String result = (String)call.invoke(params);
                      System.out.println("正在登錄...");
                      System.out.println(result);
          
                  } catch (Exception ex) {
                      ex.printStackTrace();
                 }
              }
              /**
               *和Web服務(wù)交互,獲得LoginCount值。
               */
              public void getLoginCount()
              {
               try {
                
                      call.removeAllParameters();         
                      …//省略部分代碼
                       call.setProperty(Call.SESSION_MAINTAIN_PROPERTY,Boolean.TRUE);
                       …//省略部分代碼
                      String result = (String)call.invoke(params);
                      System.out.println(result);
          
                  } catch (Exception ex) {
                      ex.printStackTrace();
                 }
               
              }
              /**
               *和Web服務(wù)交互,注銷操作
               */
              public void logout()
              {
                 try {
                      call.removeAllParameters();    
                        call.setProperty(Call.SESSION_MAINTAIN_PROPERTY,Boolean.TRUE);
                      …//省略部分代碼
                 }
              public static void main(String[] args) {
               SessionTestClient test=new SessionTestClient();
               test.login();
               test.getLoginCount();
               test.logout();
              }       
          }
          
          												
          										

          它的運行結(jié)果如圖3所示。



          圖3 基于Call的調(diào)用

          可以看出,它同樣獲得了預(yù)期的結(jié)果。





          回頁首


          總結(jié)


          JAX-RPC以HTTP作為傳輸協(xié)議,那么會話的保持可以從HTTP應(yīng)用入手。JAX-RPC兩種服務(wù)端點中,只有基于Servlet的端點才能直接使用HTTP會話。要想在服務(wù)端點中訪問HTTP會話,Web服務(wù)實現(xiàn)類必須實現(xiàn)javax.xml.rpc.server.ServiceLifecycle接口,實現(xiàn)了這個接口的服務(wù)端點的生命周期由JAX-RPC運行環(huán)境來管理。

          通過ServletEndpointContext接口的getHttpSession來獲得客戶端的會話,這個會話由JAX-RPC運行環(huán)境維護。如果要在客戶端使用HTTP會話,那么不論是Stub還是Call都必須設(shè)置SESSION_MAINTAIN_PROPERTY屬性值為Boolean.TRUE。


          來源:http://www-128.ibm.com/developerworks/cn/webservices/ws-session/index.html

          posted on 2006-07-06 15:34 渠上月 閱讀(768) 評論(0)  編輯  收藏 所屬分類: java tips
          主站蜘蛛池模板: 花莲市| 巴彦淖尔市| 长乐市| 鸡泽县| 莱阳市| 丹江口市| 噶尔县| 增城市| 腾冲县| 秀山| 红桥区| 牙克石市| 五家渠市| 都安| 轮台县| 泾阳县| 衡东县| 亳州市| 威宁| 雷波县| 晋江市| 平昌县| 青浦区| 和田市| 五大连池市| 根河市| 雅安市| 中宁县| 泌阳县| 崇州市| 巴彦淖尔市| 土默特右旗| 应用必备| 淮安市| 长海县| 平顺县| 环江| 遂宁市| 龙陵县| 池州市| 交口县|