Spring远程调用HttpInvoker

Spring支持的远程调用方式有RMI、Caucho的Hessian和Burlap,使用SOAP和JAX-RPC的Web Services,以及Spring自己的Http invoker。

 

RMI需要客户端、服务器都使用Java,使用标准的java序列化机制,但是容易受到网络限制(如防火墙)。HessianBurlap通过HTTP协议访问,但是序列化不是java的序列化机制。Spring自己的Http invoker则融合了RMIHessian的优点,能通过HTTP访问,不受防火墙限制,同时使用标准的java序列化机制,但是需要Spring框架的支持。

1、Spring对RMI的支持

如果从头写RMI需要处理RemoteException异常,使用rmic编译程序,生成客户端代理和服务器框架,涉及如下步骤:

(1)、编写服务实现类,类中的方法能够抛出java.rmi.RemoteException。

(2)、创建服务接口,以便扩展java.rmi.Remote。

(3)、运行RMI编译器(rmic),创建客户端stub类和服务器端skeleton类。

(4)、启动一个RMI注册,在RMI注册表中注册服务。

而使用Spring节省了很多不必要的代码,不需要抛出RemoteException,只需简单地编写能实现服务功能的POJO,Spring会处理其他事情。使用Spring的RmiServiceExporter可以把任何Spring管理的Bean输出成一个RMI服务,如下图:

 

RmiServiceExporter通过把POJO置入服务适配器并将服务适配器与RMI注册表绑定使POJO转换成RMI服务。

 

2、Spring对Hassian和Burlap的支持

 Hassian和Burlap是Caucho Technology提供的两种解决方法,是基于HTTP的轻量级远程服务。Hessian像RMI那样,使用二进制消息来建立客户端和服务端之间的交流。Burlap是一种基于XML的远程技术。Spring提供了HessianProxyFactoryBean和BurlapProxyFactoryBean来生成代理对象负责通过HTTP与远程服务通信,如下图:

3、Spring Http Invoker

Spring的远程调用机制HttpInvoker是一个新的远程调用模型,作为Spring框架的一部分,使用Java的序列化机制,执行基于HTTP的远程调用(不受防火墙的影响)。

通过一个简单例子来看一下HttpInvoker的使用,假设提供一个简单的helloService,要将这个服务公开,需要使用HttpInvokerServiceExporter来将helloService公开,服务接口为Hello,而服务的实现类为HelloImpl。

 

服务接口很简单:

public interface Hello {

    public Person hello(String name);

}

要传递给客户端的Person类,需要实现序列化接口:

public class Person implements Serializable {

    private String name;

    private int age;

 

    public Person() {

    }

 

    public Person(String name, int age) {

       this.name = name;

       this.age = age;

    }

 

    public String getName() {

       return name;

    }

    public void setName(String name) {

       this.name = name;

    }

    public int getAge() {

       return age;

    }

    public void setAge(int age) {

       this.age = age;

    }

}

 

服务实现类简单的创建一个Person对象然后返回给客户端:

 

public class HelloImpl implements Hello {

 

    public Person hello(String name) {

       Person p = new Person();

       p.setAge(10);

       p.setName(name);

       return p;

    }

 

}

 

HttpInvokerServiceExporter实际上是一个spring mvc控制器,它处理客户端的请求并调用服务实现。Service及实现类配置在applicationContext.xml文件中,如下:

 

<bean id="httpService"

    class="org.springframework.remoting.httpinvoker.HttpInvokerServiceExporter">

       <property name="service">

           <ref bean="helloService" />

       </property>

       <property name="serviceInterface" value="httpinvoker.Hello"></property>

    </bean>

    <bean id="helloService" class="httpinvoker.HelloImpl" />

 

Web.xml配置spring servlet入口

<web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee"

    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

    xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">

    <context-param>

           <param-name>contextConfigLocation</param-name>

           <param-value>/WEB-INF/applicationContext.xml</param-value>

    </context-param>

    <listener>

       <listener-class>

           org.springframework.web.context.ContextLoaderListener

       </listener-class>

    </listener>

    <servlet>

       <servlet-name>service</servlet-name>

       <servlet-class>org.springframework.web.servlet.DispatcherServlet

       </servlet-class>

    </servlet>

 

    <servlet-mapping>

       <servlet-name>service</servlet-name>

       <url-pattern>/service/*</url-pattern>

    </servlet-mapping>

</web-app>

 

service-servlet.xml中配置spring url处理器,这里使用SimpleUrlHandlerMapping:

 

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

       <property name="mappings">

           <props>

              <prop key="/httpService">httpService</prop>

           </props>

       </property>

</bean>

 

客户端使用相同的接口Hello及Person类,使用HttpInvokerProxyFactoryBean创建代理bean,设置属性serviceUrl为服务器的服务访问url:

 

<bean id="httpService"    class="org.springframework.remoting.httpinvoker.HttpInvokerProxyFactoryBean">

       <property name="serviceUrl">

        <value>http://localhost:8080/hello/service/httpService</value>

       </property>

       <property name="serviceInterface" value="httpinvoker.Hello"/>

</bean>

 

客户端可以使用一个简单的测试程序测试服务器的服务:

 

ApplicationContext appContext = new FileSystemXmlApplicationContext(

              "classpath:application-client.xml");

       Hello helloService = (Hello) appContext.getBean("httpService");

       System.out.println("helloService is " + helloService);

       Person person = helloService.hello("df");

       System.out.println("name: " + person.getName() + ", age: "

              + person.getAge());

posted @ 2013-04-24 19:13  7mile  阅读(993)  评论(0编辑  收藏  举报