Java Spring RMI一些尝试

简介: 最近在做一个调度服务器的项目,因为各个服务器上面的定时任务比较多,分别执行的话运维检查起来比较麻烦.就想到搞一个专门的调度服务器来统一管理这些任务.因为随时可能增加新的服务器或者新的命令,要是全写在一起每次要把整个程序替换掉,上线不方便.

最近在做一个调度服务器的项目,因为各个服务器上面的定时任务比较多,分别执行的话运维检查起来比较麻烦.就想到搞一个专门的调度服务器来统一管理这些任务.因为随时可能增加新的服务器或者新的命令,要是全写在一起每次要把整个程序替换掉,上线不方便.发现spring可以很好的解决这个问题,新加的程序可以以单独jar包的方式添加,只需要修改ApplicationContext就行了,client端只需要改配置就行了程序可以不用改.个人感觉spinrg自身的RMI类比Java自带的好理解一些.

首先是Server端,需要有一个启动函数,以及各命令对应的实现接口,启动类 .为了部署方便期间,配置文件路径直接改外部输入了

public class StartRMIServer {
    public static void startRMIServer(String path) {
        if(path != null && path.startsWith("/")) {
            new FileSystemXmlApplicationContext("/" + path + "applicationContext.xml");
        }else{
            new FileSystemXmlApplicationContext(path + "applicationContext.xml");
        }
        System.out.println("RMI服务端启动!!!");
    }

    public static void main(String[] args) {
        startRMIServer(args[0]);
    }
}

 关于FileSystemXmlApplicationContext这里一开始不知道,在Linux下输入的根路径会被当成当前路径处理,去查了之后发现是构造函数会把第一个'/'给去掉,所以这里需要加上.也可以用ClassPathXmlApplicationContext直接以file:开头

然后加入接口和实现类,当客户端发起命令时就会调用该接口,接口对应的实现类由spring定义文件来控制,所以就能够实现不同的命令对应不同的实现类.这里定义了两个不同的实现类

public interface IRmiService{
    String getMsg(String params) throws Exception;
}

 调用的类预留一个字符串参数,便于有需要的实现类解析后使用

public class HelloWordService implements IRmiService{
    public String getMsg(String params) throws Exception{
        return "Hello World!"; 
    }
}


public class RealTimeService implements IRmiService {
    public String getMsg(String params){
        return "Real Time!" +  params; 
    }
}

ApplicationContext配置定义如下,两个实现类分别对应不同的命令

   <!-- 定义接口实现类 --> 
    <bean id="helloWordService" class="com.cmb.SpringRmi.HelloWordService" scope="prototype"/> 
   
   <!-- 定义服务端接口 -->
    <bean class="org.springframework.remoting.rmi.RmiServiceExporter">
        <!-- 将远程接口实现类对象设置到RMI服务中 -->
        <property name="service" ref="helloWordService" />
        <!-- 设置RMI服务名,将作为RMI客户端的调用接口-->
        <property name="serviceName" value="helloWord" />
        <!-- 将远程接口设置为RMI服务接口 -->
        <property name="serviceInterface" value="com.cmb.SpringRmi.IRmiService" />
        <!-- 为RMI服务端远程对象注册表设置端口号-->
        <property name="registryPort" value="9090" />
    </bean>

   <bean id="realTimeService" class="com.cmb.SpringRmi.RealTimeService" scope="prototype"/>
    <bean class="org.springframework.remoting.rmi.RmiServiceExporter">
        <property name="service" ref="realTimeService" />
        <property name="serviceName" value="realTime" />
        <property name="serviceInterface" value="com.cmb.SpringRmi.IRmiService" />
        <property name="registryPort" value="9090" />
    </bean>

 这样server端就配置完成了,可以直接启动试一下

 

client端相当于是每次给server发一个请求命令,server端接收到之后去执行对应的实现类.我这边实现类加了log4j功能,参数是context路径,命令和命令对应的参数

public class RMIClient {
    public static void main(String[] args) {
        ApplicationContext ctx = new ClassPathXmlApplicationContext("file:" + args[0] + "/applicationContext.xml");
        IRmiServer helloWord = (IRmiServer) ctx.getBean(args[1]);
        LogBean log = (LogBean) ctx.getBean("log");
        PropertyConfigurator.configure(log.getPath());
        Logger logger = Logger.getLogger(RMIClient.class);
        logger.info("Call " + args[1]);
        try {
            String params = "";
            if (args.length > 2 && args[2] != null && !"".equals(args[2])) {
                params = args[2];
            }
            logger.info(helloWord.getMsg(params));
            logger.info(args[1] + " succeed");
        } catch (Exception e) {
            e.printStackTrace();
            logger.error(e.getMessage(), e);
            System.exit(1);
        }
    }
}

 接口名字其实不需要和server端一样

public interface IRmiServer{
    String getMsg(String params) throws Exception;
}

