基于 Spring 的远程过程调用(RPC):RMI、Hessian/Burlap、Spring HttpInvoker 四种实现方式详解

4,615 阅读11分钟

一 简介

在Java开发中,我们可以使用多种远程调用技术,如:

  • 远程方法调用(Remote Method Invocation,RMI)
  • Caucho的Hessian和Burlap
  • Spring基于HTTP的远程服务
  • SOAP和RESTful风格的Web Service

注:关于Web Service可以自行参考我之前写过的相关文章(PS:www.zifangsky.cn/webservice)。在本篇文章中我主要介绍前面几种方式的具体代码实现

(1)远程调用与本地调用:

远程调用是客户端应用和服务端之间的会话。在客户端,它所需要的一些功能并不在该应用的实现范围之内,所以应用要向能提供这些功能的其他系统寻求帮助。同样,远程应用通过发布服务将这些功能暴露给其他系统使用

i)二者之间的相似点:

从表面上看,RPC调用(远程过程调用)类似于调用一个本地对象的某个方法。和本地方法调用相比两者都是同步操作,会阻塞调用代码的执行,直到被调用的过程执行完毕

ii)二者之间的不同点:

本地方法调用是指同一个应用中的两个代码块之间的执行流交换;RPC调用则是执行流从一个应用传递给另一个应用的过程,理论上另一个应用可以部署在跨网络的任意一台其他远程机器上

(2)Spring对多种远程调用的支持:

Spring支持多种不同的RPC模型,包括RMI、Hessian/Burlap以及Spring自带的Http Invoker。下面我将简单介绍一下它们之间的异同点:

  • RMI:不考虑网络限制时使用(PS:因为RMI使用任意端口来交互,有时无法穿越防火墙)
  • Hessian/Burlap:考虑网络限制时,通过HTTP访问/发布基于Java的服务。Hessian是基于二进制的远程调用技术;而Burlap是基于XML的远程调用技术
  • Spring的HttpInvoker:跟Hessian/Burlap实现的调用技术类似,但是不同的是Hessian/Burlap使用了私有的对象序列化机制,而Spring的Http Invoker则使用的是Java的序列化机制

但是,不管选择哪种远程调用模型我们都会发现Spring提供了风格一致的支持。这意味着一旦理解了如何在Spring中配置和使用其中一种模型。那么当我们想要使用另外一种模型的话,将会变得非常容易

在所有的模型中,服务都作为Spring所管理的bean配置到我们的应用中。这是通过一个代理工厂bean实现的,这个bean能够把远程服务像本地对象一样装配到其他bean的属性中去。客户端向代理发起调用,就像代理提供了这些服务一样。代理代表客户端与远程服务进行通信,由它负责处理连接的细节并向远程服务发起调用。最后代理再返回远程服务执行完成之后的结果,至此整个调用过程完成

无论我们开发的是使用远程服务的代码,还是实现这些服务的代码,或者两者兼而有之。在Spring中,使用远程服务纯粹是一个配置问题。我们不需要编写任何Java代码就可以支持远程调用。我们的服务bean也不需要关心它们是否参与了一个RPC(PS:任何传递给远程调用的bean或从远程调用返回的bean可能需要实现java.io.Serializable 接口)

二 远程方法调用(RMI)

(1)定义一个暴露出来给其他系统调用的服务:

i)它的接口:

package cn.zifangsky.rmi.service;

import java.util.Date;

public interface TestRMIService {

    /**
     * 时间格式转化服务
     * @param date 时间
     * @return String类型的时间字符串
     */
    public String formatDateService(Date date);
}

ii)它的实现类:

package cn.zifangsky.rmi.service.impl;

import java.text.Format;
import java.text.SimpleDateFormat;
import java.util.Date;

import org.springframework.stereotype.Component;

import cn.zifangsky.rmi.service.TestRMIService;

@Component("testRMIServiceImpl")
public class TestRMIServiceImpl implements TestRMIService {

    @Override
    public String formatDateService(Date date) {
        Format format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

        if(date != null){
            return format.format(date);
        }else{
            return "";
        }
    }

}

从上面的代码可以看出,这些都是简单的POJO,并没有依赖其他服务

