Scripting Java(一):Java中执行脚本

Many implementations of scripting and dynamically typed languages generate Java bytecodes so that programs can be run on the Java Platform, just as are actual Java programs. Implementing a language in this way (or as a Java interpreter class for the scripting language) provides all the advantages of the Java platform: scripting implementations can take advantage of the Java platform’s binary portability, security, and high performance bytecode execution.

上面这段话可以很好的回答为什么会有这么多基于Java平台的脚本语言。anyway,今天我们只是来看看怎么在我们的Java代码中执行脚本语言。下面使用两种语言来演示,Groovy 2.4.0和Scala 2.11.5。

有两种方式可以在Java中执行脚本,

Java SE includes JSR 223: Scripting for the Java Platform API. This is a framework by which Java applications can "host" script engines. The scripting framework supports third-party script engines using the JAR service discovery mechanism. It is possible to drop any JSR-223 compliant script engine in the CLASSPATH and access the same from your Java applications (much like JDBC drivers, JNDI implementations are accessed).

所以我们既可以使用JSR223的API来执行脚本,当然也可以直接使用脚本语言提供的API来执行了。下面分别来看看。

JSR-223

通过这个API我们可以拿到实现了JSR-223的脚本引擎,那么我们怎么知道传什么参数才能拿到Groovy跟Scala的引擎呢?冲进去看看代码就知道了,

public ScriptEngine getEngineByName(String shortName) {if (shortName == null) throw new NullPointerException();//look for registered name firstObject obj;if (null != (obj = nameAssociations.get(shortName))) {ScriptEngineFactory spi = (ScriptEngineFactory)obj;try {ScriptEngine engine = spi.getScriptEngine();engine.setBindings(getBindings(), ScriptContext.GLOBAL_SCOPE);return engine;} catch (Exception exp) {if (DEBUG) exp.printStackTrace();}}for (ScriptEngineFactory spi : engineSpis) {List<String> names = null;try {names = spi.getNames();} catch (Exception exp) {if (DEBUG) exp.printStackTrace();}if (names != null) {for (String name : names) {if (shortName.equals(name)) {try {ScriptEngine engine = spi.getScriptEngine();engine.setBindings(getBindings(), ScriptContext.GLOBAL_SCOPE);return engine;} catch (Exception exp) {if (DEBUG) exp.printStackTrace();}}}}}return null;} /*** Registers a <code>ScriptEngineFactory</code> to handle a language* name. Overrides any such association found using the Discovery mechanism.* @param name The name to be associated with the <code>ScriptEngineFactory</code>.* @param factory The class to associate with the given name.* @throws NullPointerException if any of the parameters is null.*/public void registerEngineName(String name, ScriptEngineFactory factory) {if (name == null || factory == null) throw new NullPointerException();nameAssociations.put(name, factory);}

所以可以看到有两种方式可以找到ScriptEngine,

如果已经通过调用注册了名字,那么需要知道注册的是啥名字;如果没有,那就需要知道具体的ScriptEngineFactory实现的getNames方法返回了啥;

ScriptEngineFactory是通过ServiceLoader机制来进行加载的,看下Groovy跟Scala各自的实现都是啥,

javax.script.ScriptEngineFactory文件内容分别是,

org.codehaus.groovy.jsr223.GroovyScriptEngineFactoryscala.tools.nsc.interpreter.IMain$Factory

没有找到有调用registerEngineName方法,那就看下各自的getNames方法吧,GroovyScriptEngineFactory的,

private static final String SHORT_NAME = "groovy";private static final String LANGUAGE_NAME = "Groovy"; static {List<String> n = new ArrayList<String>(2);n.add(SHORT_NAME);n.add(LANGUAGE_NAME);NAMES = Collections.unmodifiableList(n);n = new ArrayList<String>(1);n.add("groovy");EXTENSIONS = Collections.unmodifiableList(n);n = new ArrayList<String>(1);n.add("application/x-groovy");MIME_TYPES = Collections.unmodifiableList(n);}

所以可以通过"groovy"或者"Groovy"来拿到Groovy的ScriptEngine。看下IMain,

@BeanPropertyval names: JList[String] = asJavaList("scala")

alright,那就是通过"scala"来拿到了。代码在后面,两种方式一起上。

Shell

通过groovy.lang.GroovyShell和scala.tools.nsc.interpreter.IMain都可以直接执行脚本,,这两个就是上面我们说的脚本语言提供的API。

我们可以在脚本语言提供的shell环境执行试试,

$ sudo groovy/bin/groovysh[sudo] password for blues: Feb 3, 2015 12:36:43 AM org.codehaus.groovy.runtime.m12n.MetaInfExtensionModule newModuleWARNING: Module [groovy-nio] – Unable to load extension class [org.codehaus.groovy.runtime.NioGroovyMethods]Groovy Shell (2.4.0, JVM: 1.6.0_33)Type ':help' or ':h' for help.—————————————————————————–groovy:000> import groovy.lang.GroovyShell===> groovy.lang.GroovyShellgroovy:000> groovySh = new GroovyShell()===> groovy.lang.GroovyShell@1e74f8bgroovy:000> groovySh.evaluate("import java.util.Random; random = new Random(); random.nextInt();")===> -1378717507$ scalaWelcome to Scala version 2.11.5 (Java HotSpot(TM) 64-Bit Server VM, Java 1.7.0_51).Type in expressions to have them evaluated.Type :help for more information.scala> import scala.tools.nsc.interpreter._import scala.tools.nsc.interpreter._scala> val iMain = new IMain()iMain: scala.tools.nsc.interpreter.IMain = scala.tools.nsc.interpreter.IMain@65adfc7bscala> iMain.eval("import java.util.Random; val random = new Random(); random.nextInt();")res0: Object = 1320282527

都没有问题。

赚钱之道很多,但是找不到赚钱的种子,便成不了事业家。

Scripting Java(一):Java中执行脚本

相关文章:

你感兴趣的文章:

标签云: