2009-07-03 6 views
7

In einem Java-Programm, das ich ein benutzerdefiniertes JavaScript-Programm bin Aufruf:Java ScriptEngine: Verwenden von Wert auf der Java-Seite?

File userJSFile=...; 
javax.script.ScriptEngineManager mgr=new ScriptEngineManager(); 
javax.script.ScriptEngine scripEngine= mgr.getEngineByExtension("js"); 
Object result=scripEngine.eval(new java.io.FileReader(userJSFile)); 

Nun möchte Ich mag ‚Ergebnis‘ verwenden: Wie kann ich einen Zugriff darauf haben? Kann ich es als Array identifizieren (Kann ich iterate seine Mitglieder werfen), eine String, eine Integer, etc ...?

Dank

EDITED: Ich weiß nur, dass mein Benutzer mir ein Skript gab den letzten Wert zurück. Ich weiß nichts über diesen Wert. Ist es ein String, ein Array, etc ..? Ich weiß es nicht, aber ich möchte es benutzen.

Antwort

0

Diese link kann hilfreich sein. Es scheint, dass Sie sich am besten auf eine implementierungsspezifische Klasse verlassen können.

9

Außer vielleicht für einfache Werte, würde ich lieber die Scripting Engine ihre Werte zu Java-Typen zwingen lassen.

public class ScriptDemo { 

    static class Result { 
    private String[] words; 

    public void setWords(String[] words) { 
     this.words = words; 
    } 
    } 

    static final String SCRIPT = "var foo = 'Hello World!';\n" 
     + "result.setWords(foo.split(' '));"; 

    public static void main(String[] args) 
     throws ScriptException { 
    Result result = new Result(); 
    javax.script.ScriptEngineManager mgr = new ScriptEngineManager(); 
    javax.script.ScriptEngine scripEngine = mgr 
     .getEngineByExtension("js"); 
    scripEngine.getContext().setAttribute("result", result, 
     ScriptContext.ENGINE_SCOPE); 
    scripEngine.eval(SCRIPT); 
    System.out.println(Arrays.toString(result.words)); 
    } 

} 

Auch wenn Sie das Skript nicht bearbeiten können, können Sie den Rückgabewert nehmen und es durch eigene generierte Skript übergeben Sie den Zwang zu tun. Dies setzt voraus, dass Sie etwas über den zurückgegebenen Wert wissen.


EDIT: da nichts über den Rückgabewert bekannt ist, würde ich es zuerst testen Java (getClass()) zu sehen, ob es eine des java.lang Typs ist. Wenn das zurückgegebene Objekt von einer API stammt, die für die Bibliothek privat ist, würde ich es mit der Skriptsprache (in diesem Fall JavaScript) untersuchen und es möglicherweise zu einem Java-Typ zwingen oder seine Eigenschaften in eine Java-Datenstruktur während des Prozesses schieben.

Mein JavaScript ist rostig, aber John Leachs Tutorial sieht ziemlich gut aus: JavaScript Introspection.

(Sie können in der Lage sein, Java Reflexion zu verwenden, aber da der Motor Implementierung zwischen Java-Versionen/JREs/JavaScript-Motoren variieren könnte, würde ich nicht auf sie verlassen.)

2

Diese Frage wurde vor gefragt Alter, aber die Antworten schienen immer noch richtig zu sein. Falls es jemand anderen interessiert, der versucht, komplexe Objekte zwischen Java und Javascript zu übergeben, wollte ich meine Lösung präsentieren.

Ich habe ein Skript geschrieben, das das NativeObject in (in-memory) JSON-Objekte konvertiert (tatsächlich verwende ich MongoDBs BSON-basierte Objekte, aber Sie sollten nur 1-1 für JSONArray und JSONObject im folgenden Beispielcode ersetzen).

So zum Beispiel, sagen, ich habe ein (Benutzer) Skript „create_object_script“, die „Erträge“ ein Objekt oder ein Array von Interesse, dann habe ich es in JSON umwandeln kann (dh eine Liste von Hashmaps) wie folgt:

Offensichtlich, wenn Sie Kontrolle über das Skript "create_object_script" haben, können Sie dies in einem einzigen Schritt tun; Meine Skripte sind benutzergeneriert, so dass diese Komplexität versteckt werden muss - die Benutzer schreiben nur Skripte, bei denen der "Rückgabewert" die letzte Zeile ist.

Ich habe die "Parsing_script" here um die Länge dieses Post zu halten.

Funktional funktioniert das sehr gut; Ich habe in JS nicht viel entwickelt, also ist es möglich, dass es effizientere Möglichkeiten gibt, dies zu tun. (Hinweis: Ich brauche meine Ergebnisse immer in einer Liste. Wenn Sie das nicht tun, können Sie ein BasicDBObject "outObj" übergeben und stattdessen in den Singleton-Fall schreiben.)

Hoffe das hilft jemand, der sich in meiner Situation um 1 Uhr letzte Nacht befindet!