天天看點

Spring HTTP Invoker使用介紹

Spring HTTP Invoker一種JAVA遠端方法調用架構實作,原理與JDK的RMI基本一緻,是以我們先跟其它JAVA遠端方法調用實作做下簡單比較。

RMI:使用JRMP協定(基于TCP/IP),不允許穿透防火牆,使用JAVA系列化方式,使用于任何JAVA應用之間互相調用。

Hessian:使用HTTP協定,允許穿透防火牆,使用自己的系列化方式,支援JAVA、C++、.Net等跨語言使用。

Burlap: 與Hessian相同,隻是Hessian使用二進制傳輸,而Burlap使用XML格式傳輸(兩個産品均屬于caucho公司的開源産品)。

Spring HTTP Invoker: 使用HTTP協定,允許穿透防火牆,使用JAVA系列化方式,但僅限于Spring應用之間使用,即調用者與被調用者都必須是使用Spring架構的應用。

為什麼使用Spring HTTP Invoker?我們可以看下Spring源碼中的注釋說明:

1

2

3

4

5

<code>/* &lt;p&gt;&lt;b&gt;HTTP invoker is the recommended protocol for Java-to-Java remoting.&lt;/b&gt;</code>

<code>* It is more powerful and more extensible than Hessian and Burlap, at the</code>

<code>* expense of being tied to Java. Nevertheless, it is as easy to set up as</code>

<code>* Hessian and Burlap, which is its main advantage compared to RMI.</code>

<code>*/</code>

Spring一定希望大家盡量使用它的産品,但實際項目中我們還是要根據需求來決定選擇哪個架構,下面我們來看看Spring HTTP Invoker的使用。

既然通過是HTTP請求調用,那麼用戶端肯定需要一個代理用于幫忙發送HTTP請求,幫忙做對象系列化和反系列化等,Spring架構中的HttpInvokerServiceExporter類處理這些雜事;而伺服器端需要一個HTTP請求處理器,幫忙處理HTTP請求已經對象系列化和反系列化工作,Spring架構中的HttpInvokerServiceExporter類就是幹這活的,對于Sun JRE 6 的HTTP Server,Spring還提供了SimpleHttpInvokerServiceExporter類供選擇。

服務端配置:

服務聲明:

在Spring配置檔案中聲明一個HttpInvokerServiceExporter類的bean,共三部分:

--服務名稱(如helloExporter)

--服務類型(如com.stevex.demo.HelloService)

--服務實作類,一般引用其它bean(如helloService)

6

<code>&lt;</code><code>bean</code> <code>name</code><code>=</code><code>"helloExporter"</code>

<code>        </code><code>class</code><code>=</code><code>"org.springframework.remoting.httpinvoker.HttpInvokerServiceExporter"</code><code>&gt;</code>

<code>        </code><code>&lt;</code><code>property</code> <code>name</code><code>=</code><code>"service"</code> <code>ref</code><code>=</code><code>"helloService"</code><code>&gt;&lt;/</code><code>property</code><code>&gt;</code>

<code>        </code><code>&lt;</code><code>property</code> <code>name</code><code>=</code><code>"serviceInterface"</code> <code>value</code><code>=</code><code>"com.stevex.demo.HelloService"</code><code>&gt;</code>

<code>        </code><code>&lt;/</code><code>property</code><code>&gt;</code>

<code>    </code><code>&lt;/</code><code>bean</code><code>&gt;</code>

服務URL關聯:

在web.xml中聲明一個與服務與服務名稱同名的Servlet(當然這個Servlet類Spring已經提供即HttpRequestHandlerServlet,這家夥的作用就是直接把強求扔給同名的bean),然後聲明servlet-mapping将其map到指定URL,這樣客戶就可以通過這個URL通路到對應服務。

7

8

9

10

<code>&lt;</code><code>servlet</code><code>&gt;</code>

<code>        </code><code>&lt;</code><code>servlet-name</code><code>&gt;helloExporter&lt;/</code><code>servlet-name</code><code>&gt;</code>