(2)新建一个context_rmi.xml文件将上面定义的方法导出成远程服务:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:jee="http://www.springframework.org/schema/jee"
    xmlns:context="http://www.springframework.org/schema/context" 
    xsi:schemaLocation="http://www.springframework.org/schema/beans 
            http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
            http://www.springframework.org/schema/jee 
            http://www.springframework.org/schema/jee/spring-jee-4.0.xsd
            http://www.springframework.org/schema/context 
            http://www.springframework.org/schema/context/spring-context-4.0.xsd">

    <context:component-scan base-package="cn.zifangsky.rmi.service.impl" />

    <bean id="testRMIService" class="org.springframework.remoting.rmi.RmiServiceExporter">
        <!-- RMI服务名 -->
        <property name="serviceName" value="testRMIService"/>
        <!-- RMI具体服务实现类 -->
        <property name="service" ref="testRMIServiceImpl" />
        <!-- 服务调用接口 -->
        <property name="serviceInterface" value="cn.zifangsky.rmi.service.TestRMIService" />
        <!-- 注册端口 -->
        <property name="registryPort" value="1099" />
    </bean>

</beans>

可以看出,通过上面的XML配置导出了一个远程服务,其地址是:rmi://127.0.0.1:1099/testRMIService

注:上面的service的值“testRMIServiceImpl”是上面的TestRMIServiceImpl类的一个实例,通过@Component注解生成并注入到这里

(3)将TestRMIService接口等类导出成jar包供客户端使用:

上面定义好一个服务之后,我们要想在客户端(另一个Web项目)中使用这个服务,那么我们肯定是需要知道这个远程方法所在的类、方法名等信息才能够正常调用的。因此,接下来还需要将这些公共类打包成jar包放到客户端的lib目录才行

这一步可以手动选择导出的类,也可以使用一个Ant脚本来自动化完成这一操作。我这里使用的Ant脚本如下:

build_service.xml:

<?xml version="1.0" encoding="UTF-8"?>
<project name="common_build" default="build_service" basedir=".">

    <property name="targetdir" value="target"/>
    <property name="classbase" value="WebContent/WEB-INF/classes/"/>
    <property name="xpf.copy.info" value="true"/>
    <property name="model.name" value="test"/>
    <property name="env.name" value="dev"/>

    <target name="build_service">
        <jar destfile="${basedir}/target/zifangsky_${model.name}_RMIService_api.jar">
            <fileset dir="${classbase}">
                <include name="cn/zifangsky/**/model/*.class" />
                <include name="cn/zifangsky/**/model/**/*.class" />
                <include name="cn/zifangsky/**/service/*.class" />
                <include name="cn/zifangsky/**/common/*.class" />
                <include name="cn/zifangsky/**/common/**/*.class" />
            </fileset>
        </jar>
    </target>

</project>

最后将生成的zifangsky_test_RMIService_api.jar放到客户端的lib目录下即可

(4)客户端的XML配置:

context_rmi_client.xml:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:jee="http://www.springframework.org/schema/jee"
    xmlns:context="http://www.springframework.org/schema/context" 
    xsi:schemaLocation="http://www.springframework.org/schema/beans 
            http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
            http://www.springframework.org/schema/jee 
            http://www.springframework.org/schema/jee/spring-jee-4.0.xsd
            http://www.springframework.org/schema/context 
            http://www.springframework.org/schema/context/spring-context-4.0.xsd">

    <context:component-scan base-package="cn.zifangsky.rmi.service" />

    <bean id="testRMIServiceClient" class="org.springframework.remoting.rmi.RmiProxyFactoryBean">
        <!-- 服务地址 -->
        <property name="serviceUrl" value="rmi://127.0.0.1:1099/testRMIService" />
        <!-- 服务调用接口 -->
        <property name="serviceInterface" value="cn.zifangsky.rmi.service.TestRMIService" />
    </bean>

</beans>

这里的代码很简单,自己看注释就明白了

(5)测试:

package cn.zifangsky.test.rmi;

import java.util.Date;

import javax.annotation.Resource;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import cn.zifangsky.rmi.service.TestRMIService;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations={"classpath:/context/context.xml","classpath:/context/context_rmi_client.xml"})
public class TestRMI {

    @Resource(name="testRMIServiceClient")
    private TestRMIService testRMIService;

    @Test
    public void testFormatDate(){
        Date date = new Date();
        System.out.println("格式化后的时间是: " + testRMIService.formatDateService(date));
    }
}

