在java应用中集成jython
今天是新年第一天,但是上周欠的帐还没还完。 上周在规则引擎的系统中加入了python部分的实现,即jython,碰到了好多坑。。。有种要死的感觉。。。其实系统之前已经集成了groovy,使用的实现是GroovyScriptEngine,就是把一段字符串形式的groovy脚本通过groovy classloader加载进来,相当于直接执行编译后的class文件。为了能平滑支持jython,实现改成jsr223的通用实现,即script engine,同时支持groovy和jython2.7(项目需要这个老版本。。。)。改完之后,jython各种不支持,然后就一点点填坑。最后就剩下最后一个问题了!本地可以正常运行,但是上到demo环境就不行了。。。然后会神奇的抛出一个空指针异常,说对应的engine没有找到。debug跟进去发现jython初始化engine的时候需要到一个叫Lib的地方import一些library,其中有一个“site”没有找到。然后就没法初始化这个jython engine。 我发现之所以,本地可以跑jython是因为跑spring boot的时候我是在intellij中用main函数的方式跑,这时候所引用的第三方jar是从.gradle/cache下读的。而通过gradle build,然后java -jar xxx方式启动的时候,jython会向这里找Lib:/Users/magiclane/git/dr/morpheus/api/build/libs/api-1.0.jar!/BOOT-INF/lib/jython-standalone-2.7.0.jar。 问题就出在路径上了。 spring boot build称可执行的jar之后的结构是这样的: example.jar | +-META-INF | +-MANIFEST.MF +-org | +-springframework | +-boot | +-loader | +- +-BOOT-INF +-classes | +-mycompany | +-project | +-YourClasses.class +-lib +-dependency1.jar +-dependency2.jar 而且java -jar xxx的时候,这些第三方jar也不会被打开。 然而jython找Lib的默认位置是通过自己的找一个class的classpath定位的。 String urlString = URLDecoder.decode(rawUrl, "UTF-8"); urlString = urlString.replaceAll(escapedPlus, plus); int jarSeparatorIndex = urlString.lastIndexOf(JAR_SEPARATOR); if (urlString.startsWith(JAR_URL_PREFIX) && jarSeparatorIndex > 0) { // jar:file:/install_dir/jython.jar!/org/python/core/PySystemState.class jarFileName = urlString.substring(JAR_URL_PREFIX.length(), jarSeparatorIndex); } 然而真实路径却是在那之前还有一段:libs/api-1....