org.springframework.remoting.httpinvoker.httpinvokerserviceexporter 實作遠端服務調用
(1)httpinvoker方式 伺服器用戶端都是spring時推薦這種方式
服務端 必須要實作 bean實體類 service接口類 serviceimpl服務實作類
用戶端隻需拷貝 bean 實體類 service接口類(注意 ,用戶端 bean,service類要和服務端bean,service類包路徑相同,比如都是
com.hlzt.csm.model.dataplatformcountbean,不然會報找不到類,而且 bean要序列化 public class dataplatformcount implements serializable;
如果服務端有 序列化的private static final long serialversionuid = 1l号,用戶端也必須有,如果服務端沒有此id,用戶端也不要有此id,不然會出錯。service類的包路徑也要相同,最好服務端寫好後直接把實體類和service服務接口類打包,拷貝到用戶端,以免造成兩端不同。
)
伺服器端要在spring-mvc配置檔案 spring-mvc-servlet.xml中加入以下(注意是在spring-mvc的配置檔案中,不是spring的配置檔案)
服務端 web.xml的配置

用戶端配置
用戶端 spring的xml檔案配置
注意的是 id="csmdatacountser" 本人測試結果是 此執行個體不能在java中通過 rource 或autowired自動注入,而要通過手工載入方式獲得
applicationcontext context =new classpathxmlapplicationcontext("/spring/spring-remote.xml");
csmdatacountser csmdatacountser=(csmdatacountser)context.getbean("csmdatacountser");
(2)spring rmi方式
首先看下執行個體程式目錄結構:
spring中釋出rmi服務(zlv_rmiserverwithspring):
(1) 定義接口messageprovider及接口中供調用的方法(messageprovider.java):
<a target="_blank" href="http://my.oschina.net/lvsantorini/blog/489405#">?</a>
1
2
3
4
5
<code>package</code> <code>org.thera.rmi.service;</code>
<code>public</code> <code>interface</code> <code>messageprovider {</code>
<code> </code><code>public</code> <code>string queryformessage(string name);</code>
<code>}</code>
(2) 實作messageprovider接口(messageproviderimpl.java):
6
7
8
9
10
<code>public</code> <code>class</code> <code>messageproviderimpl </code><code>implements</code> <code>messageprovider {</code>
<code> </code><code>@override</code>
<code> </code><code>public</code> <code>string queryformessage(string name) {</code>
<code> </code><code>return</code> <code>"hello, "</code> <code>+ name;</code>
<code> </code><code>}</code>
做好了上述準備,下面我們就可以通過spring中內建rmi,友善的釋出rmi服務端
(3) spring配置檔案作如下配置(context.xml):
11
12
13
14
15
16
17
18
19
20
21
<code><?</code><code>xml</code> <code>version</code><code>=</code><code>"1.0"</code> <code>encoding</code><code>=</code><code>"utf-8"</code><code>?></code>
<code><</code><code>beans</code> <code>xmlns</code><code>=</code><code>"http://www.springframework.org/schema/beans"</code>
<code> </code><code>xmlns:p</code><code>=</code><code>"http://www.springframework.org/schema/p"</code> <code>xmlns:xsi</code><code>=</code><code>"http://www.w3.org/2001/xmlschema-instance"</code>
<code> </code><code>xsi:schemalocation="http://www.springframework.org/schema/beans</code>
<code> </code><code>http://www.springframework.org/schema/beans/spring-beans.xsd"></code>
<code> </code><code><!-- 注入要釋出的rmi服務類 --></code>
<code> </code><code><</code><code>bean</code> <code>id</code><code>=</code><code>"messageservice"</code> <code>class</code><code>=</code><code>"org.thera.rmi.service.messageproviderimpl"</code><code>></</code><code>bean</code><code>></code>
<code> </code><code><</code><code>bean</code> <code>class</code><code>=</code><code>"org.springframework.remoting.rmi.rmiserviceexporter"</code><code>></code>
<code> </code><code><!-- rmi服務名稱,可自定義服務名稱 --></code>
<code> </code><code><</code><code>property</code> <code>name</code><code>=</code><code>"servicename"</code> <code>value</code><code>=</code><code>"messageservice"</code> <code>/></code>
<code> </code><code><!-- 導出實體 --></code>
<code> </code><code><</code><code>property</code> <code>name</code><code>=</code><code>"service"</code> <code>ref</code><code>=</code><code>"messageservice"</code> <code>/></code>
<code> </code><code><!-- 導出接口 --></code>
<code> </code><code><</code><code>property</code> <code>name</code><code>=</code><code>"serviceinterface"</code> <code>value</code><code>=</code><code>"org.thera.rmi.service.messageprovider"</code> <code>/></code>
<code> </code><code><!-- spring預設使用1099端口 --></code>
<code> </code><code><</code><code>property</code> <code>name</code><code>=</code><code>"registryport"</code> <code>value</code><code>=</code><code>"1199"</code> <code>/></code>
<code> </code><code></</code><code>bean</code><code>></code>
<code></</code><code>beans</code><code>></code>
(4) 加載spring容器,釋出rmi服務(main.java):
<code>package</code> <code>org.thera.rmi.service.main;</code>
<code>import</code> <code>org.springframework.context.applicationcontext;</code>
<code>import</code> <code>org.springframework.context.support.filesystemxmlapplicationcontext;</code>
<code>public</code> <code>class</code> <code>main {</code>
<code> </code><code>public</code> <code>static</code> <code>void</code> <code>main(string[] args) {</code>
<code> </code><code>applicationcontext ctx = </code><code>new</code> <code>filesystemxmlapplicationcontext(</code><code>"conf/context.xml"</code><code>);</code>
<code> </code><code>system.out.println(</code><code>"已成功釋出rmi服務類"</code><code>);</code>
到這裡,rmi的服務端已經釋出成功,運作結果如下截圖:
spring中用戶端調用rmi服務(zlv_rmiclientwithspring):
(1) 移植服務端服務接口檔案messageprovider.java;
(2) spring配置檔案做如下配置:
<code> </code><code><</code><code>bean</code> <code>id</code><code>=</code><code>"messageservice"</code> <code>class</code><code>=</code><code>"org.springframework.remoting.rmi.rmiproxyfactorybean"</code><code>></code>
<code> </code><code><</code><code>property</code> <code>name</code><code>=</code><code>"serviceurl"</code> <code>value</code><code>=</code><code>"rmi://192.168.1.100:1199/messageservice"</code> <code>/></code>
(3) 加載spring容器,調用rmi服務端(main.java):
<code>import</code> <code>org.thera.rmi.service.messageprovider;</code>
<code> </code><code>system.out.println(</code><code>"加載spring容器,并初始化rmi用戶端"</code><code>);</code>
<code> </code><code>messageprovider client = (messageprovider)ctx.getbean(</code><code>"messageservice"</code><code>);</code>
<code> </code><code>string temp = client.queryformessage(</code><code>"lvsantorini"</code><code>);</code>
<code> </code>
<code> </code><code>system.out.println(</code><code>"傳回結果: "</code> <code>+ temp);</code>
運作main.java,結果如下圖:
四種方式總結
1. spring remote service overview
rpc調用類似于調用本地對象的方法,都是同步的操作,調用代碼将被阻塞,直到被調用過程完成為止。
本地調用就是execute process在同一個應用的兩個代碼塊中交換。rpc就是execute
process從一個應用通過網絡傳遞給另外一個應用。
spring remoteservice支援這幾種模式:rmi, hessian, burlap, http invoker和jax-rpc。
在server端,spring可以通過相應的remoteexporter将一個bean的釋出成一個remote
service。
2. rmi in spring
rmi缺點:rmi在有防火牆的環境下運作會有困難,而且rmi要求用戶端和伺服器端都必須用java編寫。
3. hessian和burlap
hession和burlap都是caucho technology的架構,基于http的輕量級remote
hessian使用binary消息來建立用戶端和伺服器端之間的交流,因為基于binary是以對通迅帶寬的占用小。是以不依賴于語言可以被java之外的語言所用。
burlap是基于xml的技術,消息可讀性比較好,而且burlap相比其他基于xml的技術比如soap來說,burlap的消息結構比較簡單,不需要wsdl之類的東西額外定義。
使用hessian(用戶端代碼)
和rmi類似,spring使用hessianproxyfactorybean來建立一個指向hessian服務的proxy。
由此可見,當使用spring時,可以很簡單的在各種spring所支援的remote技術之間切換,而僅僅需要更改很少的配置。
輸出hessian服務
使用hessianserviceexporter
将pojo的public方法公開成hessian服務。hessianserviceexporter是一個spring
mvc controller,接收hessian的請求然後翻譯成對pojo的方法調用。
輸出burlap服務
burlap服務的輸出幾乎和hessian是一樣的,不同的地方就是使用org.springframework.remoting.caucho.burlapserviceexporter。也需要為它配置url
handler和dispatcherservlet。
4. http invoker
rmi使用java标準的序列化機制,但是很難穿過防火牆;hessian/burlap能穿越防火牆但是使用自己私有的一套系列化機制。
是以http invoker應運而生,使用http協定能通過防火牆,并且使用java序列化機制。
使用http invoker
和rmi,hessian等相同,http invoker也是通過httpinvokerproxyfactorybean。
輸出http invoker服務
和hessian相同,不同的地方就是使用org.springframework.remoting.httpinvoder.httpinvokerserviceexporter。也需要為它配置url
http invoder的限制就是用戶端和伺服器端必須使用spring。