天天看点

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,如需转载请自行联系原作者