4

これが機能しないためには、脳死した愚かなことをしなければならないことはわかっていますが、実行中のサーバーに動作を動的にロードしたい状況にあります。これを行うためのツールとして groovy を選択しました。この動作では、モデル オブジェクトや Freemarker などのサード パーティ ライブラリなど、サーバーのクラスパス上のクラスを参照する必要があります。

実現可能性を示すために、このばかげた POC をまとめました。GroovyClassPath の親クラスパスを現在のパスに設定しているにもかかわらず、Groovy スクリプトで Java クラス "ThingyDoodle" および "Fooable" を解決できません。

public class GroovyTest
{
    public static void main ( String [ ] argv ) throws Throwable
    {
            // Setting parent classloader!
            // also tried plain old "GroovyTest.class.getClassLoader()" as well
        GroovyClassLoader gcl = new GroovyClassLoader ( Thread.currentThread().getContextClassLoader() ) ;
        String src =
              "class Arf implements Fooable {
                 public String foo ( ) {
                   return new ThingyDoodle().doStuff('Arf');}}" ;
        Class clazz = gcl.parseClass(src, "AppleSauce.groovy");
        Object aScript = clazz.newInstance();
        Fooable myObject = (Fooable) aScript;
        System.out.println ( myObject.foo() ) ;
    }

    public static interface Fooable { public String foo ( ) ; }

    public static class ThingyDoodle
    {
        public String doStuff ( String input )
        {
            return "Hi Worlds" ;
        }
    }
}

ここで私は一体何を間違っているのですか?

Exception in thread "main" org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed:
AppleSauce.groovy: 1: unable to resolve class Fooable
 @ line 1, column 1.
   class Arf implements Fooable { public String foo ( ) { return new ThingyDoodle().doStuff('Arf');}}
   ^

AppleSauce.groovy: 1: unable to resolve class ThingyDoodle
 @ line 1, column 63.
   ublic String foo ( ) { return new Thingy
                                     ^
4

2 に答える 2

3

コードの問題は、FooableインターフェイスとThingyDoodleクラスが見つからないことです。これらは両方とも内部クラスであり、含まれるクラス名、つまりGroovyTestで修飾する必要があるためです。埋め込みスクリプトで両方の名前を修飾し (スクリプトを囲む引用符を修正しました)、期待どおりに実行されました。

import groovy.lang.GroovyClassLoader;

public class GroovyTest
{

    public static void main ( String [ ] argv ) throws Throwable
    {
            // Setting parent classloader!
            // also tried plain old "GroovyTest.class.getClassLoader()" as well
        GroovyClassLoader gcl = new GroovyClassLoader ( Thread.currentThread().getContextClassLoader() ) ;
        String src =
              "class Arf implements GroovyTest.Fooable { " + 
                 "public String foo ( ) { " + 
                   "return new GroovyTest.ThingyDoodle().doStuff('Arf');}}" ;
        Class clazz = gcl.parseClass(src, "AppleSauce.groovy");
        Object aScript = clazz.newInstance();
        Fooable myObject = (Fooable) aScript;
        System.out.println ( myObject.foo() ) ;
    }       
     public static interface Fooable { public String foo ( ) ; }

    public static class ThingyDoodle
    {
        public String doStuff ( String input )
        {
            return "Hi Worlds" ;
        }
    }


}
于 2012-04-26T10:38:49.127 に答える
2

どのようにコンパイルしているのかわかりません...これを試しました(ビルドツールとしてGradleを使用)が動作します...

./build.gradle

apply plugin:'application'

repositories {
    mavenCentral()
}

dependencies {
    compile group: 'org.codehaus.groovy', name: 'groovy', version: '1.8.6'
}

mainClassName = 'org.timyates.GroovyTest'

./src/main/java/org/timyates/Fooable.java

package org.timyates ;

public interface Fooable {
  public String foo() ;
}

./src/main/java/org/timyates/ThingyDoodle.java

package org.timyates ;

public class ThingyDoodle {
  public String doStuff( String input ) {
    return String.format( "Hi %s", input ) ;
  }
}

./src/main/java/org/timyates/GroovyTest.java

package org.timyates ;

import groovy.lang.GroovyClassLoader ;

public class GroovyTest {
  public static void main( String[] args ) throws Exception {
    GroovyClassLoader gcl = new GroovyClassLoader( GroovyTest.class.getClassLoader() ) ;
    String src = "import org.timyates.*\n" +
                 "class Arf implements Fooable {\n" +
                 "  public String foo() {\n" +
                 "    new ThingyDoodle().doStuff( 'tim' )\n" +
                 "  }\n" +
                 "}" ;
    Class clazz = gcl.parseClass( src, "AppleSauce.groovy" ) ;
    Fooable myObject = (Fooable)clazz.newInstance() ;
    System.out.println( myObject.foo() ) ;
  }
}

次に、gradle runコマンドラインで入力すると、次の出力が得られます。

$ gradle run
:compileJava
:processResources UP-TO-DATE
:classes
:run
Hi tim

BUILD SUCCESSFUL
于 2012-04-26T08:07:03.610 に答える