2010-03-31 8 views
12

que tienen una clase Java simple que tiene algunos métodos:¿Cómo puedo agregar métodos de una clase Java como funciones globales en 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) { 
     // .... 
    } 
} 

Me gustaría crear una instancia de esta clase y permitir que el código Javascript para llamar directamente a los métodos, así:

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

la única manera de que pudiera averiguar por ahora era utilizar

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

y luego usar utils.deal(...) en el código Javascript. También puedo escribir funciones de contenedor en Javascript para cada método, pero debería haber una forma más simple de hacerlo automáticamente para todos los métodos públicos de una clase.

+0

Te das cuenta de Java y JavaScript son dos lenguajes completamente diferentes. Pueden tener una sintaxis parecida a C similar, pero no son lo mismo. – thecoshman

+1

Rhino es un motor js incrustado para Java. Este tipo de cosas debería ser alcanzable. Lo logré en Perl con SpiderMonkey: http://blog.dorward.me.uk/2006/02/02/spambots_that_drink_coffee.html – Quentin

+3

@thecoshman Esta es una pregunta absolutamente válida. Puede ejecutar Javascript en Java y es posible que necesite utilizar elementos de Java en JS. – lexicore

Respuesta

7

No estoy muy familiarizado con Rhino, pero algo como esto debería funcionar:

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

Sólo bucle sobre las propiedades de utils, y para cada uno que es una función, cree una función global que llama eso.

EDIT: Tengo esta trabajando en un guión maravilloso, pero tenía que establecer utilidades en los enlaces, no en el motor como en el código:

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 para un buen uso de los cierres. Creo que voy a ir con tu solución. – gooli

+0

¿Cómo conseguirías que esto funcione en Java? ¿Usaría lo siguiente: motor de ScriptEngine = new ScriptEngineManager(). GetEngineByName ("js"); engine.put ("utils", nuevos Utils()); ¿o algo mas? –

+0

@AndersonGreen que probablemente funcionaría. – noah

3

No estoy seguro de cómo funcionaría esto con la API JSR-223, pero con la API de Rhino, puede crear un FunctionObject con el método que desee agregar de esta manera.

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

La documentación está disponible en https://www.mozilla.org/rhino/apidocs/org/mozilla/javascript/FunctionObject.html.

puede que tenga que hacer referencia a la biblioteca de Rhino para acceder a la clase FunctionObject, y no estoy seguro de cómo se podrían obtener el objeto scope con la API JSR-223 (aunque, es posible que null funcionaría).

+0

No creo que esto funcione porque el objeto de la función deal no tiene ninguna referencia a la instancia. –

+0

@Geoff: suponía que son métodos estáticos, ya que se llamarían sin un objeto (this) 'this'. Viéndolo de nuevo, creo que no, pero probablemente debería ser así. –

+1

Gracias por esto.En realidad, cuando se utiliza la API de Rhino, la clase 'Context' tiene un método' javaToJS' que hace exactamente lo que necesito. Parece que debería funcionar también con métodos no estáticos. Esperaba una solución JSR-223, pero no creo que haya una. – gooli

Cuestiones relacionadas