最后输出如下:

格式化后的时间是: 2017-01-08 15:55:49

从控制台的输出结果来看,这里的客户端代码的确调用了远程服务实现了时间格式的转化。到此,关于RMI的配置和使用就结束了,下面介绍的其他的几种远程调用的配置和使用跟RMI类似,因此我就简单叙述了

三 使用Hessian发布远程服务

Hessian和Burlap是Caucho Technology提供的两种基于HTTP的轻量级远程服务解决方案。借助于尽可能简单的API和通信协议,它们都致力于简化Web服务。

关于如何选择使用Hessian还是Burlap发布服务,很大程度上,它们是一样的。唯一的区别在于Hessian的消息是二进制的,而Burlap的消息是XML格式。因为Hessian的消息是二进制的,所以它在带宽上更具优势。但是如果我们更注重可读性(如出于调试的目的)或者我们的应用需要与没有Hessian实现的语言交互,那么Burlap的XML消息将会是更好的选择

(1)下载Hessian相关的jar包:

下载地址:hessian.caucho.com

(2)定义一个测试服务:

i)它的接口TestHessianService.java:

package cn.zifangsky.hessian.service;

public interface TestHessianService {

    /**
     * 测试接口
     * @return
     */
    public String sayHello();
}

ii)它的实现类TestHessianServiceImpl.java:

package cn.zifangsky.hessian.service.impl;

import java.text.Format;
import java.text.SimpleDateFormat;
import java.util.Date;

import org.springframework.stereotype.Component;

import cn.zifangsky.hessian.service.TestHessianService;

@Component("testHessianServiceImpl")
public class TestHessianServiceImpl implements TestHessianService{

    @Override
    public String sayHello() {
        Date date = new Date();
        Format format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

        return "Hello,this's TestHessianService ---Time: " + format.format(date);
    }

}

(3)导出成服务context_hessian.xml:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:jee="http://www.springframework.org/schema/jee"
    xmlns:context="http://www.springframework.org/schema/context" 
    xsi:schemaLocation="http://www.springframework.org/schema/beans 
            http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
            http://www.springframework.org/schema/jee 
            http://www.springframework.org/schema/jee/spring-jee-4.0.xsd
            http://www.springframework.org/schema/context 
            http://www.springframework.org/schema/context/spring-context-4.0.xsd">

    <context:component-scan base-package="cn.zifangsky.hessian.service.impl" />

    <bean id="/testHessianService" class="org.springframework.remoting.caucho.HessianServiceExporter">
        <!-- Hessian具体服务实现类 -->
        <property name="service" ref="testHessianServiceImpl" />
        <!-- 服务调用接口 -->
        <property name="serviceInterface" value="cn.zifangsky.hessian.service.TestHessianService" />
    </bean>

</beans>

配置web.xml将所有的Hessian服务单独发布到一个目录:

    <servlet>
        <servlet-name>hessian</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:context/context_hessian.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>hessian</servlet-name>
        <url-pattern>/hessian/*</url-pattern>
    </servlet-mapping>

因此,上面的那个测试服务的地址是:http://localhost:9180/RMIServerDemo/hessian/testHessianService

(4)将服务接口导出成jar包供客户端使用:

操作步骤同上面的RMI的操作,略

(5)客户端的XML配置:

context_hessian_client.xml:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:jee="http://www.springframework.org/schema/jee"
    xmlns:context="http://www.springframework.org/schema/context" 
    xsi:schemaLocation="http://www.springframework.org/schema/beans 
            http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
            http://www.springframework.org/schema/jee 
            http://www.springframework.org/schema/jee/spring-jee-4.0.xsd
            http://www.springframework.org/schema/context 
            http://www.springframework.org/schema/context/spring-context-4.0.xsd">

    <bean id="testHessianServiceClient" class="org.springframework.remoting.caucho.HessianProxyFactoryBean">
        <!-- 服务地址 -->
        <property name="serviceUrl" value="http://localhost:9180/RMIServerDemo/hessian/testHessianService" />
        <!-- 服务调用接口 -->
        <property name="serviceInterface" value="cn.zifangsky.hessian.service.TestHessianService" />
    </bean>

</beans>

(6)测试:

package cn.zifangsky.test.hessian;

import javax.annotation.Resource;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import cn.zifangsky.hessian.service.TestHessianService;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations={"classpath:/context/context.xml","classpath:/context/context_hessian_client.xml"})
public class TestHessian {

    @Resource(name="testHessianServiceClient")
    TestHessianService testHessianService;

    @Test
    public void sayHello(){
        System.out.println(testHessianService.sayHello());
    }

}

最后输出如下:

Hello,this's TestHessianService ---Time: 2017-01-08 16:48:25

四 使用Burlap发布远程服务

(1)下载Burlap相关的jar包:

下载地址:repo1.maven.org/maven2/edu/…

(2)定义一个测试服务:

接口TestBurlapService.java:

package cn.zifangsky.burlap.service;

public interface TestBurlapService {
    /**
     * 测试接口
     * @return
     */
    public String sayHello();
}

