Java Script Engine
The Java script engine can embed scripts into Java code, customize and extend Java applications, and since the introduction of JDK1.6, based on the Rhino engine, uses the Nashorn engine after JDK1.8 to support ECMAScript 5, but may change later.
The script engine packages are located in javax.script, and the class names and descriptions are as follows
Interface
-
Bindings
key-value pair mapping, all keys are String
-
Compilable
Implemented by a specific script engine for compiling scripts and reusable.
-
Invocable is implemented by a specific script engine that allows calls to scripts previously executed
-
ScriptContext
Script Engine Context for binding applications to script engines
-
ScriptEngine
Implemented by a specific script engine, which defines how to execute scripts, key-value pair mapping relationships, and script engine context
-
ScriptEngineFactory
A script engine factory, where each script engine has a corresponding factory.ScriptEngineManager retrieves all ScriptEngineFactories instances from ClassLoader
class
-
AbstractScriptEngine
An Abstract implementation class of ScriptEngine that provides a standard implementation of ScriptEngine
-
CompiledScript
Extended by a class that stores compiled results.They can be stored as Java classes, Java class files, or script opcodes, and they can be executed repeatedly without having to be re-parsed.Each CompiledScript is associated with a ScriptEngine, and calling the eval method of CompiledScript causes the ScriptEngine to execute
-
ScriptEngineManager
Script Engine Manager, which provides instantiation mechanisms for ScriptEngine and maintains a collection of key/value pairs for use by all created ScriptEngine shares
-
SimpleBindings
A simple key-value mapping using HashMap or other Maps
-
SimpleScriptContext
A simple implementation of ScriptContext
abnormal
-
ScriptException
Generic exception class for scripting API, exception class thrown with file name, line number, column number information
Example
Ordinary
@Test public void scriptTest() throws ScriptException { ScriptEngineManager engineManager = new ScriptEngineManager(); //Get the JavaScript parsing engine ScriptEngine engine = engineManager.getEngineByName("JavaScript"); //Map the x variable to Hello World! engine.put("x", "Hello World!"); engine.eval("print(x)"); } //output //Hello World!
More complex
Read script from file
/** * Read Js scripts from files * test.js Contents in: * var obj = new Object(); * obj.hello = function (name) { * print('Hello, ' + name); * } * @throws Exception */ @Test public void file() throws Exception{ ScriptEngineManager manager = new ScriptEngineManager(); ScriptEngine engine = manager.getEngineByName("JavaScript"); engine.eval(new FileReader(new File("script/test.js"))); Invocable inv = (Invocable) engine; Object obj = engine.get("obj"); inv.invokeMethod(obj, "hello", "Script Test!" ); }
Injecting Java variables into scripts
There may be a need to use Java variables in scripts
@Test public void scriptVar() throws Exception{ ScriptEngineManager manager = new ScriptEngineManager(); ScriptEngine engine = manager.getEngineByName("JavaScript"); File file = new File("F:/test/test.txt"); //File object f is injected directly into the js script and can be used as a global variable engine.put("files", file); engine.eval("print(files.getPath());print(files.getName());"); }
Call methods in scripts
Calling methods in loaded scripts using Invocable
@Test public void scriptTest1() throws ScriptException, NoSuchMethodException { ScriptEngineManager engineManager = new ScriptEngineManager(); ScriptEngine engine = engineManager.getEngineByName("JavaScript"); StringBuilder sb = new StringBuilder(); sb.append("var obj = new Object();"); sb.append("obj.hello = function(name){print('Hello, ' + name);}"); engine.eval(sb.toString()); //Invocable can call scripts that have already been loaded Invocable invocable = (Invocable) engine; //Get the obj object of the script Object object = engine.get("obj"); //Calling the hello function of an obj object invocable.invokeMethod(object, "hello", "Script Method!"); } //output //Hello, Script Method!
Multiple Scopes
One script engine, multiple scope s, x variables do not overwrite previous variables
@Test public void scriptTest() throws ScriptException { ScriptEngineManager engineManager = new ScriptEngineManager(); ScriptEngine engine = engineManager.getEngineByName("JavaScript"); engine.put("x", "Hello World!"); engine.eval("print(x)"); ScriptContext context = new SimpleScriptContext(); //New Script context Binds ENGINE_SCOPE of ScriptContext Bindings bindings = context.getBindings(ScriptContext.ENGINE_SCOPE); // Add a new variable to the new range engineScope bindings.put("x", "word hello!!"); // Execute the same script - but this time pass in a different script context engine.eval("print(x);", bindings); engine.eval("print(x);"); } //output //Hello World! //word hello!! //Hello World!
Using scripts to implement Java interfaces
@Test public void runnableImpl() throws Exception{ ScriptEngineManager manager = new ScriptEngineManager(); ScriptEngine engine = manager.getEngineByName("JavaScript"); // Define a JavaScript code script in a String String script = "function run() { print('run called'); }"; // Execute this script engine.eval(script); // Gets the Runnable interface object (instance) from the script engine. The interface method is implemented by a script function with a matching name. Invocable inv = (Invocable) engine; // In the script above, we have implemented the run() method of the Runnable interface Runnable runnable = inv.getInterface(Runnable.class); // Start a thread to run the script script above that implements the runnable interface Thread thread = new Thread(runnable); thread.start(); Thread.sleep(1000); }
If the script is object-based, the Java interface can be implemented by executing the script to avoid calling the script's global functions.
@Test public void runnableObject() throws ScriptException { ScriptEngineManager manager = new ScriptEngineManager(); ScriptEngine engine = manager.getEngineByName("JavaScript"); String script = "var obj = new Object();obj.run = function() {println('run method called')}"; engine.eval(script); //Get script objects Object object = engine.get("obj"); Invocable invocable = (Invocable) engine; Runnable runnable = invocable.getInterface(object, Runnable.class); Thread thread = new Thread(runnable); thread.start(); Thread.sleep(1000); }