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


Modified text is an extract of the original Stack Overflow Documentation
Autorizzato sotto CC BY-SA 3.0
Non affiliato con Stack Overflow