欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Runtime.getRuntime().exec执行jar包修改配置文件并替换问题记录

程序员文章站 2022-03-27 13:56:18
微服务结构:子工程依赖父工程,父工程向子工程提供统一配置及公用类,多个子工程依赖同一个父工程。角色定位:这个父工程,是整个应用系统的基础设施。这个基础设施,不是简单的抽取微服务的配置等,还包括了对第三方的组件集成与优化,减少子工程的配置文件,最好达到子工程只需要提供多种环境的yml文件即可而不需要额外的配置文件等。结构依赖图示:为了达到减少子工程的配置文件目的,把子工程所需要的scm.properties配置文件移到父工程中。这带来了一个问题,每个子工程的scm.properties文件...

微服务结构:子工程依赖父工程,父工程向子工程提供统一配置及公用类,多个子工程依赖同一个父工程。

角色定位:这个父工程,是整个应用系统的基础设施。这个基础设施,不是简单的抽取微服务的配置等,还包括了对第三方的组件集成与优化,减少子工程的配置文件,最好达到子工程只需要提供多种环境的yml文件即可而不需要额外的配置文件等。

结构依赖图示:

Runtime.getRuntime().exec执行jar包修改配置文件并替换问题记录

为了达到减少子工程的配置文件目的,把子工程所需要的scm.properties配置文件移到父工程中。

这带来了一个问题,每个子工程的scm.properties文件都是不同的,抽取到父工程时,必然涉及到子工程修改父工程的配置文件,但是,父工程现在已经作为一个jar包已经依赖到子工程中去。通过`Properties`修改的方式并不能达到如期目标,因为jar包中的文件已经是只读的,生成新的`scm.properties`文件是在子工程的目录下。

换另一种思路,就是在系统启动时,紧接着将子工程的`scm.properties`文件通过`jar uvf 带绝对路径的jar包 -C 带绝对路径的子包目录 scm.properties`命令替换父工程的scm.properties文件。

问题一:在本微服务应用中,通过`Runtime.getRuntime().exec`调用上述`jar`命令无效

原因:`Runtime.getRuntime().exec(jar)`的执行与本微服务应用是在通过一个jvm环境中。会看到虽然jar命令执行成功已经被输出到日志中,但实际应用还是启动不起来。原因就是该jar包已经被加载到jvm中。验证是这一原因的方式:把jar命令语句中的带绝对路径的jar包改成不带路径的jar包,系统仍然由读取到scm.properties中的值不对,而报错启动不起来,且输出日志中,也看到jar执行成功的v命令参数信息`正在添加: scm.properties(输入 = 157) (输出 = 145)(压缩了 7%)`。

解决方式:将`Runtime执行jar命令`的调用放到一个独立于本微服务应用中的Java类中,如:

/**
 * 以main方法独立执行系统调用命令
 *
 *
 * @author: 18109115
 * @since: 1.0
 * @see [相关类/方法](可选)
 */

public class ReplaceInstructionJar {

    public static void main(String[] args) {
        String jarName = args[0];
        String directory = args[1];
        System.out.println(" input param " + jarName + " , " + directory);
        String cmd = "jar uvf " + jarName + " -C " + directory + " scm.properties";
        String[] cmds = {"cmd", "/c", cmd};
        try {
            Process process = Runtime.getRuntime().exec(cmds);

            InputStream stream = process.getInputStream();
            InputStreamReader isr = new InputStreamReader(stream, "GBK");
            BufferedReader br = new BufferedReader(isr);
            String line;
            while ((line = br.readLine()) != null) {
                System.out.println(line);
            }
            process.waitFor();
            System.out.println(" end jar command. ");
        } catch (Exception e) {
            System.out.println(e);
        }

    }
}

然后在原来调用jar命令的地方改成`Runtime调用执行java命令,独立运行main方法的方式执行jar包修改并更新配置文件 `的方式(这个java文件必须是已经javac过的,我测试时,是用的断点设置,然后再另一个项目中main启动方式,道理是一样的,使用java命令的时候,别忘记`-classpath `指定该java文件所在的路径):

 

总结:

其实,最简单的方式就是在子工程添加scm.properties文件,这样我司中间件ShardRedis就不会报错,我司中间件ShardRedis使用时是强依赖scm.properties的。不过,为了追寻子工程简化配置文件,才有了jar包修改配置文件的方式。另一种方式Jar包加载卸载没研究过,欢迎有想法并实际应用过的小伙伴私信我或在底下留言,共同进步。

 

 

本文地址:https://blog.csdn.net/qq_21949545/article/details/110224329

相关标签: 工作总结 java