spring + groovy 实现动态代码注入执行

简介: 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

大功告成。尽情玩耍吧

目录
相关文章
|
1月前
|
XML Java 开发者
Spring Boot中的bean注入方式和原理
Spring Boot中的bean注入方式和原理
39 0
|
3月前
|
Java 程序员 Spring
Spring5深入浅出篇:Spring对象属性注入详解
Spring5深入浅出篇:Spring对象属性注入详解
|
3月前
|
Ubuntu Java Linux
在Spring Boot中使用iTextPDF创建动态PDF文档
iTextPDF 是一个用于创建和操作 PDF(Portable Document Format)文档的流行的 Java 库。它提供了一套全面的功能,用于处理 PDF 文件,包括创建新文档、修改现有文档以及提取信息。
84 1
|
3月前
|
移动开发 前端开发 Java
使用ipaguard插件对Spring Boot程序进行代码混淆
使用ipaguard插件对Spring Boot程序进行代码混淆
46 0
|
10天前
|
安全 数据安全/隐私保护
Springboot+Spring security +jwt认证+动态授权
Springboot+Spring security +jwt认证+动态授权
|
6天前
|
JSON Java 数据库连接
属性注入掌握:Spring Boot配置属性的高级技巧与最佳实践
属性注入掌握:Spring Boot配置属性的高级技巧与最佳实践
13 1
|
1月前
|
存储 Java 关系型数据库
Spring Batch学习记录及示例项目代码
Spring Batch学习记录及示例项目代码
|
1月前
|
XML Java 数据格式
解释Spring中一个bean的注入过程
解释Spring中一个bean的注入过程
|
2月前
|
Java Spring
Spring 使用注解注入失败,调用内容时提示空指针
Spring 使用注解注入失败,调用内容时提示空指针
14 0
|
2月前
|
Java Spring
Spring注入类的两种形式
Spring注入类的两种形式
49 0
Spring注入类的两种形式