可能是最好的Spring RMI开发教程【建议收藏】

「这是我参与11月更文挑战的第31天,活动详情查看:2021最后一次更文挑战」。

前言

Spring 作为一个基础框架,对 remoting(远程调用)有多种支持。Spring remoting support 简化了远程服务的开发。

目前,Spring 支持以下远程技术:Remote Method Invocation (RMI)HTTP InvokerHessianBurlapJAX-RPCJAX-WSJMS

Spring支持的远程技术

远程方法调用 (RMI)

Spring 通过 RmiProxyFactoryBeanRmiServiceExporter 支持 RMI。 RmiServiceExporter 将任何 Spring 管理的 bean 作为 RMI 服务导出并注册。 RmiProxyFactoryBean 是一个为 RMI 服务创建代理的工厂 bean。该代理对象代表客户端与远程 RMI 服务对话。

Spring的HTTP invoker

Spring HTTP invoker 使用标准的 Java 序列化机制通过 HTTP 暴露服务。 Spring 通过 HttpInvokerProxyFactoryBeanHttpInvokerServiceExporter 支持 HTTP 调用者基础设施。 HttpInvokerServiceExporter 将指定的服务 bean 导出为 HTTP 调用程序服务端点,可通过 HTTP 调用程序代理访问。 HttpInvokerProxyFactoryBean 是 HTTP 调用代理的工厂 bean。

Hessian

Hessian 提供了一种基于 HTTP 的二进制远程处理协议。 Spring 通过 HessianProxyFactoryBeanHessianServiceExporter 支持 Hessian。

Burlap

Burlap 是 Caucho 基于 XML 的 Hessian 替代品。 Spring 提供了 BurlapProxyFactoryBeanBurlapServiceExporter 等支持类。

JAX-RPC

Spring 通过 JAX-RPC(J2EE 1.4 的 Web 服务 API)为 Web 服务提供远程支持。

JAX-WS

Spring 通过 JAX-WS(Java EE 5 和 Java 6 中引入的 JAX-RPC 的继任者)为 Web 服务提供远程支持。

JMS

Spring 中的 JMS 远程处理支持由 JmsInvokerServiceExporterJmsInvokerProxyFactoryBean 类提供。

Spring开发RMI服务

1、创建Maven项目

image.png

2、Pom文件添加依赖

<dependencies>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-core</artifactId>
        <version>${spring.version}</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>${spring.version}</version>
    </dependency>
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
    </dependency>
<dependencies>
复制代码

3、添加实体类

@Data
public class User implements Serializable {
    private long id;
    private String name;
    private String userName;
}
复制代码

4、添加存放用户信息的本地缓存接口

public interface ICacheService {
    ConcurrentMap<Long, User> getUserMap();
}
复制代码

5、存放用户信息的本地缓存接口实现类

public class CacheServiceImpl implements ICacheService {

    // 使用ConcurrentHashMap存放用户信息
    private ConcurrentHashMap<Long, User> userMap;

    @Override
    public ConcurrentHashMap<Long, User> getUserMap() {
        return userMap;
    }

    public void setUserMap(ConcurrentHashMap<Long, User> userMap) {
        this.userMap = userMap;
    }
}
复制代码

6、添加用户操作接口

public interface IRMIUserService {

    public boolean addUser(User user);

    public boolean deleteUser(User user);

    public List<User> getUserList();
}
复制代码

7、用户操作接口实现类

@Slf4j
public class RMIUserServiceImpl implements IRMIUserService {

    ICacheService cacheService;

    @Override
    public boolean addUser(User user) {
        getCacheService().getUserMap().put(user.getId(), user);
        log.debug("添加用户到缓存,用户信息 = {}", getCacheService().getUserMap().get(user.getId()));
        return true;
    }

    @Override
    public boolean deleteUser(User user) {
        getCacheService().getUserMap().put(user.getId(), user);
        log.debug("用户: {},已经从缓存删除 " , user);
        return true;
    }

