关于 Java 类加载和 Springboot Bean 动态加载的一点想法

2021-08-07 15:54:57 +08:00
 EscYezi

最近遇到一个情况,需要修改数据库里的一些数据,这些数据是用 json 形式保存的,要给某些 key 对应的 value+1.如果用 sql 写会很复杂,如果能用 java 写好程序触发一下拿到结果就好了,但是这样做要发布到正式环境,调试也是非常不方便,每次发布要等好久。

于是想到用户 java 的自定义类加载器和 springboot 的 bean 动态加载结合起来,提供一个页面,在本地写好代码,copy 到页面上,点击运行就可以生效。有复杂的导出表格需求也可以实现。(明明当初做管理端的时候弄了那么多数据统计功能,结果还是不能满足业务线的需求)

大概流程是:点击运行后,把输入的代码变成文件流喂给类加载器,加载新定义的类,然后再加载到 spring 的 bean 容器里面,触发一下这个 bean 的运行,拿到结果返回给页面(有点像在线面试题的感觉)。

具体细节感觉还是有很多优化的点,想问下有没有类似的现成的工具?最好能和 springboot 结合起来,毕竟复杂逻辑还是要依靠已存在的一些 bean 。(如果没有的话就尝试糊一个好了 2333 )

2725 次点击
所在节点    Java
20 条回复
crclz
2021-08-07 16:17:35 +08:00
你用这么 hack 的东西,还不如把正式环境暴露给你的开发机呢。
Cbdy
2021-08-07 16:17:37 +08:00
不用这么麻烦,你可以直接在服务端解释执行一些代码,JVM 上本身就支持一些脚本语言(甚至是 Java ),

可以看这个例子:
https://github.com/cbdyzj/lib17/blob/master/repositories/boot/src/main/java/org/jianzhao/boot/service/ScriptService.java

当然,你也可以动态加载类去做,比如用 java.net.URLClassLoader
857681664
2021-08-07 16:29:23 +08:00
用 mysql 的 json 函数会非常复杂吗,我都是用 sql 迁移 json 字段的
EscYezi
2021-08-07 16:40:05 +08:00
@crclz 我倒是想直连正式环境,但是不太可能😂
EscYezi
2021-08-07 16:42:17 +08:00
@857681664 公司用的 mysql 版本有点低,不支持 json 类型字段🌚
EscYezi
2021-08-07 16:45:05 +08:00
@Cbdy 直接能写脚本那就更好了,我研究研究
857681664
2021-08-07 16:45:39 +08:00
@EscYezi 那我觉得你可以通过网络或者文件的方式的方式用类加载器加载 class
cp19890714
2021-08-07 16:48:23 +08:00
完全不是新鲜玩意,tomcat 动态加载 war 包。
或者用 js,java 自带 js 引擎。
Suddoo
2021-08-07 18:53:43 +08:00
MySQL 5.7 就支持 JSON 操作了,比这还低?
jorneyr
2021-08-07 22:21:11 +08:00
Spring 里面调用 groovy 做这些也可以,groovy 兼容 Java 。
lonenol
2021-08-07 22:34:58 +08:00
功能很简单。。直接用 java 代码,也能编译成 class 文件,然后去执行都行。。
不过最好不要这么做,太容易出问题。。万一没兜住,给线上表来了个全量更新啥的,哭都没地方哭
securityCoding
2021-08-08 13:30:13 +08:00
这样,你搭建一个分布式调度平台,比如 xxl-job 。大部分都提供了动态运行代码功能。
ljzxloaf
2021-08-08 15:02:47 +08:00
动态加载 class 不是什么难事,但是你这样不是等于直接上生产调试?理论上你可以把所以的业务逻辑都弄成动态的,问题是必要性在哪? OSGI 发展这么久为什么被 JPMS 干掉了,因为它所谓的热部署 /热替换根本没啥必要。Web 服务都是集群,无损上下线简单得很,要啥热部署 /热替换。

“但是这样做要发布到正式环境,调试也是非常不方便,每次发布要等好久” 这是啥理由,造点数据调试不就行了。

如果只是偶尔手动修改数据,直接用 sql 。如果经常需要手动修改数据,那应该反思的是,为啥要手动修改数据,用户的数据我们没有权限修改,除非是 bug 。
ljzxloaf
2021-08-08 15:07:30 +08:00
@ljzxloaf #13 正常的业务需求走开发测试部署流程,不正常的需求也尽量走正常流程,除非你 100%能 hold 住。你这么玩是否定了测试的价值。
EscYezi
2021-08-09 14:59:35 +08:00
@ljzxloaf 有道理,这个东西放在公司项目上用确实有风险,还是自己研究着玩玩吧
fengpan567
2021-08-10 18:05:32 +08:00
生产环境这么玩铁定会出事故
hcen1997
2021-08-12 11:29:04 +08:00
生产环境暴露动态代码加载过不去安全检查吧?
这个需求就是普通的更改数据嘛, 不过数据不是简单的一个字段, 而是字段->json-> 字段的形式

那只需要在 dao 层加入一个 json 地址解析就行了啊
+1 需求的功能接口加一个字段 : jsonPath
对于上层应用还是调用 字段加 1 的函数
但是对于 dao 层, 先获取 json 字符串, 解析, 根据 jsonPath 更新数据, 转回 json 字符串, -> 存回数据库

我觉得分层抽象的原理用在这个需求上刚刚好
EscYezi
2021-08-12 12:20:41 +08:00
@hcen1997 这也是个思路,不过为什么不直接传递 json 而要传递 json 地址呢
hcen1997
2021-08-12 13:20:07 +08:00
@EscYezi json 地址是指 对象中字段的地址
比如 数据库中存了 '{"t1":{"t2":1}}'
那么 json 地址就是 t1.t2
调用完函数后, 数据库中的值就会变成
'{"t1":{"t2":2}}'

为啥不直接传递 json? 随意啊, 想怎么写怎么写,
aguesuka
2021-08-13 11:41:39 +08:00
osgi 是编程语言发展的弯路, 不要开倒车

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/794288

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX