<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    隨筆-28  評論-15  文章-81  trackbacks-0

    遠程調用是客戶端應用和服務端之間的會話。在客戶端上所需要的一些功能并不包括在該應用的職能范圍內。所以應用向能提供這些功能的其他系統尋求幫助。遠程的應用通過遠程服務把這些功能公開出來。

     

    一、Spring遠程調用概覽

    Spring為各種遠程訪問技術的集成提供了工具類。Spring遠程支持是由普通(SpringPOJO實現的,這使得開發具有遠程訪問功能的服務變得相當容易。

    Spring遠程調用支持6種不同的RPC模式:遠程方法調用(RMI)、CauchoHessianBurlapSpring自己的HTTP invokerEJB和使用JAX-RPC Web Services

    RPC模式

    在何種情況下有用

    遠程方法調用(RMI

    不考慮網絡限制(如防火墻)時,訪問/公開基于Java的服務

    Hessian Burlap

    考慮網絡限制時,通過HTTP訪問/公開基于Java的服務

    HTTP invoker

    考慮網絡限制時,訪問/公開基于Spring的服務

    EJB

    訪問用EJB實現的遺留的J2EE系統

    JAX-RPC

    訪問Web Services

    其中(來自Spring2.0參考手冊):

    l         遠程方法調用(RMI。通過使用 RmiProxyFactoryBean RmiServiceExporterSpring同時支持傳統的RMI(使用java.rmi.Remote接口和java.rmi.RemoteException)和通過RMI調用器實現的透明遠程調用(支持任何Java接口)。

    l         SpringHTTP調用器Spring提供了一種特殊的允許通過HTTP進行Java串行化的遠程調用策略,支持任意Java接口(就像RMI調用器)。相對應的支持類是 HttpInvokerProxyFactoryBean HttpInvokerServiceExporter

    l         Hessian。通過 HessianProxyFactoryBean HessianServiceExporter,可以使用Caucho提供的基于HTTP的輕量級二進制協議來透明地暴露服務。

    l         Burlap BurlapCaucho的另外一個子項目,可以作為Hessian基于XML的替代方案。Spring提供了諸如 BurlapProxyFactoryBean BurlapServiceExporter的支持類。

    l         JAX RPCSpring通過JAX-RPC為遠程Web服務提供支持。

    不管選擇哪種遠程模式,你會發現Spring對每一種模式的支持中貫穿著一個共同的風格。這就意味著你一旦理解了Spring如何配置并使用其中的一種模式,當你決定使用另一種不同的模式的時候,你將擁有非常低的學習曲線。

    在所有的模式中,服務可以作為Spring管理的Bean配置到你的應用中。這是用一個代理工廠Bean實現的,這個Bean使你能把遠程服務當作本地對象一樣置入到其他Bean的屬性中。

    客戶端發起對代理的調用,好像是代理提供了這些服務的功能一樣。代理代表客戶端和遠程服務交流。它處理連接的具體情況,并向遠程服務發起遠程調用。

    在服務端,你能夠把任何Spring管理的Bean的功能公開成為一個遠程服務,可使用在表6.1中所列的任何模式(除了EJBJAX-RPC)。

    不論開發的是使用遠程服務的代碼,還是實現那些服務的代碼,或者二者兼而有之,在Spring中,使用遠程服務純粹是個配置問題。你不用寫任何Java代碼來支持遠程調用。你的服務Bean不必關心它們是否被卷入到RPC里(雖然任何傳遞給遠程調用的Bean或從遠程調用返回的Bean可能需要實現java.io.Serializable)。

     

    二、與RMI一起工作

    1.連接RMI服務

    SpringRmiProxyFactoryBean是一個工廠Bean,能創建一個指向RMI服務的代理。用RmiProxyFactoryBean來引用一個RMI PaymentService是非常簡單的,只要在Spring配置文件中聲明下面的<bean>

    <bean id="paymentService" class="org.springframework.remoting.rmi.RmiProxyFactoryBean">

     

        <property name="serviceUrl">

     

          <value>rmi://${paymenthost}/PayService</value>

     

        </property>

     

        <property name="serviceInterface">

     

          <value>com.springinaction.payment.PaymentService</value>

     

        </property>

     

    </bean>

    RMI服務的URL是通過serviceUrl屬性設置的。這里,服務被命名為PayService并且是在一臺名字用一個屬性占位符配置的機器上(參考第2章的2.4.3節)。serviceInterface屬性指明了這個服務所實現的接口,客戶端通過這個接口調用在這個服務里的方法。

    把這個支付服務定義為一個Spring管理的Bean,你就能把它作為一個合作者置入到另外的Bean上,就像你對任何非遠程的Bean做的那樣。舉例來說,假設StudentServiceImpl需要使用這個支付服務來批準一張信用卡的支付。你就使用以下代碼把RMI服務置入到StudentServiceImpl中:

    <bean id="studentService"

     

           class="com.springinaction.training.service.StudentServiceImpl">

     

     …

     

        <property name="paymentService">

     

          <ref bean="paymentService"/>

     

        </property>

     

     …

     

     </bean>

    StudentServiceImpl甚至不需要知道它處理的是一個RMI服務。它只是通過注入機制接收PaymentService對象,不必關心它是從哪里來的。此外,代理會捕獲任何可能被這個服務拋出的RemoteException,并把它們作為運行時間異常重新拋出,這樣,你可以安全地忽略這些異常。這也讓遠程服務Bean和這個服務的另外實現之間的交換成為可能——或許是不同的遠程服務,或者有可能是單元測試時的一個模擬實現。

    2.輸出RMI服務

    Spring提供了比較簡單的發布RMI服務的方法:使用POJO。開始之前,你需要寫這個服務的接口:

    publicinterface PaymentService

           {

               public String authorizeCreditCard(String cardNumber, String cardHolderName, int expireMonth, int expireYear, float amount) throws AuthorizationException;

     

               publicvoid settlePayment(String authCode, int merchantNumber, float amount) throws SettlementException;

           }

    由于服務接口不是從java.rmi.Remote繼承的,它的方法都不拋出java.rmi.RemoteException這點讓這個接口簡短了很多。但更重要的是,客戶端通過這個接口訪問支付服務時,將不再需要捕捉那些它們可能沒法處理的異常了。下一步,定義服務的實現類:

    publicclass PaymentServiceImpl implements PaymentService

           {

               public PaymentServiceImpl() {}

     

               public String authorizeCreditCard(String creditCardNumber, String cardHolderName, int expirationMonth, int expirationYear, float amount) throws AuthorizationException

               {

                      // String authCode = ...;

                      // implement authorization

                      return authCode;

               }

     

               publicvoid settlePayment(String authCode, int accountNumber, float amount) throws SettlementException

               {

                 // implement settlement

               }

            }

    你要做的下一件事就是在Spring的配置文件里把PaymentServiceImpl配置為一個<bean>

    <bean id="paymentService" class="org.springframework.payment.PaymentServiceImpl">

     …

    </bean>

    PaymentServiceImpl沒有設置RMI所固有的特性。它僅僅是一個適合在Spring配置文件中聲明的簡單的POJO。事實上,完全有可能在非遠程方式中,通過直接把它置入到客戶端里,來使用這個實現。

     

    三、使用HessianBurlap的遠程調用

    HessianBurlapCaucho Technologyhttp://www.caucho.com)提供的兩種解決方法,是基于HTTP的輕量級遠程服務。它們都致力于通過把它們的API和通信協議變得盡可能的簡單,來簡化Web服務。

    事實上,HessianBurlap是同一個問題的兩個方面,但每個都服務于略微不同的目的。Hessian,像RMI那樣,使用二進制消息來建立客戶端和服務端之間的交流。但與其他二進制遠程技術(如RMI)不同的是,它的二進制消息可以移植到其他非Java的語言中。

    Burlap是一種基于XML的遠程技術,這使得它自然而然地可以移植到任何可以解析XML的語言中。正由于它的XML,比起Hessian的二進制格式來,它的可讀性更強。但和其他基于XML的遠程技術(例如SOAPXML-RPC)不同,Burlap的消息結構是盡可能的簡單,不需要額外的外部定義語言(如WSDLIDL等)

    如何在HessianBurlap之間做選擇。很大程度上說,它們是一樣的。惟一的不同就是Hessian的消息是二進制的,而Burlap的消息是XML。由于Hessian的消息是二進制的,所以它在帶寬上更占優勢。但如果可讀性對你來說很重要的話(如出于調試的目的)或者你的應用將和沒有Hessian實現(任何除了JavaPython)的語言交流,那么BurlapXML消息會是更好的選擇。

    1.訪問Hessian/Burlap服務

    所有RMI的細節都包含在Spring配置文件的Bean的配置里。這樣做的好處就是,由于客戶端忽略了服務的實現,從一個RMI客戶端轉到Hessian客戶端是極其簡單的,不需要改變任何客戶端代碼。

    壞處就是,如果你真地喜歡寫代碼的話,那么這一節就可能讓你有點兒失望了。因為寫基于RMI服務的客戶端代碼和基于Hessian服務的客戶端代碼惟一的不同就是你將使用SpringHessianProxyFactoryBean來代替RmiProxyFactoryBean。客戶端代碼中基于Hessian的支付服務可以用以下代碼聲明:

    <bean id="paymentService" class="org.springframework.

     

              ?remoting.caucho.HessianProxyFactoryBean">

     

        <property name="serviceUrl">

     

            <value>http://${serverName}/${contextPath}/pay.service</value>

     

        </property>

     

        <property name="serviceInterface">

     

            <value>com.springinaction.payment.PaymentService</value>

     

        </property>

     

     </bean>

    就像基于RMI的服務那樣,serviceInterface屬性指定這個服務實現的接口。并且,如同RmiProxyFactoryBeanserviceUrl表明這個服務的URL。既然Hessian是基于HTTP的,當然應該在這里設置一個HTTP URL了(你將在下一節中看到這個URL是如何得來的)。

    事實證明,寫一個Burlap服務是同樣無趣的。二者惟一的不同就是,你使用BurlapProxyFactoryBean代替HessianProxyFactoryBean

    <bean id="paymentService" class="org.springframework.

     

              ?remoting.caucho.BurlapProxyFactoryBean">

     

        <property name="serviceUrl">

     

          <value>http://${serverName}/${contextPath}/pay.service</value>

     

        </property>

     

        <property name="serviceInterface">

     

          <value>com.springinaction.payment.PaymentService</value>

     

        </property>

     

     </bean>

    盡管我們覺得在RMIHessianBurlap服務之間稍微不同的配置是很沒有樂趣的,但這個單調恰恰是有好處的。它意味著你不費吹灰之力就可以在各種Spring支持的遠程技術之間轉換,無須去學習一個全新的模型。你一旦配置了一個對RMI服務的引用,把它重新配置為HessianBurlap服務也是很輕松的工作。

    2.用HessianBurlap公開Bean的功能

    輸出一個Hessian服務:

    Spring里輸出一個Hessian服務和在Spring里實現一個RMI服務驚人地相似。為把支付服務公開為RMI服務,你得在Spring配置文件中配置一個RmiServiceExporter Bean。非常類似的,把支付服務公開為Hessian服務,你也需要配置一個exporter Bean。只不過這一次用的是HessianServiceExporter

    <bean name="hessianPaymentService" class="org.springframework.

     

             ?remoting.caucho.HessianServiceExporter">

     

        <property name="service">

     

          <ref bean="paymentService"/>

     

        </property>

     

        <property name="serviceInterface">

     

          <value>com.springinaction.payment.PaymentService</value>

     

        </property>

     

     </bean>

    HessianServiceExporterHessian服務中實現的功能和RmiServiceExporterRMI服務中的功能是完全一樣的。那就是說,它把一個Bean的公共方法公開為一個Hessian服務的方法。

    正如RmiServiceExporterservice屬性中被置入了實現這個服務的Bean的引用。這里,這個service屬性綁定的是paymentService Bean的引用。serviceInterface屬性用來表示PaymentService是這個服務所實現的接口。

    然而,和RmiServiceExporter不同,你不需要設置serviceName屬性。在RMI中,serviceName屬性用來在RMI注冊表中注冊一個服務。Hessian沒有注冊表,因此就沒有必要命名一個Hessian服務。

    配置Hessian控制器:

    RmiServiceExporterHessianServiceExporter另外一個主要的區別就是,由于Hessian是基于HTTP所以HessianServiceExporter被實現成Spring MVCController。這就是說,為了使用輸出的Hessian服務,你需要完成兩個額外的配置步驟:

    1.在你的Spring配置文件中配置一個URL處理器,來分發Hessian服務的URL給適當的Hessian服務Bean

    2web.xml中配置一個SpringDispatcherServlet,并把你的應用部署為web用。

    輸出一個Burlap服務:

    Spring管理的Bean作為Burlap服務輸出。用SpringBurlapServiceExporter來代替HessianServiceExporter就能完成這項任務:

    <bean name="burlapPaymentService" class="org.springframework.

     

                ?remoting.caucho.BurlapServiceExporter">

     

        <property name="service">

     

          <ref bean="paymentService"/>

     

        </property>

     

        <property name="serviceInterface">

     

          <value>com.springinaction.payment.PaymentService</value>

     

        </property>

     

     </bean>

    你會發現,除了Bean的名字(完全是任意的)和使用了BurlapServiceExporter以外,這個BeanhessianPaymentService是一樣的。配置Burlap服務和配置Hessian服務的其他方面也是一樣的,這也就包括了需要建一個URL處理器和DispatcherServletHessianBurlap解決了RMI頭疼的防火墻問題。

     

    四、使用HTTP invoker

    1.通過HTTP訪問服務

    訪問一個HTTP invoker服務,你需要使用HttpInvokerProxyFactoryBean要讓支付服務作為一個HTTP invoker服務公開,得配置一個Bean,用HttpInvokerProxyFactoryBean來代理它,如下所示:

    <bean id="paymentService" class= "org.springframework.remoting.

     

              ?httpinvoker.HttpInvokerProxyFactoryBean">

     

        <property name="serviceUrl">

     

          <value>http://${serverName}/${contextPath}/pay.service</value>

     

        </property>

     

        <property name="serviceInterface">

     

          <value>com.springinaction.payment.PaymentService</value>

     

        </property>

     

     </bean>

    serviceInterface屬性仍然用來表示這個支付服務所實現的接口;serviceUrl屬性仍然是用來表示遠程支付服務的位置。由于HTTP invoker是基于HTTP的,如同HessianBurlap一樣,serviceUrl就能包含與HessianBurlap版本的Bean里一樣的URL

    2.把Bean作為HTTP服務公開

    使用HttpInvokerServiceExporterBean的方法輸出為遠程方法,面的Bean的定義展示了如何把paymentService Bean作為一個遠程的基于HTTP invoker的服務輸出:

    <bean id="httpPaymentService" class="org.springframework.remoting.

     

            ?httpinvoker.HttpInvokerServiceExporter">

     

        <property name="service">

     

          <ref bean="paymentService"/>

     

        </property>

     

        <property name="serviceInterface">

     

          <value>com.springinaction.payment.PaymentService</value>

     

        </property>

     

    </bean>

    基于HTTP invoker的服務,顧名思義,是基于HTTP的,就像HessianBurlap服務一樣。并且,也和HessianServiceExporterBurlapServiceExporter那樣,HttpInvokerServiceExporter也是一個SpringController。這就意味著你需要建立一個URL處理器,把HTTP URL映射到服務上:

    <bean id="urlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">

     

        <property name="mappings">

     

          <props>

     

             <prop key="/pay.service">httpPaymentService</prop>

     

          </props>

     

        </property>

     

     </bean>

    SpringHTTP invoker是作為一個兩全其美的遠程調用解決方案出現的,把HTTP交流的簡單性和Java內置的對象序列化機制結合起來。這讓HTTP invoker服務成為一個引人注目的對RMI或是對Hessian/Burlap的替代品。

    要記住HTTP invoker有個重大的限制,它是一個只在Spring框架中提供的遠程調用解決方案。這就意味著客戶端和服務器端都必須是使用Spring的應用。

     

    五.使用EJB

    雖然Spring提供了大量的功能,讓POJO具有EJB的能力,但你或許不能總是享受在完全沒有EJB的項目上工作的奢侈。一方面,你可能會接觸一些其他系統,它們的功能是通過無狀態的會話EJB開放出來的。另一方面,你可能被放在一個項目中,由于正統技術(或者可能是政治)的原因,你不得不寫EJB代碼。

    不管你的應用是EJB客戶端,還是你必須寫EJB本身,你都不需要為了用EJB,完全放棄Spring帶來的好處。Spring有兩種方法提供對EJB的支持:

    ?   Spring能讓你在Spring的配置文件里,把EJB作為Bean來聲明。這樣,把EJB引用置入到其他Bean的屬性里就成為可能了,好像EJB就是另一個POJO

    ?   Spring能讓你寫EJB,讓EJB成為Spring配置的Bean的代理的工作。

     

    六、使用JAX-RPCWeb Service

    JAX-RPC基于XML的遠程調用的Java APIJava APIs for XML-based remote procedure call的縮寫。這是一個口語化的詞,僅僅意味著JAX-RPCJava程序使用XML訪問遠程服務的一種方式。特別地,這個服務是指用SOAPSimple Object Access Protocol)協議公開它們的功能的web service

     

    七、小結

    Spring提供了遠程服務的支持,讓使用遠程服務和使用常規的JavaBean一樣簡單。

    在客戶端,Spring提供了代理工廠Bean,能讓你在Spring應用中配置遠程服務。不管是使用RMIHessianBurlapHTTP invokerEJB、還是Web service,你都可以把遠程服務置入到你的應用里,好像它們是POJO一樣。Spring甚至捕獲了所有拋出的RemoteException,并在發生異常的地方重新拋出運行時RemoteAccessException,讓你的代碼從處理可能不可恢復的異常中解放出來。

        Spring的遠程調用我不知什么時候才能用上,在這里在不太理解的基礎上對書作了簡單的摘抄,先留個記號等以后用著了在回頭學習。

     

    posted on 2007-10-23 21:51 譚明 閱讀(1613) 評論(0)  編輯  收藏 所屬分類: Spring
    主站蜘蛛池模板: 男人天堂2018亚洲男人天堂| 欧洲人成在线免费| 亚洲综合久久1区2区3区| 可以免费观看一级毛片黄a| 两个人的视频高清在线观看免费| 最新国产乱人伦偷精品免费网站| 久久亚洲精品无码gv| 97久久国产亚洲精品超碰热| 久久99国产亚洲精品观看| 国产午夜亚洲精品理论片不卡| 国产小视频在线观看免费| 最近中文字幕免费mv视频8| 精品福利一区二区三区免费视频| 国产精品偷伦视频观看免费 | 国产精品成人免费福利| 免费看黄的成人APP| 精品国产呦系列在线观看免费 | 日韩精品电影一区亚洲| 黑人粗长大战亚洲女2021国产精品成人免费视频| 小日子的在线观看免费| 亚洲免费观看视频| 中文字幕不卡免费视频| 精品国产呦系列在线观看免费 | 亚洲高清无码综合性爱视频| 午夜a级成人免费毛片| 成年女人免费视频播放体验区| 国产啪精品视频网免费| 免费观看AV片在线播放| 无码国产精品一区二区免费| 亚洲高清中文字幕免费| 麻豆视频免费播放| 91情侣在线精品国产免费| 免费国产黄线在线观看| 免费被黄网站在观看| 国产传媒在线观看视频免费观看| 国产精品深夜福利免费观看| 免费播放春色aⅴ视频| 三上悠亚亚洲一区高清| 亚洲国产精品无码久久一线| 婷婷久久久亚洲欧洲日产国码AV| 日韩亚洲Av人人夜夜澡人人爽 |