之前已经写过一篇关于class的动态替换博客,今天我们来介绍一下如何用springloaded进行jar&class的动态替换。

首先说一下实验过程,结合了目前我正在做的项目,这个项目是一个前置系统,分别对接银联和核心系统。项目一开始由一个jar包组成,逻辑上可以分为3层:分发层,业务处理层,dao层(数据库操作相关),所有的class文件最后都在jar包中,运行时,只要启动这个jar包就行了,它是一个进程,会启动一个监听端口用来接收银联发送过来的报文。

这样做的缺点:后期你要修改代码,哪怕只有一行代码修改,你也要重新打包成jar包,kill掉正在运行的进程,然后重新启动!一开始对于我这种菜鸟,除了觉得这样做很麻烦之外,其他也没有觉得什么。后来,仔细一分析,在生产上运行,你停服务,是一件不可思议的事,因为所有的交易都要停止,像对于支付这样的交易,那影响就太大了!

所以,自然想到热部署方案,热部署网上也有一些相关的博客。但基本都不太“正规”,即都是那种简单的例子,看起来就不大可行。其中比较多的是自己定义classload来重新加载class文件,而且我看那些方法中路径和要重新加载的class文件都是写死的,这也太。。。当然,也有我觉得比较高大上的方法,就是将现在的系统改造成微服务架构,对于业务上独立的交易都改造成一个个微服务,那要卸载服务,重新部署服务自然都不在话下。不得不说,这确实是一个比较好的方法,但工作量和难度都是比较高的,想来想去,暂时不考虑,但会作为知识储备来学习,在适当的时间再来改造,因为这是趋势!

直到前几天,我偶然发现一个关于springloaded的帖子,这种方法比较简单,而且从名字可以看成,它是spring旗下的一个项目,应该来说还是比较可靠的,所以就试着用这个方法来进行改造,改造的方法也比较简单。

首先,我们要将jar包中的一些业务相关的代码从jar包中抽离出来,具体拆分的方法可以为,基本不需要修改的代码或者框架型的代码放在jar包中,而后期需要经常修改的代码从jar包冲分离出来。如下图:

所有的业务相关的代码(class文件)都放在business文件夹下,具体做法是创建了一个新的工程,然后现有的工程会依赖这个新的工程。同时,可以看到相关的配置文件我们也从jar包中分离出来,比如mybatis文件夹中放的是和数据库操作相关的文件。

我们在libs文件夹中放入

然后,输入命令:

这里插播一下,一开始我是上面这种写法,但是发现jar替换时不起任何效果,后来我想会不会是顺序的问题,我把-jar后面的参数移到最后面,发现这时候起作用了:

然后参数verbose可以省略,因为加上这个参数,日志中会有很多详细的信息,生产上不太方便查看,测试的时候可以加上。

我们发起一笔报文,前置系统运行结果如下:

我们对这个交易的代码进行修改,把“协议支付签约触发短信”这几个字去掉,然后保存,用这个class文件替换原先的class文件

可以看到,在不用停程序的情况下,运行结果已经改变了,基本达到我们的需求。

接下来的话就是,如果jar包里面的代码有修改,那就重新打包来替换旧的jar包,与替换class文件类似,我试了一下,同样是可以的。

2018-07-25更新

今天我在生产上试了一种情况,发现更换了class没有用,比如:a.jar直接调用了b.class,而b.class又调用了c.class,现在替换了c.class文件,发现不起作用。我们上面的例子是替换了b.class文件起作用。只有重启,c.class文件才起作用。这个问题后续值得继续关注!

