2019-02-27

2019-02-27  本文已影响4人  老柿子

java 调用groovy脚本

调用方式其实是有几种方式,但是每个使用不当都会有一定的问题,因此这里专门进行总结下
一共有两种方式:

  1. 通过GroovyShell调用
  2. 通过GroovyClassLoader调用
  3. 享元工厂方式生成调用

GroovyShell调用

其中我们最常用的是用GroovyShell方式

错误

//这种调用方式是有问题的,会有两个无法清理,一个是InnerLoader对象和脚本Class
@Test
public void testRun() throws InterruptedException {
    GroovyShell shell = new GroovyShell();
    shell.evaluate(getScript());
}

正确

@Test
public void testRun() throws InterruptedException {
    GroovyShell shell = new GroovyShell();
    shell.evaluate(getScript());
    //运行完,记得将内部的缓存清理
    shell.getClassLoader().clearCache();
}

GroovyClassLoader调用

这种调用方式也是我们常用的

错误

//这种调用方式也是有问题的
@Test
public void testRun2() throws InterruptedException {
    GroovyClassLoader loader = new GroovyClassLoader();
    InvokerHelper.createScript(loader.parseClass(getScript()), new Binding()).run();
}

正确

每次调用完之后也需要将缓存清理掉

//这种调用方式也是有问题的
@Test
public void testRun2() throws InterruptedException {
    GroovyClassLoader loader = new GroovyClassLoader();
    InvokerHelper.createScript(loader.parseClass(getScript()), new Binding()).run();
    loader.clearCache();
}

通过工厂方式

通过享元工厂方式达到相同脚本共享问题
1.脚本通过SHA256进行压缩节省空间
2.相同脚本使用以前的脚本
3.脚本执行完成之后清理缓存

/**
 * groovy脚本类享元工厂
 *
 * @author zhouzhenyong
 * @since 2019/1/17 下午7:33
 */
@SuppressWarnings("unchecked")
public class GroovyScriptFactory {
    private static Map<String, Class<Script>> scriptCache = new HashMap<>();
    private GroovyClassLoader classLoader = new GroovyClassLoader();
    private static GroovyScriptFactory factory = new GroovyScriptFactory();

    /**
     * 设置为单例模式
     */
    private GroovyScriptFactory(){}

    public static GroovyScriptFactory getInstance(){
        return factory;
    }

    private Class getScript(String key) {
        // 压缩脚本节省空间
        String encodeStr = EncryptUtil.SHA256(key);
        if(scriptCache.containsKey(encodeStr)){
            return scriptCache.get(encodeStr);
        }else{
            // 脚本不存在则创建新的脚本
            Class<Script> scriptClass = classLoader.parseClass(key);
            scriptCache.put(encodeStr, scriptClass);
            return scriptClass;
        }
    }

    private Object run(Class<Script> script, Binding binding) {
        Script scriptObj = InvokerHelper.createScript(script, binding);
        Object result = scriptObj.run();
        // 每次脚本执行完之后,一定要清理掉内存
        classLoader.clearCache();
        return result;
    }

    public Object scriptGetAndRun(String key, Binding binding) {
        return run(getScript(key), binding);
    }
}

附件代码:

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import lombok.experimental.UtilityClass;

/**
 * @author zhouzhenyong
 * @since 2019/2/22 上午11:20
 */
@UtilityClass
public class EncryptUtil {

    /**
     * 传入文本内容,返回 encrypt-256 串
     */
    public String SHA256(final String strText) {
        return encrypt(strText, "SHA-256");
    }

    /**
     * 传入文本内容,返回 encrypt-512 串
     */
    public String SHA512(final String strText) {
        return encrypt(strText, "SHA-512");
    }

    public String MD5(final String strText){
        return encrypt(strText, "MD5");
    }

    /**
     * 字符串 encrypt 加密
     */
    private String encrypt(final String str, final String strType) {
        MessageDigest messageDigest;
        String encodeStr = "";
        if (null == str || str.length() == 0) {
            return encodeStr;
        }
        try {
            messageDigest = MessageDigest.getInstance(strType);
            messageDigest.update(str.getBytes());

            // 将byte 转换为字符展示出来
            StringBuilder stringBuffer = new StringBuilder();
            String temp;
            for (byte aByte : messageDigest.digest()) {
                temp = Integer.toHexString(aByte & 0xFF);
                if (temp.length() == 1) {
                    //1得到一位的进行补0操作
                    stringBuffer.append("0");
                }
                stringBuffer.append(temp);
            }
            encodeStr = stringBuffer.toString();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        return encodeStr;
    }
}
上一篇 下一篇

猜你喜欢

热点阅读