Использование GroovyShell в качестве «средства оценки / выражения» (или: Как повторно использовать GroovyShell) - PullRequest
9 голосов
/ 16 марта 2011

Я использую GroovyShell в качестве «средства оценки / выражения» внутри моей программы.Он принимает два ввода: (a) один или несколько сценариев инициализации (b) пользовательский сценарий.Оба затем объединяются во время выполнения как большой кусок скрипта (текста) и передаются в оболочку.

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

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

Приведенный выше код будет выполняться в цикле, где содержимое userScript будет варьироваться.

Пока что initScripts содержит только определения переменных (например, def $yyyy = new Date().format('yyyy')), на которые можно ссылаться в userScript (например, print "$yyyy 001").

Есть ли более эффективный подход для этого?(Например, повторное использование оболочки, как?) Потому что сейчас это очень медленно.

Редактировать: Groovy является обязательным.Пожалуйста, не рекомендуйте другой скрипт-движок.

Редактировать: Я думаю, может ли GroovyShell сделать это (псевдокод):

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

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

Возможно ли это?(В прошлый раз я гуглил, это было невозможно, но я надеюсь, что ошибаюсь)

Ответы [ 3 ]

7 голосов
/ 16 марта 2011

Вы можете кэшировать GroovyShell, вам не нужно всегда создавать новый:

final static GroovyShell shell = new GroovyShell()

Также, если вы запускаете один скрипт много раз, вы тоже можете их кэшировать.Вы можете создать Script с GroovyShell.parse (String scriptText) , использовать Script.run () для запуска сценария.

Этот раздел документации также может помочь, вместо сценариев вы также можете динамически создавать шпунтовые объекты.

1 голос
/ 16 марта 2011

Полагаю, вы могли бы избежать веса создания полной среды Groovy каждый раз.

Начиная с Java 6, в Java есть поддержка API сценариев, которая позволяет использовать легковесные механизмы сценариев.

В качестве примера см. эту страницу на Groovy веб-сайте , объясняющую, как запустить Groovy-скрипт в приложении Java с использованием GroovyScriptEngineImpl.

обратите внимание, что вы можетепотерять некоторые отличные черты, например Groovy grape, но вы сможете

  • повторно использовать ваш механизм сценариев
  • , чтобы обеспечить выполнение сценария в контексте приложения (в конечном итоге получая выгоду от использования объектов Java))

EDIT одна важная вещь, на которую следует обратить внимание, состоит в том, что ни GroovyScriptEngineImpl, ни GroovyShell не могут гарантировать вам какой-либо вид безопасности потоков, так как любой Groovy-скрипт может свободно создавать любыеномер нити.Фактически, единственный способ гарантировать безопасность потоков - это установить , установив SecurityManager , запрещающий операции с потоками.На самом деле, даже это не гарантировало бы безопасность потоков (так как эта безопасность потоков могла быть достигнута только при условии, что вся ваша база Java-кода является потокобезопасной).

0 голосов
/ 17 марта 2011

В итоге я делаю это:

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

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

И чтобы быть в безопасности, вы можете поместить shell в ThreadLocal или в пул.

...