需要使用备用主类来运行springboot应用程序

时间:2018-10-16 18:00:19

标签: java spring spring-boot

我有一个运行良好的Spring Boot应用程序。我编写了一个附加类,旨在验证定义的Spring上下文和附加属性的某些方面。它打算作为备用主类运行。完成分析后,将打印结果并退出。

当我执行“ Run As”->“ Spring Boot App”,然后选择该替代主类而不是默认的“ Application”类时,一切正常。

我现在需要能够从命令行执行此操作。我注意到曾经有人遇到过这个问题,here对此进行了描述,但是该解决方案对我不起作用。

就原型而言,替代类仅在src / test / java中。我构造了这样的命令行:

java -cp "target/Service.jar;target/test-classes" -Dloader.main=... org.springframework.boot.loader.PropertiesLauncher

其中“ Service.jar”是组装好的弹簧靴子罐,其本身运行良好。运行此命令时,我得到的是这样的东西:

    Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/commons/cli/ParseException
    at java.lang.Class.getDeclaredMethods0(Native Method)
    at java.lang.Class.privateGetDeclaredMethods(Class.java:2701)
    at java.lang.Class.getDeclaredMethod(Class.java:2128)
    at org.springframework.boot.loader.MainMethodRunner.run(MainMethodRunner.java:47)
    at org.springframework.boot.loader.Launcher.launch(Launcher.java:87)
    at org.springframework.boot.loader.Launcher.launch(Launcher.java:50)
    at org.springframework.boot.loader.PropertiesLauncher.main(PropertiesLauncher.java:593)
Caused by: java.lang.ClassNotFoundException: org.apache.commons.cli.ParseException
    at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:338)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
    ... 7 more

请注意,备用主类没有任何Spring或SpringBoot批注。不需要在Eclipse中运行POC。

我确定ParseException类提到了SpringBoot jar中有一个包装好的jar,但是像这样运行它显然以某种方式错过了它。

更新

我注意到“ ParseException”类是晚于CLI工件的,它不是从常规主类中引用的,而是从我的特殊替代类中引用的。为了解决这个问题,我只构建了一个命令行,为本地存储库中的“ commons-cli”工件指定了一个类路径条目。

但是,一旦我克服了这个问题,我便击中了十几个其他遗失的工件,这些原始工件很可能会被原始的springboot主类引用(几个spring-工件,jersey-server等)。我设法通过使用相同的技术来遍历每个对象,并将路径添加到本地仓库中的工件。我终于让替代主类成功执行并完成了它的工作。这导致非常烦人的命令行,而且我不明白为什么必须在类路径上手动指定这么多工件。我猜想使用PropertiesLauncher而不是默认启动器与此有关。我对这种解决方案不太满意。

1 个答案:

答案 0 :(得分:0)

因为Spring Boot select c.hacker_id , h.name , count(c.hacker_id) c_count from hackers h join challenges c on c.hacker_id = h.hacker_id group by c.hacker_id , h.name having c_count = ( SELECT MAX(temp1.cnt) from ( SELECT COUNT(hacker_id) cnt from challenges group by hacker_id ) temp1 ) or c_count in (select t.cnt from ( select count(*) cnt from challenges group by hacker_id ) t group by t.cnt having count(t.cnt) = 1) order by c_count DESC , c.hacker_id jar具有不同的结构Executable Jar File Structure

uber

这意味着example.jar | +-META-INF | +-MANIFEST.MF +-org | +-springframework | +-boot | +-loader | +-<spring boot loader classes> +-BOOT-INF +-classes | +-mycompany | +-project | +-YourClasses.class +-lib +-dependency1.jar +-dependency2.jar jar具有特定的类路径和类加载器:uber将加载:
   您来自org.springframework.boot.loader.LaunchedURLClassLoader的课程
您对BOOT-INF/classes/*的依赖

因此,当您将BOOT-INF/lib/*添加到alternate main class jar的根目录中时,uber找不到它

但是当您从IDE运行时,会发现从目录构建的LaunchedURLClassLoaderclasspath,在IDE中,您的应用也会从另一个类加载器alternate main class

this answer在您的情况下不起作用,因为您的jdk.internal.loader.ClassLoaders$AppClassLoader位于alternate main class中,这意味着src/test/java中的类不会落入jar中,它们将在构建罐子之前可用并在测试期间运行

看看E.4 PropertiesLauncher Features通知并尝试其他配置,您也可以配置classpath:)