GVKun编程网logo

java – GroovyShell:嵌入式执行(java做嵌入式)

10

如果您对java–GroovyShell:嵌入式执行感兴趣,那么本文将是一篇不错的选择,我们将为您详在本文中,您将会了解到关于java–GroovyShell:嵌入式执行的详细内容,我们还将为您解答j

如果您对java – GroovyShell:嵌入式执行感兴趣,那么本文将是一篇不错的选择,我们将为您详在本文中,您将会了解到关于java – GroovyShell:嵌入式执行的详细内容,我们还将为您解答java做嵌入式的相关问题,并且为您提供关于Gradle:使用项目类路径执行Groovy交互式Shell、Groovy - GroovyShell、groovy hello world 第一个groovy程序、groovy – 使用选项和参数执行shell脚本的有价值信息。

本文目录一览:

java – GroovyShell:嵌入式执行(java做嵌入式)

java – GroovyShell:嵌入式执行(java做嵌入式)

我正在尝试将groovy嵌入到大型Java应用程序中.

Java应用程序应该在启动时加载一些实用程序Groovy脚本.

然后应用程序应该多次运行其他脚本.还需要在GUI处输入一些代码并在用户请求时执行它.

我面临的问题是:

我正在加载启动脚本,如下所示:

groovyshell gShell = new groovyshell();
gShell.evaluate(new FileReader("scripts/autoload.groovy"));

假设我的autoload.groovy包含:

def prnt(m) {
    println("From Groovy: " + m);
}

这很好用.但是,当我想使用以下命令运行用户命令时:

gShell.evaluate("prnt 66");

我收到错误:
groovy.lang.MissingMethodException:没有方法签名:Script2.prnt()适用于参数类型:(java.lang.Integer)值:[66]

我的用户脚本如何访问已加载的方法?

注意:我也试过“autoload.prnt 88”,仍然得到错误.

最佳答案
每个评估调用都被编译并作为单独的脚本运行,并且

def prnt(m) {
    println("From Groovy: " + m);
}

定义从autoload.groovy生成的Script类中的方法,该方法无法从后续的“调用”脚本访问.但是,由同一groovyshell运行的脚本共享相同的绑定,因此您可以在一个脚本的绑定中存储值,并在另一个脚本中访问它们.在绑定中存储值只是将值分配给另外未声明的变量:

prnt = { m ->
    println("From Groovy: " + m);
}

这将在绑定变量prnt中存储闭包,您可以从同一shell中的其他脚本调用闭包.注意