利用springloaded进行java jar&class的动态替换的更多相关文章

  1. 利用springloaded进行java class动态替换

    我们知道对于一个java文件,如Test.java,首先需要通过javac命令(javac Test.java)进行编译,生成class文件,再将class文件在jvm上进行加载运行,也就是java命 ...

  2. 【java】 linux下利用nohup后台运行jar文件包程序

    Linux 运行jar包命令如下: 方式一: java -jar XXX.jar 特点:当前ssh窗口被锁定,可按CTRL + C打断程序运行,或直接关闭窗口,程序退出 那如何让窗口不锁定? 方式二 ...

  3. 使用C#利用cmd来调用java jar包获取其中的数据

    其实也很简单,就是在C#中构建一个Process,启动jar包,并且给jar包传递参数 因为我并没有怎么学过JAVA,所以只写了个很小的Demo,就是根据传入的参数获取对应的数据 以下是JAVA De ...

  4. java -jar参数运行方式设置classpath

    转载自:https://www.cnblogs.com/aggavara/archive/2012/11/16/2773246.html 当用java -jar yourJarExe.jar来运行一个 ...

  5. Java安全之Javassist动态编程

    Java安全之Javassist动态编程 0x00 前言 在调试CC2链前先来填补知识盲区,先来了解一下Javassist具体的作用.在CC2链会用到Javassist以及PriorityQueue来 ...

  6. 【hadoop2.6.0】利用Hadoop的 Java API

    Hadoop2.6.0的所有Java API都在 http://hadoop.apache.org/docs/r2.6.0/api/overview-summary.html 里. 下面实现一个利用J ...

  7. -Xbootclasspath参数、java -jar参数运行应用时classpath的设置方法

    当用java -jar yourJarExe.jar来运行一个经过打包的应用程序的时候,你会发现如何设置-classpath参数应用程序都找不到相应的第三方类,报ClassNotFound错误.实际上 ...

  8. 利用sfntly的sfnttool.jar提取中文字体

    雨忆博客中提到了sfntly(具体介绍可以看:https://code.google.com/p/sfntly/),利用其中sfnttool.jar就可以提取只包含指定字符的字体,如果想在页面中通过@ ...

  9. 【项目分析】利用C#改写JAVA中的Base64.DecodeBase64以及Inflater解码

    原文:[项目分析]利用C#改写JAVA中的Base64.DecodeBase64以及Inflater解码 最近正在进行项目服务的移植工作,即将JAVA服务的程序移植到DotNet平台中. 在JAVA程 ...

随机推荐

  1. select2 清除选中项解决办法

    在项目中使用select2:选中项 设置可清除. 代码中加上了allowClear : true $.get("/Work/Ajax/Select.ashx", function ...

  2. Linux之文件(目录)默认权限、特殊权限与隐藏权限

    文件默认权限 从Linux之用户组.文件权限详解了解到文件与目录的基本权限管理,文件在创建时如果不指定具体的权限,那么系统会给它分配一个默认的权限,这个默认权限就是umask. vbird@Ubunt ...

  3. 如何在Windows命令行(DOS界面)中调用 编译器 来编译C/C++源程序

    首先说明一下背景: 为什么要在DOS界面编译C/C++源程序?有很多现成的开发环境(IDE)如:vs, vc++等,这些开发环境集成了编译,调试,使用起来很方便,而且图形化操作界面,简洁明了.但是在开 ...

  4. Python 输出

    普通的输出 生活中的“输出”: 软件中的“输出”: python中变量的输出: print('hello world') 格式化输出 占位符% print('Hello,%s' % 'Python') ...

  5. for批处理skip参数不支持变量延迟!n!的解决办法

    a.txt 文件a第1行 文件a第2行 文件a第3行 b.txt 文件b第1行 文件b第2行 文件b第3行 合并ab .bat @echo off REM 把两个文件逐行合并成一列 set n=0 f ...

  6. jenkins 可以设置最多执行并发执行多少个

    系统-系统配置

  7. 铁板纹理 Base Shape

    软件:Substance Designer 2017.1.2 最近正在根据官方的教程,学习Metal Rust纹理的制作.这篇文章仅记录Base Shape的制作方法. Base Shape最终渲染效 ...

  8. Android倒计时实现

    Android为我们封装好了一个抽象类CountDownTimer,可以实现计时器功能: /** * 倒数计时器 */ private CountDownTimer timer = new Count ...

  9. linux上用route添加/删除路由

    1. 查看 route -n 2. 添加 route add -net 9.123.0.0 netmask 255.255.0.0 gw 9.123.0.1 3. 删除 route del -net ...

  10. leetcode200

    深度优先搜索,每次遇到1,则岛的数量+1,从这个1开始找到所有相连的1,将其改为0. public class Solution { private void dfsSearch(char[,] gr ...