Java封装groovy脚本引擎并支持脚本包含(include)功能

码云
2020-11-30 09:06

上篇文章“Java封装groovy脚本引擎并提供脚本缓存的代码GroovyScriptEngine” 介绍了基本的groovy脚本引擎,本文在此基础上扩展了脚本包含功能。参考以下代码:

package com.findsrc.common.script;

import java.io.IOException;
import java.io.InputStream;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.annotation.Resource;

import org.springframework.stereotype.Component;

import com.findsrc.common.exception.NestedRuntimeException;
import com.findsrc.common.util.ResourceUtil;
import com.findsrc.common.util.StringUtil;


@Component("scriptEngine")
public class FSScriptEngine implements ScriptEngine {
    //包含的正则
    public static final Pattern PATTERN = Pattern.compile("^\\s*?#include\\((.+?)\\)\\s*?;?", 8);
    
    //见上篇文章中的介绍
    @Resource(name = "groovyScriptEngine")
    private ScriptEngine scriptEngine;
    
    @Override
    public Object evalFile(String fileName, Map<String, Object> binding) {
        InputStream is = ResourceUtil.loadStream(fileName);
        String content;
        try {
            content = StringUtil.readStream(is);
        } catch (IOException e) {
            throw new NestedRuntimeException("脚本未找到:" + fileName, e);
        } finally {
            ResourceUtil.close(is);
        }
        return eval(content, binding);
    }
    
    @Override
    public Object eval(String script, Map<String, Object> binding) {
        return eval(script, script, binding);
    }
    
    @Override
    public Object eval(String scriptName, String script, Map<String, Object> binding) {
        script = prepareScript(script);
        return this.scriptEngine.eval(scriptName, script, binding);
    }
    
    //清除脚本缓存
    @Override
    public void clearCache() {
        this.scriptEngine.clearCache();
    }
    
    public void setScriptEngine(ScriptEngine scriptEngine) {
        this.scriptEngine = scriptEngine;
    }
    
    //处理include
    public String prepareScript(String script) {
        Matcher matcher = PATTERN.matcher(script);
        StringBuffer preparedScript = new StringBuffer();
        while (matcher.find()) {
            String includeFile = matcher.group(1).trim();
            InputStream is = ResourceUtil.loadStream(includeFile);
            String content;
            try {
                content = StringUtil.readStream(is);
            } catch (IOException e) {
                throw new NestedRuntimeException("包含的脚本未找到:" + includeFile, e);
            } finally {
                ResourceUtil.close(is);
            }
            String valueReplacement = content.replaceAll("\\\\", "\\\\\\\\").replaceAll("\\$", "\\\\\\$");
            matcher.appendReplacement(preparedScript, valueReplacement);
        }
        matcher.appendTail(preparedScript);
        return preparedScript.toString();
    }
}

 

使用方式,参考以下groovy代码:

//functions.sc 内容
import static com.findsrc.bitlight.BitLightUtil.*
def Log = { it ->	println it }
def GetTime = {it-> return GetTime(it,600) }
final ROOT='/Users/rainy/Documents'
//functions.sc 内容



//include上级目录的functions.sc
#include(../functions.sc) 
ROOT+'/'+GetYmd(rowdata.datetime)+'/'+rowdata.contractId+'.dat'

 

全部评论