spring设置如下,这里设置了两条命令helloWorld和printDate,分别对应类HelloWordService和RealTimeService

    <!--bean id为程序调用时输入的第一参数-->    
    <bean id="helloWord" class="org.springframework.remoting.rmi.RmiProxyFactoryBean"> 
        <!--ip和端口为server的ip和刚才注册的端口号,服务名为设置的serviceName-->
        <property name="serviceUrl" value="rmi://localhost:9090/helloWord"/>
        <!--调用的接口-->
        <property name="serviceInterface" value="com.cmb.SpringRmiClient.IRmiServer"/>
        <!-- 当连接失败时是否刷新远程调用stub -->
        <property name="refreshStubOnConnectFailure" value="true"/>
    </bean>
    
    <bean id="printDate" class="org.springframework.remoting.rmi.RmiProxyFactoryBean"> 
        <property name="serviceUrl" value="rmi://localhost:9090/realTime"/>
        <property name="serviceInterface" value="com.cmb.SpringRmiClient.IRmiServer"/>
        <property name="refreshStubOnConnectFailure" value="true"/>
    </bean>

此时就可以执行client,可以看到如果输入的命令不同,打印出的结果是不同的,说明调用的实现类不同.

部署的时候采用命令行指定java.ext.dirs的方式,这样可以把所有相关的程序jar包都放到文件夹里面,便于后续扩展程序的部署.

java -Djava.ext.dirs="rmiclient/lib" -jar rmiclient/rmiclient.jar D:/test/rmiclient printDate

关于后续添加部署.我现在想要添加一个程序,那么应该把这个jar包放置到server上的lib目录中,把server进程结束,然后在server的ApplicationContext增加一组bean,client的ApplicationContext也对应增加一组,重启之后就可以使用新的程序了.

 通过这个小工具的开发对spring工厂和IOC有了些了解,后面要多研究吃透spring

个人GitHub地址: https://github.com/GrayWind33
相关文章
|
9天前
|
监控 Java 数据库
从零学 Dropwizard:手把手搭轻量 Java 微服务,告别 Spring 臃肿
Dropwizard 整合 Jetty、Jersey 等成熟组件,开箱即用,无需复杂配置。轻量高效,启动快,资源占用少,内置监控、健康检查与安全防护,搭配 Docker 部署便捷,是构建生产级 Java 微服务的极简利器。
57 0
|
2月前
|
前端开发 Java 开发者
Java新手指南:在Spring MVC中使用查询字符串与参数
通过结合实际的需求和业务逻辑,开发者可以灵活地利用这些机制,为用户提供更丰富而高效的Web应用体验。
75 15
|
3月前
|
JSON 前端开发 Java
Java新手指南:如何在Spring MVC中处理请求参数
处理Spring MVC中的请求参数是通过控制器方法中的注解来完成的。这些注解包括 `@RequestParam`, `@PathVariable`, `@ModelAttribute`, `@RequestBody`, `@RequestHeader`, `@Valid`, 和 `@RequestMapping`。使用这些注解可以轻松从HTTP请求中提取所需信息,例如URL参数、表单数据或者JSON请求体,并将其转换成Java对象以供进一步处理。
210 17
|
3月前
|
安全 Java 微服务
Java 最新技术和框架实操:涵盖 JDK 21 新特性与 Spring Security 6.x 安全框架搭建
本文系统整理了Java最新技术与主流框架实操内容,涵盖Java 17+新特性(如模式匹配、文本块、记录类)、Spring Boot 3微服务开发、响应式编程(WebFlux)、容器化部署(Docker+K8s)、测试与CI/CD实践,附完整代码示例和学习资源推荐,助你构建现代Java全栈开发能力。
378 0
|
2月前
|
Cloud Native Java API
Java Spring框架技术栈选和最新版本及发展史详解(截至2025年8月)-优雅草卓伊凡
Java Spring框架技术栈选和最新版本及发展史详解(截至2025年8月)-优雅草卓伊凡
291 0
|
4月前
|
IDE Java 数据库连接
解决Java环境中无法识别org.mybatis.spring.annotation.MapperScan的问题。
祝你好运,在这场MyBatis的魔法冒险中获得胜利!记住,魔法书(官方文档)永远是你最好的朋友。
289 18
|
3月前
|
Java 数据库连接 API
Java 8 + 特性及 Spring Boot 与 Hibernate 等最新技术的实操内容详解
本内容涵盖Java 8+核心语法、Spring Boot与Hibernate实操,按考试考点分类整理,含技术详解与代码示例,助力掌握最新Java技术与应用。
109 2
|
6月前
|
前端开发 Java 物联网
智慧班牌源码,采用Java + Spring Boot后端框架,搭配Vue2前端技术,支持SaaS云部署
智慧班牌系统是一款基于信息化与物联网技术的校园管理工具,集成电子屏显示、人脸识别及数据交互功能,实现班级信息展示、智能考勤与家校互通。系统采用Java + Spring Boot后端框架,搭配Vue2前端技术,支持SaaS云部署与私有化定制。核心功能涵盖信息发布、考勤管理、教务处理及数据分析,助力校园文化建设与教学优化。其综合性和可扩展性有效打破数据孤岛,提升交互体验并降低管理成本,适用于日常教学、考试管理和应急场景,为智慧校园建设提供全面解决方案。
397 70