Wie rufe ich eine Methode einer Java-Instanz aus JavaScript auf?

8

Ich benutze den Mozilla Rhino JavaScript Emulator. Es erlaubt mir, Java-Methoden zu einem Kontext hinzuzufügen und sie dann aufzurufen, als wären sie JavaScript-Funktionen. Aber ich kann es nicht zum Laufen bringen, außer wenn ich eine statische Methode verwende.

Das Problem ist dieser Teil der Dokumentation:

  

Wenn die Methode nicht statisch ist, entspricht der Java-Wert "this" dem JavaScript-Wert "this". Jeder Versuch, die Funktion mit einem "this" -Wert aufzurufen, der nicht den richtigen Java-Typ hat, führt zu einem Fehler.

Offensichtlich stimmt mein Java "dieser" Wert nicht mit dem in JavaScript überein und ich habe keine Idee, wie man sie zusammenbringt. Am Ende möchte ich eine Instanz in Java erstellen und ein paar Methoden davon im globalen Bereich installieren, damit ich die Instanz von Java initialisieren kann, sie aber in meinen Skripten verwenden kann.

Hat jemand dafür einen Beispielcode?

    
Aaron Digulla 09.08.2010, 16:08
quelle

2 Antworten

8

Wenn eine Java-Methode (ob statisch oder nicht-statisch) als globale Funktion in einem Bereich zur Verfügung gestellt werden soll, verwenden wir die folgende Logik:

%Vor%

Hier sollte der boundScope immer der Bereich sein, in dem die Funktion zur Verfügung gestellt werden soll.

Der Wert des übergeordneten Bereichs hängt jedoch davon ab, ob wir eine Instanzmethode oder eine statische Methode binden. Bei einer statischen Methode kann es sich um jeden sinnvollen Bereich handeln. Es kann sogar dasselbe wie boundScope sein.

Aber im Fall einer Instanzmethode sollte parentScope die Instanz sein, deren Methode gebunden wird.

Das obige war nur Hintergrundinformationen. Nun werde ich erklären, was das Problem ist, und eine natürliche Lösung dafür geben, d. H. Die Instanzmethode direkt als globale Funktion aufrufen, anstatt explizit eine Instanz des Objekts zu erstellen und dann die Methode unter Verwendung dieser Instanz aufzurufen.

Wenn eine Funktion aufgerufen wird, ruft Rhino die Methode FunctionObject.call() auf, der ein Verweis auf this übergeben wird. Falls die Funktion eine globale Funktion ist, wird sie ohne einen Verweis auf this aufgerufen (dh xxx() anstelle von this.xxx() ), der Wert der this Variable, die an die FunctionObject.call() Methode übergeben wird, ist Umfang, in dem der Aufruf ausgeführt wurde (dh in diesem Fall ist der Wert des Parameters this identisch mit dem Wert des Parameters scope ).

Dies wird zu einem Problem, wenn die Java-Methode, die aufgerufen wird, eine Instanzmethode ist, weil gemäß den JavaDocs des Konstruktors von FunctionObject class:

Wenn die Methode nicht statisch ist, entspricht der Java this -Wert dem JavaScript this -Wert. Jeder Versuch, die Funktion mit einem this -Wert aufzurufen, der nicht den richtigen Java-Typ hat, führt zu einem Fehler.

Und in dem oben beschriebenen Szenario ist das genau der Fall. Der Wert für Javascript this stimmt NICHT mit dem Wert für Java this überein und führt zu einem inkompatiblen Objektfehler.

Die Lösung besteht darin, FunctionObject abzuleiten, die call() -Methode zu überschreiben, die this -Referenz zwangsweise zu fixieren und den Aufruf dann normal ablaufen zu lassen.

So etwas wie:

%Vor%

Ich denke, es wäre am besten mit einem abgeschlossenen / vollständigen Beispiel, das unten eingefügt wird, zu verstehen. In diesem Beispiel stellen wir die Instanzmethode myJavaInstanceMethod (Double number) als globale Funktion in einem JavaScript-Bereich ('scriptExecutionScope') zur Verfügung. In diesem Fall muss der Wert des Parameters 'parentScope' eine Instanz der Klasse sein, die diese Methode enthält (z. B. MyScriptable).

%Vor%

Wenn Sie das Verhalten mit dem Fix sehen wollen, dann kommentieren Sie Zeile 78 und Kommentarzeile 79:

%Vor%

Wenn Sie das Verhalten OHNE den Fix sehen wollen, dann kommentieren Sie die Zeile 78 und entfernen Sie die Zeile 79:

%Vor%

Hoffe, das hilft.

    
Jawad 10.05.2013, 09:59
quelle
3

Sie können eine Java -Instanz an den JavaScript-Kontext binden, und von dort aus wird diese ID dann eine Referenz auf das "echte" Java-Objekt. Sie können es verwenden, um Methodenaufrufe von Javascript nach Java auszuführen.

Java-Seite:

%Vor%

Javascript:

%Vor%

In diesem Beispiel wird nun davon ausgegangen, dass Sie die APIs java.util.script des JDK 6 verwenden, um zwischen Java und Rhino zu gelangen. Vom "normalen" Rhino ist es ein wenig anders, aber die Grundidee ist die gleiche.

Alternativ können Sie Java-Klassen in die Javascript-Umgebung importieren, und Rhino bietet Ihnen Javascript-Domänenverweise auf Java-Objekte, wenn Sie Javascript "neu" für Verweise auf Java-Klassen verwenden.

    
Pointy 09.08.2010 16:25
quelle

Tags und Links