当前位置: 首页 > 知识库问答 >
问题:

如何在不重启JVM的情况下向Spring应用程序添加外部JAR?

颜博达
2023-03-14

我有一个Spring Boot应用程序,它可以根据特定条件将外部JAR文件复制到文件夹中。这些JAR可以包含许多Spring组件(即用@component注释或元注释的类),Spring应用程序应该能够扫描和实例化这些bean。根据某些条件,是否可以动态加载JAR文件的内容,并使它们可用于Spring应用程序上下文?我充分意识到这对安全的影响。

我已经阅读了Spring为其可执行JAR格式提供的不同类型的LauncherPropertiesLauncher,但是看起来这些Launcher并不检测类路径的更改,而是只扫描一次目录以查找JAR文件。

下面的简单应用程序演示了这个问题:

// .../Application.java
@SpringBootApplication
public class Application {
  public static void main(String[] args) {
    System.out.println("Please copy JAR files and press Enter ...");
    System.in.read();
    SpringApplication.run(Application.class, args);
  }
}

将默认的JarLauncher替换为PropertiesLauncher:

// build.gradle
tasks.named('bootJar') {
  manifest {
    attributes 'Main-Class': 'org.springframework.boot.loader.PropertiesLauncher',
      'Start-Class': 'com.example.customlauncher.Application'
  }
}

PropertiesLauncher的属性文件中指定外部JAR的位置:

# .../resources/loader.properties
loader.path=file:/path/to/dir
java -jar build/libs/customlauncher-0.0.1-SNAPSHOT.jar
    null

有没有一种方法可以在没有太多尴尬的黑客攻击的情况下实现这一点?还是建议使用OSGi之类的东西?我是不是完全错了,有一个更好的方法让类路径上的JAR不总是需要加载(如果JAR是“禁用的”,JVM不应该加载/编译它,不应该由Spring提取它,等等)?

共有1个答案

宿嘉
2023-03-14

如果在启动Spring应用程序之前复制JAR文件,看起来这是可能的。感觉有点讨厌,但很管用。使用风险自负!

您需要两个类,一个用于引导外部JAR,然后通过手动创建的PropertiesLauncher启动第二个。bootstrapping类可以是一个普通的旧Java类(但也可以是一个Spring Boot应用程序),只有第二个类需要是一个SpringBootApplication。

// BootstrapApplication.java
public class BootstrapApplication {
  public static void main(String[] args) {
    System.out.println("Please copy JAR files and press Enter ...");
    System.in.read();

    PropertiesLauncher.main(args);
  }
}
// Application.java
@SpringBootApplication
public class Application {
  public static void main(String[] args) {
    SpringApplication.run(Application.class, args);
  }
}

在gradle文件中,我们可以切换回默认的JarLauncher,方法是删除bootjar任务清单配置,并通过Springboot配置块应用设置。Mainclass将在manifest.mf文件中以start-class结束。

// build.gradle
html" target="_blank">springBoot {
    mainClass = 'com.example.customlauncher.BootstrapApplication'
}
# .../resources/loader.properties
loader.path=file:/path/to/dir
loader.main=com.example.customlauncher.Application
java -jar build/libs/customlauncher-0.0.1-SNAPSHOT.jar

在JVM启动后,但在BootstrapApplication中调用PropertiesLauncher#main之前,添加到/path/to/dir的任何JAR文件都可以在类路径和应用程序上下文中使用,如application所示。

 类似资料:
  • 我是新来的jboss服务器。我有jboss 4.2.3服务器。我在单个服务器上有很多应用程序。我需要在不重启jboss服务器的情况下部署我的应用程序。有可能吗?如果是这样,有哪些选择? 提前谢谢!!

  • 问题内容: 我希望在不停止应用程序的情况下分析Java应用程序。我可以在应用程序运行时以某种方式添加Javaagent吗? 问题答案: 根据java.lang.instrument软件包的文档,应该是可能的。 VM启动后启动代理 一个实现可以提供一种机制,可以在VM启动之后的某个时间启动代理。有关如何启动的详细信息是特定于实现的,但通常应用程序已启动并且其主要方法已被调用。在虚拟机启动后实现支持启

  • 问题内容: 我有一个用React编写并与Webpack捆绑在一起的Web应用程序。该应用程序具有一个JSON配置文件,我想在运行时将其包含在内,而不是与webpack捆绑在一起。 在应用程序的入口点,我使用json-loader导入内容,但是这样做会强制将文件嵌入应用程序中,并且一旦捆绑了配置文件,便无法更新。 如何配置webpack.config.js文件以排除config.json文件,但仍允

  • 当我在浏览器中键入React应用程序的任何路径时,例如:http://localhost/login,请求击中我的服务器,我的服务器以401 Unauthorized响应。 当请求不是授权的后端api时,我希望在react路由中处理请求。 网络安全配置。爪哇: 重新验证入口点。爪哇: 是否有办法将请求转发到索引。重新验证EntryPoint中的html?

  • 问题内容: 我正在为我的应用程序使用“ Spring-boot + Hibernate4 + mysql”。作为其中一部分,我要求即使数据库关闭,我的sprint- boot应用程序也应能够启动。目前,当我尝试在不启动数据库的情况下启动我的spring boot应用程序时,它给出了以下异常。 我进行了很多研究,发现此例外与财产有关。 我尝试在Spring Boot的“ application.ym

  • 我正在为我的应用程序使用“Spring启动Hibernate4 mysql”。作为其中的一部分,我有一个要求,即使数据库关闭,我的冲刺启动应用程序也应该能够启动。目前,当我试图在没有数据库的情况下启动我的Spring启动应用程序时,它会给出以下异常。 我做了很多研究,发现这个异常与属性。 我尝试在Spring引导的“application.yml”中设置此属性,但此属性的值在运行时没有反映出来。