def prnt = { m ->

要么

Closure prnt = { m ->

不起作用,因为def或类型使它成为局部变量声明(对这个特定脚本是私有的),而不是对绑定的赋值.

Gradle:使用项目类路径执行Groovy交互式Shell

Gradle:使用项目类路径执行Groovy交互式Shell

我有一个由几个子项目组成的Gradle项目。我刚刚创建了一个新的应用程序,以添加对我想运行的交互式Groovy Shell的支持:

gradle console

要么

gradle console:run

因此,我新console模块的build.gradle文件如下:

apply plugin: ''groovy''apply plugin:''application''mainClassName = ''org.codehaus.groovy.tools.shell.Main''dependencies {  compile ''org.codehaus.groovy:groovy-all:2.2.2''  compile ''org.fusesource.jansi:jansi:1.11''  compile ''commons-cli:commons-cli:1.2''  compile ''jline:jline:2.11''  compile project('':my-module'')}task(console, dependsOn: ''classes'', type: JavaExec) {  main = ''org.codehaus.groovy.tools.shell.Main''  classpath = sourceSets.main.runtimeClasspath}

但是,当我跑步gradle :console:rungradle console得到类似以下信息时:

:console:runGroovy Shell (2.2.2, JVM: 1.6.0_45)Type ''help'' or ''\h'' for help.--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------groovy:000> BUILD SUCCESSFULTotal time: 4.529 secsgiovanni@mylaptop:~/Projects/my-project$

因此,交互式外壳似乎开始了,但立即退出了。

难道我做错了什么?

编辑 :将以下内容添加到build.gradle文件:

run.standardInput = System.in

现在,从输入流中读取标准输入(由于注释)。

但是,Gradle似乎对此卡住了:

Groovy Shell (2.2.2, JVM: 1.6.0_45)Type ''help'' or ''\h'' for help.--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------groovy:000> > Building 88% > :console:run

并且没有输入被接受。即使这样也会导致相同的结果:

gradle --no-daemon console:run

更新2018:

Dylons接受的答案似乎不再起作用,./gradlew console立即退出:

$ ./gradlew console

配置项目:Task.leftShift(Closure)方法已被弃用,并计划在Gradle
5.0中删除。请改用Task.doLast(Action)。在build_8qb2gvs00xed46ejq1p63fo92.run(/home/jhe052/eclipse-
workspace/QuinCe/build.gradle:118)(使用–stacktrace运行以获取此弃用警告的完整堆栈跟踪。)

在3秒钟内成功建立3项可执行的任务:1项已执行,2项最新

用doLast替换leftShift(<<)会删除不赞成使用的消息,但结果相同。版本信息:

$ ./gradlew  --version

摇篮4.4.1

建立时间:2017年12月20日15:45:23 UTC修订版:10ed9dc355dc39f6307cc98fbd8cea314bdd381c

Groovy:2.4.12 Ant:2017年2月2日编译的Apache Ant(TM)版本1.9.9 JVM:1.8.0_151(Oracle
Corporation 25.151-b12)OS:Linux 4.13.0-32-通用amd64

答案1

小编典典

这适用于JDK 7+(对于JDK 6,请参见下图):

configurations {    console}dependencies {    // ... compile dependencies, runtime dependencies, etc.    console ''commons-cli:commons-cli:1.2''    console(''jline:jline:2.11'') {        exclude(group: ''junit'', module: ''junit'')    }    console ''org.codehaus.groovy:groovy-groovysh:2.2.+''}task(console, dependsOn: ''classes'') << {    def classpath = sourceSets.main.runtimeClasspath + configurations.console    def command = [        ''java'',        ''-cp'', classpath.collect().join(System.getProperty(''path.separator'')),        ''org.codehaus.groovy.tools.shell.Main'',        ''--color''    ]    def proc = new ProcessBuilder(command)        .redirectOutput(ProcessBuilder.Redirect.INHERIT)        .redirectInput(ProcessBuilder.Redirect.INHERIT)        .redirectError(ProcessBuilder.Redirect.INHERIT)        .start()    proc.waitFor()    if (0 != proc.exitValue()) {        throw new RuntimeException("console exited with status: ${proc.exitValue()}")    }}

为了使此功能适用于JDK
6,我从http://codingdict.com/questions/113978修改了解决方案。我的解决方案是针对标准Linux终端量身定制的,因此,如果您运行的外壳使用换行符使用’\
n’以外的char序列或将退格编码为其他127以外的值,则可能需要对其进行一些修改。我不确定如何正确打印颜色,因此它的输出相当单调,但是可以完成工作:

configurations {    console}dependencies {    // ... compile dependencies, runtime dependencies, etc.    console ''commons-cli:commons-cli:1.2''    console(''jline:jline:2.11'') {        exclude(group: ''junit'', module: ''junit'')    }    console ''org.codehaus.groovy:groovy-groovysh:2.2.+''}class StreamCopier implements Runnable {    def istream    def ostream    StreamCopier(istream, ostream) {        this.istream = istream        this.ostream = ostream    }    void run() {        int n        def buffer = new byte[4096]        while ((n = istream.read(buffer)) != -1) {            ostream.write(buffer, 0, n)            ostream.flush()        }    }}class InputCopier implements Runnable {    def istream    def ostream    def stdout    InputCopier(istream, ostream, stdout) {        this.istream = istream        this.ostream = ostream        this.stdout = stdout    }    void run() {        try {            int n            def buffer = java.nio.ByteBuffer.allocate(4096)            while ((n = istream.read(buffer)) != -1) {                ostream.write(buffer.array(), 0, n)                ostream.flush()                buffer.clear()                if (127 == buffer.get(0)) {                    stdout.print("\b \b")                    stdout.flush()                }            }        }        catch (final java.nio.channels.AsynchronousCloseException exception) {            // Ctrl+D pressed        }        finally {            ostream.close()        }    }}def getChannel(istream) {    def f = java.io.FilterInputStream.class.getDeclaredField("in")    f.setAccessible(true)    while (istream instanceof java.io.FilterInputStream) {        istream = f.get(istream)    }    istream.getChannel()}task(console, dependsOn: ''classes'') << {    def classpath = sourceSets.main.runtimeClasspath + configurations.console    def command = [        ''java'',        ''-cp'', classpath.collect().join(System.getProperty(''path.separator'')),        ''org.codehaus.groovy.tools.shell.Main''    ]    def proc = new ProcessBuilder(command).start()    def stdout = new Thread(new StreamCopier(proc.getInputStream(), System.out))    stdout.start()    def stderr = new Thread(new StreamCopier(proc.getErrorStream(), System.err))    stderr.start()    def stdin  = new Thread(new InputCopier(        getChannel(System.in),        proc.getOutputStream(),        System.out))    stdin.start()    proc.waitFor()    System.in.close()    stdout.join()    stderr.join()    stdin.join()    if (0 != proc.exitValue()) {        throw new RuntimeException("console exited with status: ${proc.exitValue()}")    }}

然后,通过以下方式执行:

gradle console

或者,如果您从gradle中听到很多噪音:

gradle console -q

Groovy - GroovyShell

Groovy - GroovyShell

Summary

  • 执行一个外部的脚本。
  • 如果单独执行一个脚本我们一行一行写就行,如果需要传入参数,返回参数,我们就定义一个 Closure

Demo

import groovy.json.JsonSlurper

class Main {
    static void main(args) {
        def shell = new groovyshell()

        // 要执行的脚本内容,是一行一行的代码,在 shell.evaluate(script) 的时候,就是逐行执行。
        // 如果最后有 return 语句,就可以接收返回结果。
        String script =
        """
        println 'Script!'
        return "222"
        """
        def scriptResult = shell.evaluate(script)


        // 要执行的脚本内容是一个 Closure 对象,在执行的时候就返回一个 Closure 对象,
        // 调用该 Closure 对象的 call() 方法,获取对应的值。
        String closure =
        """
        { dataMap -> println "Groovy!"; return "返回值"}
        """

        // 返回的是 Script 对象,对象里面是一个 Closure 对象,需要执行才能返回结果。
        def closureResult = shell.evaluate(closure)
        println(closureResult())
    }
}

Demo

package info.aoye

import grails.gorm.transactions.Transactional

@Transactional
class ComponentDemoService {

    static scope = "singleton"

    // 传递过来一个组件对象脚本对象,一个 Object 类型 param
    def evaluate(Component component, Object object) {
        def shell = new groovyshell()
        def closure
        def result

        try
        {
            closure = shell.evaluate(component?.script)
            // 如果不需要参数,就直接执行脚本
            if (!object)
            {
                println("111")
                result = closure
            }
            else
            {
                // 如果是有参数,返回 Closure 对象,这里需要执行一下这个 Closure。
                result = closure(object)
            }
        }
        catch (Exception e)
        {
            println e
            result = e
        }

        return result
    }
}

groovy hello world 第一个groovy程序

groovy hello world 第一个groovy程序




vi  hello.groovy 

输入: 

def hello = { who ->
    println "hello ${who}"
}
hello("groovy")


运行:

$ groovy hello.groovy
返回结果:hello groovy

groovy – 使用选项和参数执行shell脚本

groovy – 使用选项和参数执行shell脚本

我正在使用Jenkins在 linux机器上启动脚本.

当我在服务器上手动运行它时,它可以工作:

/ bin / bash -c’/ some / script MyProduct SomeBranch’

当我用groovy运行它时,它不起作用.

我得到了同样的错误,好像我没有传递“-c”选项,所以不知何故“-c”不起作用.

这是我的代码:

branchName = "SomeBranch"
configName = "release"
println "Building for branch "+branchName+" and configuration "+configName

def chkbranch = { String product,String branch -> mkcmd( product,branch ) } 
private def mkcmd ( String product,String branch ) {
  // Build the command string to run
      def cmd = "/bin/bash -c ''/some/script "+product+" "+branch+"''"
      def sout = new StringBuffer()
      def serr = new StringBuffer()
  // Run the command
      println "running "+cmd
      def proc = cmd.execute()
      proc.consumeProcessOutput ( sout,serr )
      proc.waitForProcessOutput ()
      println "out> $sout"
      println "err> $serr"
      return sout
}

chkbranch ( "MyProduct",branchName )

这是在Groovy中构建命令的正确方法吗?:

def cmd = "/bin/bash -c ''/some/script "+product+" "+branch+"''"
cmd.execute()

谢谢!

我试过类似/有用资源的问题:

> groovy execute with parameters containing spaces
> Groovy executing shell commands
> http://www.joergm.com/2010/09/executing-shell-commands-in-groovy/
> https://fbflex.wordpress.com/2011/11/30/replacing-the-groovy-execute-method-with-one-that-prints-output-while-the-process-is-running/

解决方法

尝试以下列方式运行该命令:

def cmd = ["/bin/bash","-c","/some/script",product,branch]

您也可以尝试:

def cmd = ["/some/script",branch]

if / some / script是可执行的 – BTW是否置于root(/)下?

关于java – GroovyShell:嵌入式执行java做嵌入式的介绍现已完结,谢谢您的耐心阅读,如果想了解更多关于Gradle:使用项目类路径执行Groovy交互式Shell、Groovy - GroovyShell、groovy hello world 第一个groovy程序、groovy – 使用选项和参数执行shell脚本的相关知识,请在本站寻找。

本文标签: