8.2HTTP调用
RMI虽然是Java标准的远程调用模式,但是RMI最大的特点是使用特定的JRMP(Java Remote MethodProtocol,Java 远程方法协议) 二进制协议,很难穿透防火墙,仅适合企业内容网络中使用。如果需要跨防火墙调用,则HTTP协议几乎是唯一的选择。
因此我们需要一种以HTTP协议为基础的远程调用。Spring支持3中基于HTTP协议的远程调用,以及我们将在下面讨论的WEB服务,在这里先讨论Spring支持3中HTTP远程调用。
Hessian 和 Burlap 这两种基本HTTP的远程调用协议是有Caucho开发的,并且集成在Resin服务期内,可以直接使用。Hessian是一个二进制协议,而Burlap是一个基于XML的 ,两者没有本质的不同。区别在于,Hessian由于使用了二进制协议,所以效率更高,但是很难被读懂,而Burlap使用XML作为载体,其传输内容很容易被开发人员所理解,并且,从理论上讲,任何其他语言只要能解析XML就可以使用Burlap和Java程序通信。不过,这两种协议由于是私有协议,并没有成为标准,因此仅适合Java系统内跨防火墙进行调用。
除Hessina和Burlap外,Spring本身还提供了一个HTTP远程调用协议,我们暂且称之为HTTP Invoker。和Hessian、Burlap使用自定义的序列化机制有所不同,HTTP Invoker使用Java标砖的序列化机制,通过HTTP协议来实现远程调用,因此这种方式也适用于Java应用程序的通信。
在Spring中,使用Hessian、Burlap和HTTP Invoker非常容易,我们甚至根本无需了解其API细节就可以直接使用它们。下面的HttpCall_Server工程演示了在Spring环境下将服务接口暴露成为远程服务的方法。由于Hessian、Burlap和HTTP Invoker都需要通过Servlet来实现服务接口,因此,该工程是一个基于Spring MVC框架的WEB应用程序。
我们设置了一个非常简单的接口TimeService,用于返回当前时间。
public interface TimeService { String getTime(); } |
TimeServiceImpl是实现类,其实现非常简单。
public class TimeServiceImpl implements TimeService {
@Override public String getTime() { return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()); } } |
现在,我们需要将TimeService 暴露为远程接口,以便客户端可以通过HTTP实现远程调用。在Spring中,通过Hessian、Burlap和HTTP Invoker实现该服务非常简单,Spring已经提供了现成的HttpRequestHandler,只需要告诉Spring业务接口和实现类,就立刻可以将其输出为远程接口。在Spring的XML配置文件dispatcher-servlet.xml中定义如下:
<beanid="timeService"class="com.zsw.httpcall.TimeServiceImpl"/>
<beanname="/HessianService"class="org.springframework.remoting.caucho.HessianServiceExporter"> <propertyname="service"ref="timeService"/> <propertyname="serviceInterface"value="com.zsw.httpcall.TimeService"/> </bean>
<beanname="/BurlapService"class="org.springframework.remoting.caucho.BurlapServiceExporter"> <propertyname="service"ref="timeService"/> <propertyname="serviceInterface"value="com.zsw.httpcall.TimeService"/> </bean>
<beanname="/SpringHttpService"class="org.springframework.remoting.httpinvoker.HttpInvokerServiceExporter"> <propertyname="service"ref="timeService"/> <propertyname="serviceInterface"value="com.zsw.httpcall.TimeService"/> </bean>
|
以Hessian为例,只需首先定义好提供服务的TimeService Bean,然后将TimeService接口及其实现类注入到HessianServiceExporter,就立刻实现了一个Hessian远程调用服务。Burlap和HTTP Invoker的配置完全相同。我们甚至在编译器没有用到任何额外的jar包实现了3个远程调用接口。
下一步需要在WEB.xml中配置好Spring的DispatchServlet。
<servlet> <servlet-name>dispatcher</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <load-on-startup>0</load-on-startup> </servlet>
<servlet-mapping> <servlet-name>dispatcher</servlet-name> <url-pattern>/remote/*</url-pattern> </servlet-mapping> |
下一步,我们需要编写客户端来实现远程调用上述服务。在Eclipse中新建一个HttpCall_Client工程,结构如下:
在Spring中调用Hessian、Burlap和HTTP Invoker也非常容易。首先,将TimeService接口从HttpCall_Server工程中复制过来,然后再config.xml中配置如下:
<beanid="hessianService"class="org.springframework.remoting.caucho.HessianProxyFactoryBean"> <propertyname="serviceUrl"value="http://localhost:8080/remote/HessianService"/> <propertyname="serviceInterface"value="com.zsw.httpcall.TimeService"/> </bean>
<beanid="burlapService"class="org.springframework.remoting.caucho.BurlapProxyFactoryBean"> <propertyname="serviceUrl"value="http://localhost:8080/remote/BurlapService"/> <propertyname="serviceInterface"value="com.zsw.httpcall.TimeService"/> </bean>
<beanid="springHttpService"class="org.springframework.remoting.httpinvoker.HttpInvokerProxyFactoryBean"> <propertyname="serviceUrl"value="http://localhost:8080/remote/SpringHttpService"/> <propertyname="serviceInterface"value="com.zsw.httpcall.TimeService"/> </bean> |
以Hesian为例,为了获得远程接口,只需要将服务端地址和接口类注入到HessianProxyFactoryBean中,其返回的即时具有TimerService接口的远程对象,客户端只需要调用该对象即可,甚至不知道该对象到底是否是一个远程对象。Burlap和HTTP Invoker的配置和Hessian完全相同。
为了让读者更直观地看到远程调用的效果,我们做出了一个Swing界面,允许用户选择使用哪个远程对象。先启动HttpCall_Server工程,然后运行HttpCall_Client的Main方法,效果如下:
以上3中HTTP调用都可以跨防火墙,不过,由于使用的都是私有协议,因此只能用于Java应用程序之间的远程调用。如果希望和易购平台实现远程调用,就不洗使用标砖的WEB服务 (Web Services).
HTTP调用例子,下载地址:http://download.csdn.net/detail/sz_bdqn/4255104