    @Override
    public List<User> getUserList() {
        List<User> list = new ArrayList<>(getCacheService().getUserMap().values());
        log.debug("用户列表 = {}", list);
        return list;
    }

    private ICacheService getCacheService() {
        return cacheService;
    }

    public void setCacheService(ICacheService cacheService) {
        this.cacheService = cacheService;
    }
}
复制代码

8、RMI服务端

public class RMIServer {
    public static void main(String[] args) {
        new ClassPathXmlApplicationContext("rmiServerAppContext.xml");
    }
}
复制代码

9、RMI服务端XML配置

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans

http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">

    <bean id="UserMap" class="java.util.concurrent.ConcurrentHashMap" />

    <bean id="CacheService" class="com.rameo.rmi.CacheServiceImpl">
        <property name="userMap" ref="UserMap"/>
    </bean>

    <bean id="RMIUserService" class="com.rameo.rmi.RMIUserServiceImpl" >
        <property name="cacheService" ref="CacheService"/>
    </bean>

    <!-- 声明 RMI Server -->
    <bean class="org.springframework.remoting.rmi.RmiServiceExporter">

        <!-- serviceName 表示 RMI 服务名称 -->
        <property name="serviceName" value="rmiUserService"/>

        <!-- service 表示 RMI 对象 -->
        <property name="service" ref="RMIUserService"/>

        <!-- serviceInterface 表示暴露的 RMI 服务接口 -->
        <property name="serviceInterface" value="com.rameo.rmi.IRMIUserService"/>

        <!-- 注册端口 1099 -->
        <property name="registryPort" value="1099"/>
    </bean>
</beans>
复制代码

10、RMI客户端

@Slf4j
public class RMIClient {
    public static void main(String[] args) {

        log.debug("RMI Service Client is starting...");

        ApplicationContext context = new ClassPathXmlApplicationContext("rmiClientAppContext.xml");

        // 远程用户服务通过 RMI 客户端应用程序上下文调用
        IRMIUserService rmiClient = (IRMIUserService) context.getBean("rmiUserService");

        User user1 = new User();
        user1.setId(1);
        user1.setName("张三");
        user1.setUserName("zhangsan");

        User user2 = new User();
        user1.setId(2);
        user1.setName("李四");
        user1.setUserName("lisi");

        // 通过远程调用添加用户到缓存
        rmiClient.addUser(user1);
        rmiClient.addUser(user2);

        // 通过远程调用从缓存获取用户列表
        rmiClient.getUserList();

        // 通过远程调用从缓存删除用户
        rmiClient.deleteUser(user1);
        rmiClient.deleteUser(user2);

        log.debug("RMI Service Client is stopped...");
    }
}
复制代码

11、RMI客户端XML配置

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans

http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">

    <!-- 声明 RMI Client -->
    <bean id="rmiUserService" class="org.springframework.remoting.rmi.RmiProxyFactoryBean">
        <!-- serviceUrl 表示 RMI server 调用地址 -->
        <property name="serviceUrl" value="rmi://127.0.0.1:1099/rmiUserService"/>

        <!-- serviceInterface 表示 RMI server 接口调用 -->
        <property name="serviceInterface" value="com.rameo.rmi.IRMIUserService"/>

        <property name="refreshStubOnConnectFailure" value="true"/>
    </bean>
</beans>
复制代码

12、启动RMI服务端和客户端

启动RMI服务端

image.png

启动RMI客户端

image.png

13、查看RMI服务端接口被调用的日志

image.png

总结

通过调用日志可以看到,服务端通过 RMI registry 暴露了一个服务地址,端口为1099。

客户端通过 rmi 协议,调用 rmi://127.0.0.1:1099/rmiUserService 地址,远程调用服务端接口。

猜你喜欢

转载自juejin.im/post/7035960327376207885
今日推荐