其实现类TestBurlapServiceImpl.java:

package cn.zifangsky.burlap.service.impl;

import java.text.Format;
import java.text.SimpleDateFormat;
import java.util.Date;

import org.springframework.stereotype.Component;

import cn.zifangsky.burlap.service.TestBurlapService;

@Component("testBurlapServiceImpl")
public class TestBurlapServiceImpl implements TestBurlapService{

    @Override
    public String sayHello() {
        Date date = new Date();
        Format format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

        return "Hello,this's TestBurlapService ---Time: " + format.format(date);
    }

}

(3)导出成服务context_burlap.xml:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:jee="http://www.springframework.org/schema/jee"
    xmlns:context="http://www.springframework.org/schema/context" 
    xsi:schemaLocation="http://www.springframework.org/schema/beans 
            http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
            http://www.springframework.org/schema/jee 
            http://www.springframework.org/schema/jee/spring-jee-4.0.xsd
            http://www.springframework.org/schema/context 
            http://www.springframework.org/schema/context/spring-context-4.0.xsd">

    <context:component-scan base-package="cn.zifangsky.burlap.service.impl" />

    <bean id="/testBurlapService" class="org.springframework.remoting.caucho.BurlapServiceExporter">
        <!-- Burlap具体服务实现类 -->
        <property name="service" ref="testBurlapServiceImpl" />
        <!-- 服务调用接口 -->
        <property name="serviceInterface" value="cn.zifangsky.burlap.service.TestBurlapService" />
    </bean>

</beans>

对应的web.xml配置:

    <servlet>
        <servlet-name>burlap</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:context/context_burlap.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>burlap</servlet-name>
        <url-pattern>/burlap/*</url-pattern>
    </servlet-mapping>

因此,上面的那个测试服务的地址是:http://localhost:9180/RMIServerDemo/burlap/testBurlapService

(4)将服务接口导出成jar包供客户端使用:

操作步骤同上面的RMI的操作,略

(5)客户端的XML配置:

context_burlap_client.xml:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:jee="http://www.springframework.org/schema/jee"
    xmlns:context="http://www.springframework.org/schema/context" 
    xsi:schemaLocation="http://www.springframework.org/schema/beans 
            http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
            http://www.springframework.org/schema/jee 
            http://www.springframework.org/schema/jee/spring-jee-4.0.xsd
            http://www.springframework.org/schema/context 
            http://www.springframework.org/schema/context/spring-context-4.0.xsd">

    <bean id="testBurlapServiceClient" class="org.springframework.remoting.caucho.BurlapProxyFactoryBean">
        <!-- 服务地址 -->
        <property name="serviceUrl" value="http://localhost:9180/RMIServerDemo/burlap/testBurlapService" />
        <!-- 服务调用接口 -->
        <property name="serviceInterface" value="cn.zifangsky.burlap.service.TestBurlapService" />
    </bean>

</beans>

(6)测试:

package cn.zifangsky.test.burlap;

import javax.annotation.Resource;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import cn.zifangsky.burlap.service.TestBurlapService;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations={"classpath:/context/context.xml","classpath:/context/context_burlap_client.xml"})
public class TestBurlap {

    @Resource(name="testBurlapServiceClient")
    private TestBurlapService testBurlapService;

    @Test
    public void sayHello(){
        System.out.println(testBurlapService.sayHello());
    }


}

最后输出如下:

Hello,this's TestBurlapService ---Time: 2017-01-08 17:03:47

五 使用Spring的Http Invoker发布远程服务

(1)定义一个测试服务:

接口TestHttpInvokerService.java:

package cn.zifangsky.httpinvoker.service;

public interface TestHttpInvokerService {
    /**
     * 测试接口
     * @return
     */
    public String sayHello();
}

