V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
EscYezi
V2EX  ›  Java

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

  •  
  •   EscYezi · 116 天前 · 1556 次点击
    这是一个创建于 116 天前的主题,其中的信息可能已经有所发展或是发生改变。

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

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

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

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

    20 条回复    2021-08-13 11:41:39 +08:00
    crclz
        1
    crclz  
       116 天前
    你用这么 hack 的东西,还不如把正式环境暴露给你的开发机呢。
    Cbdy
        2
    Cbdy  
       116 天前   ❤️ 1
    不用这么麻烦,你可以直接在服务端解释执行一些代码,JVM 上本身就支持一些脚本语言(甚至是 Java ),

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

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

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

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

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

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

    为啥不直接传递 json? 随意啊, 想怎么写怎么写,
    aguesuka
        20
    aguesuka  
       111 天前
    osgi 是编程语言发展的弯路, 不要开倒车
    关于   ·   帮助文档   ·   API   ·   FAQ   ·   我们的愿景   ·   广告投放   ·   感谢   ·   实用小工具   ·   4133 人在线   最高记录 5497   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 21ms · UTC 06:11 · PVG 14:11 · LAX 22:11 · JFK 01:11
    ♥ Do have faith in what you're doing.