2011-03-16 12 views
7

estoy usando GroovyShell como una "expresión evaluador/motor" dentro de mi programa. Acepta dos entradas: (a) uno o más scripts de inicio (b) scripts definidos por el usuario. Ambos se concatenan en el tiempo de ejecución como una gran porción de script (texto) y se alimentan al shell.GroovyShell como "evaluador de expresiones/motor" (o: Cómo reutilizar GroovyShell)

String initScripts = getFromDB() 
String userScript = getFromUser() 

def shell = new GroovyShell() 
output = shell.evaluate(initScripts + userScript) 

El código anterior se ejecutará en un bucle, donde el contenido de userScript variarán.

Hasta ahora, initScripts sólo contienen definiciones de variables (por ejemplo def $yyyy = new Date().format('yyyy')) que podría hacer referencia en userScript (por ejemplo print "$yyyy 001").

¿Hay alguna enfoque más eficiente para esto? (Por ejemplo, reutilizando el caparazón, ¿cómo?) Porque ahora es muy lento.

Editar: Groovy es una necesidad. Por favor, no recomiende otro motor de scripting.

Editar: Estoy pensando si GroovyShell puede hacer esto (pseudo-código):

def shell = new GroovyShell() 
shell.evaluate(initScripts) 

for each userScript in DB { 
    shell.put(userScript) 
    def result = shell.evaluateThat() 
    println "Result is $result" 
} 

Es esto posible? (La última vez que busqué en Google no es posible, pero espero que me equivoque)

Respuesta

7

Puede almacenar en caché el GroovyShell, no es necesario crear uno nuevo siempre:

final static GroovyShell shell = new GroovyShell() 

Además, si se ejecuta un script muchas veces que puede almacenar en caché ellos también. Puede crear un Script con GroovyShell.parse(String scriptText), use Script.run() para ejecutar el script.

This sectionThis section de la documentación podría ayudar también, en lugar de secuencias de comandos también puede crear objetos groovy de forma dinámica.

+1

¿GroovyShell es sin estado y es seguro para subprocesos? Algunas personas pueden usar el programa al mismo tiempo con diferentes secuencias de comandos (eso es seguro, ya que 'userScript' puede ser diferente por usuario, incluso por invocación). – wiradikusuma

+1

Sí, es seguro para subprocesos y sin estado (pero, como veo, no crea copias defensivas si no utiliza el constructor predeterminado, no debería ser un problema en su caso) http://svn.codehaus.org/groovy/ tronco/groovy/groovy-core/src/main/groovy/lang/GroovyShell.java – Adam

+0

Creo que puedes reutilizar el objeto shell, pero no creo que puedas reutilizar el objeto script. Las instancias de script utilizan un 'Map' para el enlace, que no es seguro para subprocesos. – HDave

1

Creo que se puede evitar el peso de la construcción de un entorno maravilloso completa cada vez.

Desde Java 6, hay un soporte para la API de secuencias de comandos en Java, que permite el uso de motores de scripting ligeros.

Como ejemplo, vea this page in groovy website explicando cómo iniciar un script groovy en una aplicación Java usando GroovyScriptEngineImpl.

aviso, podría perder algunos bondades maravillosos, como la uva tal vez maravilloso, pero usted será capaz de

  • reutilizar su motor de scripts
  • asegurarse de que sus evals de script en el contexto de aplicación (el tiempo que se benefician de los objetos de Java el uso)

EDITAR una cosa importante a notar es que ni GroovyScriptEngineImpl ni GroovyShell se puede garantizar la seguridad de cualquier tipo de hilo, como cualquier script groovy es libre de engendrar cualquier cantidad de hilo. De hecho, la única forma de garantizar la seguridad del hilo sería mediante installing a SecurityManager que prohíbe las operaciones con el hilo. De hecho, incluso eso no garantizaría la seguridad de los subprocesos (ya que esta seguridad de subprocesos solo podría lograrse asegurando que toda su base de código Java sea segura para subprocesos).

+0

Lo he investigado, pero mi pregunta sigue siendo la misma, ¿es segura? ¿Cómo puedo reutilizarlo? (Si voy a usar GroovyScriptEngineImpl). – wiradikusuma

+0

Lo siento, pero no puedo ver en qué parte de su pregunta pregunta por la seguridad de las hebras. – Riduidel

+0

Vaya, mi mal, no lo dije explícitamente: P – wiradikusuma

0

termino haciendo esto:

def shell = new GroovyShell() 
shell.evaluate(initScripts) 

for(i in 1..count) 
{ 
    output = shell.evaluate(userScripts); 
} 

Y sólo para estar seguro, puede poner en shellThreadLocal o la piscina.

Cuestiones relacionadas