其实现类TestHttpInvokerServiceImpl.java:

package cn.zifangsky.httpinvoker.service.impl;

import java.text.Format;
import java.text.SimpleDateFormat;
import java.util.Date;

import org.springframework.stereotype.Component;

import cn.zifangsky.httpinvoker.service.TestHttpInvokerService;

@Component("testHttpInvokerServiceImpl")
public class TestHttpInvokerServiceImpl implements TestHttpInvokerService {

    @Override
    public String sayHello() {
        Date date = new Date();
        Format format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

        return "Hello,this's TestHttpInvokerService ---Time: " + format.format(date);
    }

}

(2)导出成服务context_invoker.xml:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:jee="http://www.springframework.org/schema/jee"
    xmlns:context="http://www.springframework.org/schema/context" 
    xsi:schemaLocation="http://www.springframework.org/schema/beans 
            http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
            http://www.springframework.org/schema/jee 
            http://www.springframework.org/schema/jee/spring-jee-4.0.xsd
            http://www.springframework.org/schema/context 
            http://www.springframework.org/schema/context/spring-context-4.0.xsd">

    <context:component-scan base-package="cn.zifangsky.httpinvoker.service.impl" />

    <bean id="/testHttpInvokerService" class="org.springframework.remoting.httpinvoker.HttpInvokerServiceExporter">
        <!-- Http Invoker具体服务实现类 -->
        <property name="service" ref="testHttpInvokerServiceImpl" />
        <!-- 服务调用接口 -->
        <property name="serviceInterface" value="cn.zifangsky.httpinvoker.service.TestHttpInvokerService" />
    </bean>

</beans>

对应的web.xml配置:

    <servlet>
        <servlet-name>invoker</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:context/context_invoker.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>invoker</servlet-name>
        <url-pattern>/invoker/*</url-pattern>
    </servlet-mapping>

因此,上面的那个测试服务的地址是:http://localhost:9180/RMIServerDemo/invoker/testHttpInvokerService

(3)将服务接口导出成jar包供客户端使用:

操作步骤同上面的RMI的操作,略

(4)客户端的XML配置:

context_httpinvoker_client.xml:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:jee="http://www.springframework.org/schema/jee"
    xmlns:context="http://www.springframework.org/schema/context" 
    xsi:schemaLocation="http://www.springframework.org/schema/beans 
            http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
            http://www.springframework.org/schema/jee 
            http://www.springframework.org/schema/jee/spring-jee-4.0.xsd
            http://www.springframework.org/schema/context 
            http://www.springframework.org/schema/context/spring-context-4.0.xsd">

    <bean id="testHttpInvokerServiceClient" class="org.springframework.remoting.httpinvoker.HttpInvokerProxyFactoryBean">
        <!-- 服务地址 -->
        <property name="serviceUrl" value="http://localhost:9180/RMIServerDemo/invoker/testHttpInvokerService" />
        <!-- 服务调用接口 -->
        <property name="serviceInterface" value="cn.zifangsky.httpinvoker.service.TestHttpInvokerService" />
    </bean>

</beans>

(5)测试:

package cn.zifangsky.test.httpinvoker;

import javax.annotation.Resource;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import cn.zifangsky.httpinvoker.service.TestHttpInvokerService;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations={"classpath:/context/context.xml","classpath:/context/context_httpinvoker_client.xml"})
public class TestHttpInvoker {

    @Resource(name="testHttpInvokerServiceClient")
    private TestHttpInvokerService testHttpInvokerService;

    @Test
    public void sayHello(){
        System.out.println(testHttpInvokerService.sayHello());
    }

}

最后输出如下:

Hello,this's TestHttpInvokerService ---Time: 2017-01-08 17:09:51

至此,关于基于Spring的远程过程调用(RPC)的四种实现方式的介绍就全部结束了。从上面的代码可以看出,由于Spring的封装,这几种服务的发布和实现步骤都是很类似的,并且我们实际需要做的工作也变得非常简单,我们很大程度上只需要关注我们的具体业务逻辑就行了