美文网首页码农的世界
Java ScriptEngine 经验分享 - 关于jpyth

Java ScriptEngine 经验分享 - 关于jpyth

作者: 草编椅 | 来源:发表于2019-10-13 18:45 被阅读0次
    即然是和Java的ScriptEngine搞到一块儿,那当然是要互通的!

    互通,就要能把java类型注入到jpython引擎里,或被获取。
    目前有两种方式注入

    • 方式1,在脚本里引用(这个网站资料好找)
    from java.lang import System
    
    • 方式2,引擎对象上注入(这个难找点)
    //注入实例
    _eng.put("__JTEAPI", new __JTEAPI_CLZ());
    
    //注入类
    _eng.put("XContext", XContext.class);
    _eng.put("ONode", ONode.class);
    
    整到一起后,多份python代码,总要互调的
    //设计一个require接口(只讲意图,实现此处不讲)
    sb.append("def require(path):\n" +
            "    __JTEAPI.require(path)\n" +
            "    return __global['lib'][path]\n\n");
    
    _eng.eval(sb.toString());
    
    或讲 我们还要搞下mvc,那来个视图支持
    //设计一个modelAndView接口
    sb.append("def modelAndView(tml,mod):\n" +
            "    return __JTEAPI.modelAndView(tml,mod)\n\n");
    
    _eng.eval(sb.toString());
    
    附一份完整的适配示例

    此示例为嵌入式FaaS引擎 SolonJT 的一个执行器的适配

    public class PythonJtExecutor implements IJtExecutor {
        private static final ThData<StringBuilder> _tlBuilder = new ThData(new StringBuilder(1024 * 5));
        private static final String _lock = "";
        private static PythonJtExecutor _g;
    
        public static PythonJtExecutor singleton() {
            if (_g == null) {
                synchronized (_lock) {
                    if (_g == null) {
                        _g = new PythonJtExecutor();
                    }
                }
            }
    
            return _g;
        }
    
    
        private final ScriptEngine _eng;
        private final Invocable    _eng_call;
        private final Set<String>  _loaded_names;
    
        private PythonJtExecutor() {
            _loaded_names = Collections.synchronizedSet(new HashSet<>());
    
            ScriptEngineManager scriptEngineManager = new ScriptEngineManager();
            _eng = scriptEngineManager.getEngineByName("python");
            _eng_call = (Invocable) _eng;
    
            XApp.global().shared().forEach((k, v) -> {
                sharedSet(k, v);
            });
    
            XApp.global().onSharedAdd((k, v) -> {
                sharedSet(k, v);
            });
    
            sharedSet("__JTEAPI", new __JTEAPI_CLZ());
    
            sharedSet("XContext", XContext.class);
            sharedSet("ONode", ONode.class);
    
            sharedSet("Datetime", Datetime.class);
            sharedSet("Timecount", Timecount.class);
            sharedSet("Timespan", Timespan.class);
    
            try {
                StringBuilder sb = new StringBuilder();
    
                sb.append("__global = {'lib':{}}\n\n");
    
                sb.append("def modelAndView(tml,mod):\n" +
                        "    return __JTEAPI.modelAndView(tml,mod)\n\n");
    
                sb.append("def require(path):\n" +
                        "    __JTEAPI.require(path)\n" +
                        "    return __global['lib'][path]\n\n");
    
                _eng.eval(sb.toString());
    
            } catch (Exception ex) {
                ex.printStackTrace();
            }
    
    
        }
    
        public void sharedSet(String name, Object val) {
            _eng.put(name, val);
        }
    
        //
        // IJtEngine 接口
        //
        @Override
        public String language() {
            return "python";
        }
    
        @Override
        public boolean isLoaded(String name2) {
            return _loaded_names.contains(name2);
        }
    
        @Override
        public boolean preLoad(String name2, AFileModel file) throws Exception {
            if (isLoaded(name2) == false) {
                _loaded_names.add(name2);
    
                _eng.eval(compilerAsFun(name2, file));
            }
    
            return true;
        }
    
        @Override
        public void del(String name) {
            String name2 = name.replace(".", "_").replace("*","_");
            _loaded_names.remove(name2);
            _loaded_names.remove(name2 + "__lib");
        }
    
        @Override
        public void delAll() {
            _loaded_names.clear();
        }
    
        @Override
        public Object exec(String name, AFileModel file, XContext ctx, Map<String, Object> model, boolean outString) throws Exception {
            String name2 = name.replace(".", "_").replace("*","_");
    
            preLoad(name2, file);
    
            Object tmp = _eng_call.invokeFunction("API_" + name2, ctx);
    
            if (tmp == null) {
                return null;
            } else {
                if (outString) {
                    if (tmp instanceof Number || tmp instanceof String || tmp instanceof Boolean){
                        return tmp.toString();
                    }else{
                        return NodeUtil.fromObj(tmp).toJson();
                    }
                }else{
                    return tmp;
                }
            }
        }
    
    
        //////////////////////////////////////////////////////////////////
    
    
        /**
         * 编译为函数代码
         */
        public String compilerAsFun(String name, AFileModel file) {
            StringBuilder sb = _tlBuilder.get();
            sb.setLength(0);
    
            String[] lines = file.content.split("\n");
    
    
            if (name.endsWith("__lib")) {
                sb.append("class API_").append(name).append(":\n");
    
                for (int i = 0, len = lines.length; i < len; i++) {
                    sb.append("    ").append(lines[i]).append("\n");
                }
                sb.append("\n\n");
    
                sb.append("__global['lib']['")
                        .append(file.path)
                        .append("']=")
                        .append("API_")
                        .append(name)
                        .append("()");
    
            } else {
                sb.append("def API_").append(name).append("(ctx):\n");
                for (int i = 0, len = lines.length; i < len; i++) {
                    sb.append("    ").append(lines[i]).append("\n");
                }
            }
    
    
            return sb.toString();
        }
    }
    
    public class __JTEAPI_CLZ {
        public String require(String path) throws Exception {
            String name = path.replace("/", "__");
            String name2 = name.replace(".", "_") + "__lib";
    
            AFileModel file = ExecutorFactory.fileGet(path);
    
            PythonJtExecutor.singleton().preLoad(name2, file);
    
            return name2;
        }
    
        public Object modelAndView(String path, Map<String, Object> model) throws Exception {
            String path2 = path;//AFileUtil.path2(path);//不用转为*
            String name = path2.replace("/", "__");
    
            AFileModel file = ExecutorFactory.fileGet(path2);
    
            if (file.file_id > 0) {
                return ExecutorFactory.call(name, file, XContext.current(), model, true);
            } else {
                return "";
            }
        }
    }
    

    使用效果

    lib = require('/ext_exes_python/demo1_clz')
    
    obj = {'a':1,'b':'hello world!','c':ctx.path(),'d':lib.d()}
    
    return obj
    

    相关文章

      网友评论

        本文标题:Java ScriptEngine 经验分享 - 关于jpyth

        本文链接:https://www.haomeiwen.com/subject/zrdkmctx.html