spring + groovy 实现动态代码注入执行
昨天线上的代码调用一个远程的服务无缘无故不成功,又没加那么多日志,不好定位问题,好想在线上执行一下代码,打印点log看看
于是想着怎么动态执行点java代码,忽然想起以前玩过的groovy,于是搞起来
大概思路是这样,写一个控制器,接收一段代码,动态执行,然后返回执行结果,切记,做好权限控制,免得杯具
没想到实现起来异常简单
1、gradle.build加入groovy依赖
compile "org.codehaus.groovy:groovy:2.5.3"
2、写个工具类,方便拿到spring上下文对象,这个很常见
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
public class SpringContextUtils implements ApplicationContextAware {
static ApplicationContext context;
@Override
public void setApplicationContext(ApplicationContext context)
throws BeansException {
SpringContextUtils.context = context;
}
public static ApplicationContext getContext() {
return context;
}
public static void autowireBean(Object bean) {
context.getAutowireCapableBeanFactory().autowireBean(bean);
}
public static <T> T getBean(Class<T> clazz) {
return context.getBean(clazz);
}
}
3、写个控制器
import com.ruizton.util.SpringContextUtils;
import groovy.lang.GroovyClassLoader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.lang.reflect.Method;
@RestController
public class GroovyController {
@RequestMapping("/runScript")
public Object runScript(String script) throws Exception {
if (script != null) {
// 这里其实就是groovy的api动态的加载生成一个Class,然后反射生成对象,然后执行run方法,最后返回结果
// 最精华的地方就是SpringContextUtils.autowireBean,可以实现自动注入bean,
Class clazz = new GroovyClassLoader().parseClass(script);
Method run = clazz.getMethod("run");
Object o = clazz.newInstance();
SpringContextUtils.autowireBean(o);
Object ret = run.invoke(o);
return ret;
} else {
return "no script";
}
}
}
上面是java的全部内容了,接下来就是调用了
首先准备写个test.groovy代码
import org.springframework.beans.factory.annotation.Autowired
class Foo {
@Autowired
FooService fooService;
Object run() {
// do something
def f = fooService.findById(38);
if (f != null) {
return f.name
}
return null
}
}
不写类直接写代码块也是可以的
test.groovy
def sum = 1 + 2
return "sum = " + sum
上面代码也会生成一个Class对象,里面的代码默认在run方法下面,所以控制器哪里都是调用的run方法
再写个python调用一个接口,其实就是读文件然后调用一下java的接口,要是不怕死,也可以在后台做一个可视化界面,加个执行按钮直接调用
test.py
#!/usr/bin/python
import requests
def read(filename):
f = open(filename,'r')
file = f.read()
f.close()
return file
res = requests.post('http://127.0.0.1/runScript.html', data = {
'script': read('test.groovy')
})
print res.text
$ chmod +x test.py
$ ./test.py
大功告成。尽情玩耍吧

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
-
上一篇
C# WPF MVVM QQ密码管家项目(8,完结篇:自动输入QQ号、密码)
原文: C# WPF MVVM QQ密码管家项目(8,完结篇:自动输入QQ号、密码) 目录: 1,界面设计 2,数据模型的建立与数据绑定 3,添加QQ数据 4,修改QQ数据 5,删除QQ数据 6,密码选择输入界面数据绑定 7,对QQ登录界面的自动输入思路分析 8,完结篇:自动输入QQ号、密码 接上篇,获取QQ登录界面句柄、窗口位置、鼠标/键盘操作等都需要用到win32api win32api是windows系统预留的接口,通过接口我们可以实现对系统更加深度地操作。 第1步:获取窗口句柄 win32api获取窗口句柄方法c#代码: #region 查找窗口句柄 [DllImport("user32.dll", SetLastError = true)] public static extern IntPtr FindWindow(string lpClassName, string lpWindowName); #endregion 有两个参数可以填,第一个lpClassName填类名,第二个lpWindowName填窗口名。也就是说可以通过类名或者窗口名获得指定窗口的句柄(不填的参数...
-
下一篇
SpringBoot实现Java高并发秒杀系统之Web层开发(三)
SpringBoot实现Java高并发秒杀系统之Web层开发(三) 接着上一篇文章:SpringBoot实现Java高并发之Service层开发,今天我们开始讲SpringBoot实现Java高并发秒杀系统之Web层开发。 Web层即Controller层,当然我们所说的都是在基于Spring框架的系统上而言的,传统的SSH项目中,与页面进行交互的是struts框架,但struts框架很繁琐,后来就被SpringMVC给顶替了,SpringMVC框架在与页面的交互上提供了更加便捷的方式,MVC的设计模式也是当前非常流行的一种设计模式。这次我们针对秒杀系统讲解一下秒杀系统需要和页面交互的操作和数据都涉及哪些? 本项目的源码请参看:springboot-seckill如果觉得不错可以star一下哦(#^.^#) 本项目一共分为四个模块来讲解,具体的开发教程请看我的博客文章: SpringBoot实现Java高并发秒杀系统之DAO层开发(一) SpringBoot实现Java高并发秒杀系统之Service层开发(二) SpringBoot实现Java高并发秒杀系统之Web层开发(三) Spr...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- MySQL数据库在高并发下的优化方案
- SpringBoot2配置默认Tomcat设置,开启更多高级功能
- Windows10,CentOS7,CentOS8安装Nodejs环境
- SpringBoot2整合Redis,开启缓存,提高访问速度
- Linux系统CentOS6、CentOS7手动修改IP地址
- CentOS7编译安装Gcc9.2.0,解决mysql等软件编译问题
- CentOS7编译安装Cmake3.16.3,解决mysql等软件编译问题
- Jdk安装(Linux,MacOS,Windows),包含三大操作系统的最全安装
- 设置Eclipse缩进为4个空格,增强代码规范
- Docker容器配置,解决镜像无法拉取问题