2010-03-31 17 views
12

Ho una semplice classe Java che ha alcuni metodi:Come posso aggiungere metodi da una classe Java come funzioni globali in Javascript usando Rhino?

public class Utils { 
    public void deal(String price, int amount) { 
     // .... 
    } 
    public void bid(String price, int amount) { 
     // .... 
    } 
    public void offer(String price, int amount) { 
     // .... 
    } 
} 

vorrei creare un'istanza di questa classe e consentire il codice Javascript di chiamare direttamente i metodi, in questo modo:

deal("1.3736", 100000); 
bid("1.3735", 500000); 

l'unico modo ho potuto capire, per ora è stato quello di utilizzare

ScriptEngine engine = new ScriptEngineManager().getEngineByName("js"); 
engine.put("utils", new Utils()); 

e quindi utilizzare utils.deal(...) nel codice Javascript. Posso anche scrivere funzioni wrapper in Javascript per ogni metodo, ma dovrebbe esserci un modo più semplice per farlo automaticamente per tutti i metodi pubblici di una classe.

+0

Ti rendi conto Java e JavaScript sono due completi lingue diverse. Possono avere sintassi simile a C, ma non sono uguali. – thecoshman

+1

Rhino è un motore js incorporato per Java. Questo tipo di cose dovrebbe essere realizzabile. L'ho gestito in Perl con SpiderMonkey: http://blog.dorward.me.uk/2006/02/02/spambots_that_drink_coffee.html – Quentin

+3

@thecoshman Questa è una domanda assolutamente valida. È possibile eseguire Javascript in Java e potrebbe essere necessario utilizzare i gadget Java in JS. – lexicore

risposta

7

io non sono reale familiarità con Rhino, ma qualcosa di simile dovrebbe funzionare:

for(var fn in utils) { 
    if(typeof utils[fn] === 'function') { 
    this[fn] = (function() { 
     var method = utils[fn]; 
     return function() { 
     return method.apply(utils,arguments); 
     }; 
    })(); 
    } 
} 

Basta ciclo sulle proprietà di utils, e per ognuno che è una funzione, creare una funzione globale che chiama esso.

EDIT: Ho ottenuto questo lavoro in uno script Groovy, ma ho dovuto impostare utils negli attacchi, non sul motore, come nel codice:

import javax.script.* 

class Utils { 
    void foo(String bar) { 
     println bar 
    } 
} 

ScriptEngine engine = new ScriptEngineManager().getEngineByName("js"); 

engine.eval(""" 
for(var fn in utils) { 
    if(typeof utils[fn] === 'function') { 
    this[fn] = (function() { 
     var method = utils[fn]; 
     return function() { 
     return method.apply(utils,arguments); 
     }; 
    })(); 
    } 
} 

foo('foo'); // prints foo, sure enough 
""",new SimpleBindings("utils":new Utils())) 
+0

+1 per un buon uso delle chiusure. Penso che andrò con la tua soluzione. – gooli

+0

Come faresti funzionare in Java? Useresti il ​​seguente: motore ScriptEngine = new ScriptEngineManager(). GetEngineByName ("js"); engine.put ("utils", new Utils()); o qualcos'altro? –

+0

@ AnandonGreen che probabilmente funzionerebbe. – noah

3

Non sono sicuro di come funzionerebbe utilizzando l'API JSR-223, ma con l'API di Rhino è possibile creare un FunctionObject con il metodo che si desidera aggiungere in questo modo.

Class[] parameters = new Class[] { String.class, Integer.class }; 
Method dealMethod = Utils.class.getMethod("deal", parameters); 
engine.put("deal", new FunctionObject("deal", dealMethod, scope)); 

La documentazione è disponibile al https://www.mozilla.org/rhino/apidocs/org/mozilla/javascript/FunctionObject.html.

potrebbe essere necessario fare riferimento alla libreria di Rhino per accedere alla classe FunctionObject, e io non sono sicuro di come si dovrebbe ottenere l'oggetto scope con la JSR-223 API (anche se, è possibile che null avrebbe funzionato).

+0

Non penso che funzioni perché l'oggetto della funzione deal non ha riferimenti all'istanza. –

+0

@Geoff: stavo assumendo che fossero metodi statici, dato che sarebbero stati chiamati senza un oggetto 'this' (JavaScript). Guardandolo di nuovo, immagino che non lo siano, ma probabilmente dovrebbe esserlo. –

+1

Grazie per questo.In realtà, quando si usa l'API di Rhino, la classe 'Context' ha un metodo' javaToJS' che fa esattamente ciò di cui ho bisogno. Sembra che dovrebbe funzionare anche con metodi non statici. Speravo in una soluzione JSR-223, ma non credo che ce ne sia una. – gooli

Problemi correlati