Zoeken…


Invoering

Java is op zichzelf een extreem krachtige taal, maar de kracht ervan kan verder worden uitgebreid dankzij JSR223 (Java Specification Request 223) die een script-engine introduceert

Opmerkingen

Met de Java Scripting API kunnen externe scripts communiceren met Java

De Scripting API kan interactie tussen het script en Java mogelijk maken. De scripttalen moeten een Script Engine-implementatie op het klassenpad hebben.

Standaard wordt JavaScript (ook bekend als ECMAScript) standaard geleverd door nashorn. Elke Script Engine heeft een scriptcontext waarin alle variabelen, functies en methoden worden opgeslagen in bindingen. Soms wilt u misschien meerdere contexten gebruiken omdat deze de uitvoer omleiden naar een gebufferde writer en een fout naar een andere.

Er zijn veel andere script-engine-bibliotheken zoals Jython en JRuby. Zolang ze zich op het klassenpad bevinden, kunt u code evalueren.

We kunnen bindingen gebruiken om variabelen in het script bloot te leggen. We hebben in sommige gevallen meerdere bindingen nodig, omdat het blootstellen van variabelen aan de motor in feite variabelen alleen aan die motor blootstelt, soms moeten we bepaalde variabelen blootleggen, zoals systeemomgeving en pad die hetzelfde is voor alle motoren van hetzelfde type. In dat geval hebben we een binding nodig die een wereldwijde reikwijdte heeft. Door variabelen hieraan bloot te stellen, wordt deze blootgesteld aan alle script-engines die door dezelfde EngineFactory zijn gemaakt

Evaluatie van een javascript-bestand in -scripting-modus van 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;
    }
    
}

Nu de belangrijkste methode

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);");
}

Je output zou er ongeveer hetzelfde uit moeten zien
hello world

Zoals u kunt zien, is de belichte variabele x afgedrukt. Nu testen met een bestand.

Hier hebben we test.js

print(x);
function test(){
    print("hello test.js:test");
}
test();

En de bijgewerkte hoofdmethode

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");
}

Ervan uitgaande dat test.js zich in dezelfde map bevindt als uw toepassing, zou u een vergelijkbare uitvoer moeten hebben

hello world
hello test.js:test


Modified text is an extract of the original Stack Overflow Documentation
Licentie onder CC BY-SA 3.0
Niet aangesloten bij Stack Overflow