Java Language
Utilizzo di altri linguaggi di scripting in Java
Ricerca…
introduzione
Java in sé è un linguaggio estremamente potente, ma la sua potenza può essere ulteriormente estesa Grazie a JSR223 (Java Specification Request 223) che introduce un motore di script
Osservazioni
L'API Java Scripting consente agli script esterni di interagire con Java
L'API Scripting può abilitare l'interazione tra lo script e java. Le lingue di scripting devono avere un'implementazione di Script Engine nel classpath.
Per default JavaScript (noto anche come ECMAScript) viene fornito da Nashorn per impostazione predefinita. Ogni motore di script ha un contesto di script in cui tutte le variabili, le funzioni, i metodi sono memorizzati in associazioni. A volte è possibile che si desideri utilizzare più contesti poiché supportano il reindirizzamento dell'output a un writer bufferizzato e un errore a un altro.
Ci sono molte altre librerie di motori di script come Jython e JRuby. Finché sono sul classpath è possibile eseguire il codice di valutazione.
Possiamo usare i binding per esporre le variabili nello script. Abbiamo bisogno di legami multipli in alcuni casi poiché l'esposizione di variabili al motore fondamentalmente espone le variabili solo a quel motore, a volte richiediamo di esporre determinate variabili come l'ambiente di sistema e il percorso che è lo stesso per tutti i motori dello stesso tipo. In tal caso, è necessaria un'associazione che è un ambito globale. Esporre le variabili a quelle esposte a tutti i motori di script creati dallo stesso EngineFactory
Valutazione di un file javascript in modalità -scripting di nashorn
public class JSEngine {
/*
* Note Nashorn is only available for Java-8 onwards
* You can use rhino from ScriptEngineManager.getEngineByName("js");
*/
ScriptEngine engine;
ScriptContext context;
public Bindings scope;
// Initialize the Engine from its factory in scripting mode
public JSEngine(){
engine = new NashornScriptEngineFactory().getScriptEngine("-scripting");
// Script context is an interface so we need an implementation of it
context = new SimpleScriptContext();
// Create bindings to expose variables into
scope = engine.createBindings();
}
// Clear the bindings to remove the previous variables
public void newBatch(){
scope.clear();
}
public void execute(String file){
try {
// Get a buffered reader for input
BufferedReader br = new BufferedReader(new FileReader(file));
// Evaluate code, with input as bufferdReader
engine.eval(br);
} catch (FileNotFoundException ex) {
Logger.getLogger(JSEngine.class.getName()).log(Level.SEVERE, null, ex);
} catch (ScriptException ex) {
// Script Exception is basically when there is an error in script
Logger.getLogger(JSEngine.class.getName()).log(Level.SEVERE, null, ex);
}
}
public void eval(String code){
try {
// Engine.eval basically treats any string as a line of code and evaluates it, executes it
engine.eval(code);
} catch (ScriptException ex) {
// Script Exception is basically when there is an error in script
Logger.getLogger(JSEngine.class.getName()).log(Level.SEVERE, null, ex);
}
}
// Apply the bindings to the context and set the engine's default context
public void startBatch(int SCP){
context.setBindings(scope, SCP);
engine.setContext(context);
}
// We use the invocable interface to access methods from the script
// Invocable is an optional interface, please check if your engine implements it
public Invocable invocable(){
return (Invocable)engine;
}
}
Ora il metodo principale
public static void main(String[] args) {
JSEngine jse = new JSEngine();
// Create a new batch probably unecessary
jse.newBatch();
// Expose variable x into script with value of hello world
jse.scope.put("x", "hello world");
// Apply the bindings and start the batch
jse.startBatch(ScriptContext.ENGINE_SCOPE);
// Evaluate the code
jse.eval("print(x);");
}
Il tuo output dovrebbe essere simile a questo
hello world
Come puoi vedere la variabile esposta x è stata stampata. Ora prova con un file.
Qui abbiamo test.js
print(x);
function test(){
print("hello test.js:test");
}
test();
E il metodo principale aggiornato
public static void main(String[] args) {
JSEngine jse = new JSEngine();
// Create a new batch probably unecessary
jse.newBatch();
// Expose variable x into script with value of hello world
jse.scope.put("x", "hello world");
// Apply the bindings and start the batch
jse.startBatch(ScriptContext.ENGINE_SCOPE);
// Evaluate the code
jse.execute("./test.js");
}
Supponendo che test.js si trovi nella stessa directory dell'applicazione Dovresti avere un output simile a questo
hello world
hello test.js:test