Calling a Groovy function from Java

2020-01-30 07:50发布

How do you call a function defined in a Groovy script file from Java?

Example groovy script:

def hello_world() {
   println "Hello, world!"
}

I've looked at the GroovyShell, GroovyClassLoader, and GroovyScriptEngine.

标签: java groovy
6条回答
迷人小祖宗
2楼-- · 2020-01-30 07:55

Either

  1. Compile as ataylor suggests
  2. Use JSR-223 as explained here
  3. If you are using Spring, have a groovy class that implements a Java interface, and inject into your code with:

<lang:groovy id="messenger" script-source="classpath:Messenger.groovy">
    <lang:property name="message" value="I Can Do The Frug" />
</lang:groovy>

One advantage of the spring approach is the concept of 'refreshable beans'. That is, Spring can be configured to monitor your script file for modifications, and replace at runtime.

查看更多
够拽才男人
3楼-- · 2020-01-30 07:58

The simplest way is to compile the script into a java class file and just call it directly. Example:

// Script.groovy
def hello_world() {
    println "Hello, World!"
}

// Main.java
public class Main {
    public static void main(String[] args) {
        Script script = new Script();
        script.hello_world();
    }
}

$ groovyc Script.groovy
$ javac -classpath .:$GROOVY_HOME/embeddable/groovy-all-1.7.5.jar Main.java
$ java -classpath .:$GROOVY_HOME/embeddable/groovy-all-1.7.5.jar Main
Hello, World!
查看更多
Melony?
4楼-- · 2020-01-30 08:01

Just more elegant ways:

GroovyScriptEngine engine = new GroovyScriptEngine( "." )

Object instance = engine
  .loadScriptByName(scriptName)
  .newInstance()

Object result = InvokerHelper.invokeMethod(instance, methodName, args)

And if script class extends groovy.lang.Script:

Object result = engine
  .createScript(scriptName, new Binding())
  .invokeMethod(methodName, args)

No need to extend groovy.lang.Script if you just want call main method of your groovy class:

Object result = engine
  .createScript(scriptName, new Binding())
  .run()
查看更多
beautiful°
5楼-- · 2020-01-30 08:16

One simple example:

import groovy.lang.GroovyClassLoader;
import groovy.lang.Script;

public class GroovyEmbedder {

    static public final String GROOVY_SCRIPT=
            "println ('Hello World !')";

    static public void main(String[] args) throws Exception {
        ((Script) new GroovyClassLoader().parseClass(GROOVY_SCRIPT).newInstance()).run();
    }
}

Testing

> javac -cp groovy-all-2.4.10.jar GroovyEmbedder.java
> java -cp groovy-all-2.4.10.jar:. GroovyEmbedder
Hello World !
查看更多
Emotional °昔
6楼-- · 2020-01-30 08:18

Assuming you have a file called test.groovy, which contains (as in your example):

def hello_world() {
   println "Hello, world!"
}

Then you can create a file Runner.java like this:

import groovy.lang.GroovyShell ;
import groovy.lang.GroovyClassLoader ;
import groovy.util.GroovyScriptEngine ;
import java.io.File ;

class Runner {
  static void runWithGroovyShell() throws Exception {
    new GroovyShell().parse( new File( "test.groovy" ) ).invokeMethod( "hello_world", null ) ;
  }

  static void runWithGroovyClassLoader() throws Exception {
    // Declaring a class to conform to a java interface class would get rid of
    // a lot of the reflection here
    Class scriptClass = new GroovyClassLoader().parseClass( new File( "test.groovy" ) ) ;
    Object scriptInstance = scriptClass.newInstance() ;
    scriptClass.getDeclaredMethod( "hello_world", new Class[] {} ).invoke( scriptInstance, new Object[] {} ) ;
  }

  static void runWithGroovyScriptEngine() throws Exception {
    // Declaring a class to conform to a java interface class would get rid of
    // a lot of the reflection here
    Class scriptClass = new GroovyScriptEngine( "." ).loadScriptByName( "test.groovy" ) ;
    Object scriptInstance = scriptClass.newInstance() ;
    scriptClass.getDeclaredMethod( "hello_world", new Class[] {} ).invoke( scriptInstance, new Object[] {} ) ;
  }

  public static void main( String[] args ) throws Exception {
    runWithGroovyShell() ;
    runWithGroovyClassLoader() ;
    runWithGroovyScriptEngine() ;
  }
}

compile it with:

$ javac -cp groovy-all-1.7.5.jar Runner.java 
Note: Runner.java uses unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.

(Note: The warnings are left as an exercise to the reader) ;-)

Then, you can run this Runner.class with:

$ java -cp .:groovy-all-1.7.5.jar Runner
Hello, world!
Hello, world!
Hello, world!
查看更多
一纸荒年 Trace。
7楼-- · 2020-01-30 08:18

You too can use the Bean Scripting Framework to embed any scripting language into your Java code. BSF give you the opportunity of integrate other languages, but is not native integration.

If you are clearly focused to use Groovy the GroovyScriptEngine is the most complete solution.

=)

查看更多
登录 后发表回答