刚才我还在家楼下遛弯儿,突然手机响了,是我们组小王在群里问,说哥你会不会用Groovy搞SpringBoot的动态编程,就是那种能动态加功能、不重启还能在线修改业务逻辑的那种骚操作,我一听这话有点意思,赶紧回家开电脑琢磨了半小时...现在赶紧跟你们说说,怕忘了。
其实吧,Groovy你们都知道吧?写起来跟Java一个德性,但是就是懒得写getter/setter那种,变量声明随便来,动态能力爆炸。我第一次在SpringBoot项目里玩Groovy还是前年晚上加班,有个需求老是变,搞得后端同学怨声载道。我说,咱别发版了,要不直接搞个Groovy脚本引擎,业务逻辑热更新,谁还管你需求怎么改。
当时那个需求就是要按配置文件动态加载促销规则,不能重启。其实你用Java做也不是不行,啥反射、策略模式,但代码全得重新发版,风险贼大。我就偷偷上了Groovy。代码写死太Low了,直接上GroovyShell,脚本全放DB或者本地文件,定时热加载,真有问题你下线脚本不就得了。
比如说,你业务里有个活动规则,按Java写死大概就是:
public class PromotionService {
public int calculateDiscount(int price) {
// 规则写死,变起来头疼
if (price > 100) return 20;
return 5;
}
}
但是用Groovy就完全不一样,我给你看看当时咋整的:
import groovy.lang.GroovyShell;
public class PromotionGroovyService {
private GroovyShell shell = new GroovyShell();
public int calculateDiscount(int price) {
String script = "if(price > 100) return 20 else return 5";
shell.setVariable("price", price);
Object result = shell.evaluate(script);
return (int) result;
}
}
这个效果你明白吧?只要业务方给你一个脚本,甚至你可以让他们自己写规则,只要别把系统玩炸了,直接一遍一遍试脚本,线上也能改。等于Java变成“壳”,Groovy是“心脏”,脚本就是“灵魂”,咋说呢,灵活得很。
SpringBoot集成Groovy,真没多麻烦
你要真问怎么接,没啥难的,SpringBoot加个Groovy依赖呗:
<groupId>org.codehaus.groovy</groupId>
<artifactId>groovy</artifactId>
<version>4.0.13</version>
正常写个Service注入进去就行,很多人问GroovyShell会不会有线程安全问题,答:你别用一个Shell全局复用就行,每次new一个或者搞线程本地(ThreadLocal),怕内存泄漏你可以定时清理一下shell。
而且Spring还自带GroovyScriptFactory这种玩意,Spring官方自己也用Groovy写了一堆动态Bean,那玩法贼多。
说点坑和注意的地方
之前我就遇到过,Groovy脚本能不能随便让业务方乱写?理论上能,但你得加沙箱机制,不然万一写个System.exit(0),公司主站直接拜拜了...还有就是脚本里要用到Java对象怎么办?你得提前塞到shell上下文里,比如:
shell.setVariable("order", order);
脚本就能直接用order.getAmount()那种写法了,业务要啥给啥,随便玩。
另外说个小插曲,上次我加班写完Groovy热加载,刚部署完老大说要改个规则,业务妹子直接在页面上贴了个新脚本点保存,服务一点事没有直接生效了,她当场喊我“技术大神”,我那天回家都笑出声了...不过第二天又有需求改,这年头后端太难了。
怎么说呢,Groovy玩起来真香,尤其是SpringBoot这类Java框架,你要是场景需要灵活变更、业务规则频繁变,Groovy绝对可以用一用。只是你要记得脚本安全别放飞,热加载一定搞好隔离,要不然运维哥们给你电话轰炸,那滋味太酸爽了。
还有人问性能咋样,其实你别大规模用在高频业务就还行,Groovy Shell编译会慢点,但热编译好了以后,后面执行速度其实不慢。像促销、风控、一些定制化规则都很适合。