<code>        </code><code>&lt;</code><code>servlet-class</code><code>&gt;</code>

<code>            </code><code>org.springframework.web.context.support.HttpRequestHandlerServlet</code>

<code>        </code><code>&lt;/</code><code>servlet-class</code><code>&gt;</code>

<code>    </code><code>&lt;/</code><code>servlet</code><code>&gt;</code>

<code>    </code><code>&lt;</code><code>servlet-mapping</code><code>&gt;</code>

<code>        </code><code>&lt;</code><code>url-pattern</code><code>&gt;/remoting/HelloService&lt;/</code><code>url-pattern</code><code>&gt;</code>

<code>    </code><code>&lt;/</code><code>servlet-mapping</code><code>&gt;</code>

用戶端配置:

在spring bean配置檔案中建立一個類HttpInvokerProxyFactoryBean的bean,指定serviceUrl屬性為伺服器端的服務提供的URL,serviceInterface屬性為伺服器端配置的服務類型。

<code>&lt;</code><code>bean</code> <code>id</code><code>=</code><code>"remoteHelloService"</code>

<code>        </code><code>class</code><code>=</code><code>"org.springframework.remoting.httpinvoker.HttpInvokerProxyFactoryBean"</code><code>&gt;</code>

<code>        </code><code>&lt;</code><code>property</code> <code>name</code><code>=</code><code>"serviceUrl"</code>

<code>            </code><code>value</code><code>=</code><code>"http://localhost:8080/demo/remoting/HelloService"</code> <code>/&gt;</code>

<code>        </code><code>&lt;</code><code>property</code> <code>name</code><code>=</code><code>"serviceInterface"</code>

<code>            </code><code>value</code><code>=</code><code>"com.stevex.demo.HelloService"</code> <code>/&gt;</code>

服務端實作:

因為服務端需要提供HTTP請求服務,而且是基于Servlet的,是以服務端需要跑在如Tomcat這樣的Servlet Web容器上;服務類隻要是普通的POJO即可,沒有特殊要求:

<code>@Service</code><code>(</code><code>"helloService"</code><code>)</code>

<code>public</code> <code>class</code> <code>HelloServiceImpl </code><code>implements</code> <code>HelloService {</code>

<code>    </code><code>@Override</code>

<code>    </code><code>public</code> <code>String hello() { </code>

<code>        </code><code>return</code> <code>"Hello Stevex, I am invoked by Spring HTTP Invoker!"</code><code>;</code>

<code>    </code><code>}</code>

<code>}</code>

<code>public</code> <code>interface</code> <code>HelloService {</code>

<code>    </code><code>public</code> <code>String hello();</code>

用戶端實作:

因為用戶端依賴服務端的服務類,是以需要設定類路徑依賴,可以将class檔案(或者jar包)拷貝到用戶端。

11

<code>public</code> <code>class</code> <code>HelloClient {</code>

<code>    </code><code>public</code> <code>static</code> <code>void</code> <code>main(String[] args) {</code>

<code>        </code><code>GenericXmlApplicationContext ctx = </code><code>new</code> <code>GenericXmlApplicationContext();</code>

<code>        </code><code>ctx.load(</code><code>"classpath:http-invoker-app-context.xml"</code><code>);</code>

<code>        </code><code>ctx.refresh();</code>

<code>        </code><code>HelloService helloService = ctx.getBean(</code><code>"remoteHelloService"</code><code>,</code>

<code>                </code><code>HelloService.</code><code>class</code><code>);</code>

<code>                                                                         </code> 

<code>        </code><code>System.out.println(helloService.hello());</code>

全部搞定後,将伺服器先跑起來,然後運作用戶端程式就可以看到調用結果了,不知道性能如何,有空測試測試!

<a href="http://down.51cto.com/data/2364013" target="_blank">附件:http://down.51cto.com/data/2364013</a>

     本文轉自sarchitect 51CTO部落格,原文連結:http://blog.51cto.com/stevex/1353236,如需轉載請自行聯系原作者