Spring Boot 中的热插拔

50

我一直在使用Spring Boot进行P.O.C。

目前来看,进展非常良好和有前途,但有一个主要的缺点:我正在使用嵌入式服务器(即将Web应用程序打包成.jar),因此在开发过程中,每当我更改CSS、HTML或JS文件时,都必须重新构建jar并重新启动服务器。无法热交换,这真的会严重拖慢界面开发速度。

我可以想到几种快速解决方案,例如从不同域加载静态资源,并从本地nginx提供服务,以及其他类似的变体,但在使用IntelliJ / Eclipse时是否有一些内置选项呢?


如果您不介意从Spring Boot切换,可以尝试使用Mason http://github.com/metamug/mason。它被设计为快速且能够在更改时重新部署。 - Sorter
12个回答

28
有几个选项。在IDE中运行(特别是开启调试模式)是进行开发的好方法(所有现代IDE都允许重新加载静态资源,通常也可以热交换Java类更改)。Spring Boot devtools是一种廉价的方式,可以获得相当大的提升(只需将其添加到类路径中)。它通过在检测到更改时在热JVM中重新启动应用程序来工作。它还会关闭诸如thymeleaf缓存之类的东西,因此您不必自己记住要这样做。如果您使用更高级别的工具编写该代码,则可以将其与外部css/js编译器进程一起使用。 Spring Loaded不再推荐使用,但可能仍在使用。如果需要零延迟的热交换,则更复杂的基于代理的工具效果更好(例如JRebel)。
请参阅docs以获取一些最新内容。

谢谢Dave,我会研究一下Spring-Loaded和Maven选项来重新加载静态文件。有一个问题:我正在运行Idea12,但在注释驱动的配置中运行嵌入式Tomcat时找不到重新打包静态资源的方法,你确定它应该可以工作吗? - Amnon
我不是一个常规的IDEA用户,但我不知道有任何问题。去年我参与了一个项目,所有人都使用它,从未遇到任何问题。这一定是可能的。也许你需要将src/main/resources明确添加到你的类路径中? - Dave Syer
我在IntelliJ中也遇到了问题。我按照Spring Boot的文档进行操作,并确保Thymeleaf缓存设置为false,但每当我更改位于src/main/resources下的模板时,都必须重新启动运行嵌入式容器的应用程序。 - Roy Kachouh
3
我没意识到在调试模式下启动后可以通过STS热重载.class文件。谢谢! - duma
1
@RoyKachouh Dave是正确的。请看我的答案以获取说明(非常简单!) - David Groomes

14

不过在使用IntelliJ/Eclipse时,难道没有内置选项吗?

在我的IntelliJ 15.0和Windows 10中,以下步骤对我有帮助:

步骤1:将以下依赖项添加到pom.xml文件中(虽然这个方法已经被到处提到,但单独这一步并不能解决问题),就像@jonashackt所说的那样。

<dependency>
     <groupId>org.springframework.boot</groupId>
     <artifactId>spring-boot-devtools</artifactId>
</dependency>

步骤2: 从文件->设置->构建-执行-部署->编译器 (确保选择主编译器选项而不是其任何子选项)

启用自动构建项目。 点击“确定”并关闭对话框 注意: 在最新版中,它将是自动构建项目

步骤3: 按住 Shift+Ctrl+A (在 Windows 上),您将看到一个带有标题“输入操作或选项名称”的搜索对话框,键入注册表。 双击第一个说“注册表…”的选项,它将打开另一个窗口。 查找以下选项:

compiler.automake.allow.when.app.running

要启用它,请单击关闭按钮。

步骤4:重新启动IDE。

本文详细说明自来源以来。


2
这只是在保存文件时重新启动SpringBoot吗? - powder366
不,它允许您在保存时反映更改。 - shabby
4
是的,但是当我保存时,它会从头重新启动SpringBoot。 我只是希望加载已更改的类。 - powder366
Thymeleaf模板和静态资源可以在不构建的情况下重新加载,如果您从文件系统而不是类路径中获取它们:https://dev59.com/yFkS5IYBdhLWcg3wUFB0#72928208 - Thomas W
没有编译器。构建时允许自动创建。构建版本号:IU-231.9161.38,构建日期:2023年6月20日。 - Tony B

7

Thymeleaf模板和静态资源也可以在不构建的情况下重新加载,如果您从文件系统而不是类路径中获取它们的话:https://dev59.com/yFkS5IYBdhLWcg3wUFB0#72928208 - Thomas W

6
我不知道这种支持有多远,但是如果你使用Eclipse IDE(或任何阅读此文的人):通过m2e以调试模式启动Spring-Boot应用程序(按下“Debug”下拉按钮并选择您的maven运行配置项)。

对我而言,它像魔法一样工作。

我的maven运行配置项配置如下:

  • 目标设置为“spring-boot:run”
  • 基本目录是项目目录

没有使用任何其他库(甚至没有使用spring-boot-devtools)。

就是这样。


热代码替换(HCR)仅在类签名未更改时才有效;请确保已选中“项目>自动构建”。请参阅:https://wiki.eclipse.org/FAQ_What_is_hot_code_replace%3F - Nianliang

5

为什么使用optional=true - nabster
@nabster 可选依赖项用于在无法将项目拆分为子模块时使用。其想法是某些依赖项仅用于项目中的某些功能,如果不使用该功能,则不需要这些依赖项。理想情况下,这样的功能将被拆分为依赖于核心功能项目的子模块... 阅读更多:https://maven.apache.org/guides/introduction/introduction-to-optional-and-excludes-dependencies.html - horvoje

5
假设您正在使用Gradle,请在您的build.gradle中使用以下配置:
apply plugin: 'java'
apply plugin: 'idea'
apply plugin: 'spring-boot'
apply plugin: 'application'

applicationDefaultJvmArgs = ["-agentlib:jdwp=transport=dt_socket,address=localhost:7000,server=y,suspend=n"]

mainClassName = "package.ApplicationRunner"

使用命令gradle build run从IDE或命令行运行应用程序。

现在,IDE可以连接到远程JVM(端口7000),其中Spring Boot应用程序正在运行。它还支持静态文件的热部署。

如果在IDE中正确管理了依赖项,甚至可以从intelliJ运行主类。主类是包含将调用SpringApplication.run("classpath:/applicationContext.xml", args);的main方法的类。


5
在Intellij中,我可以得到这个行为。当程序在调试模式下运行时,选择运行>重新加载已更改的类 注意:在Intellij完成操作后,可能会说已加载类是最新的。没有要重新加载的内容。这是误导性的,因为它实际上重新加载了您的类路径资源。
我的环境/设置包括:
Intellij 13
嵌入式Tomcat
类型为“应用程序”的运行/调试配置(仅使用一个主类)
提供静态html、css和js文件(没有jsp)

5

您还可以使用JRebel - 它将重新加载所有更改(更好的热交换),包括Spring Bean。它很容易与Intellij和Eclipse集成。


3

从1.3.0版本(现在的里程碑版本2)开始,您可以使用spring-boot-devtools轻量级工具来实现此目的-请查看文档此博客文章。 只需升级到>= 1.3.0,并将以下内容添加到您的pom.xml文件中:

<dependencies>
  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-devtools</artifactId>
  </dependency>
</dependencies>

然后使用“Run As”启动您的SpringBootApplication,一切都会很好。


2

我推荐使用 Thymeleaf(模板引擎)和 jRebel for personal developer(个人开发者专用工具)。

Thymeleaf 模板文件只是 HTML 资源,因此在您编辑模板文件后它们会立即更改。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接