使用Spring Boot DevTools加快开发速度

2018年11月2日 上次更新时间:2019年4月28日html

Spring Boot开发者工具

DevTools 支持 自动刷新自动重启 –自动刷新(或自动加载)是指在浏览器中从新加载UI,以查看静态内容的更改。自动从新启动是指从新加载服务器端代码和配置,而后从新启动服务器。

如何使用DevTools进一步加快Spring Boot开发的速度,并使之更加有趣和高效?前端

设定

像一般使用Spring Boot同样,设置很是简单。您须要作的就是添加正确的依赖关系,您就能够开始工做了。Spring Boot会检测到这一点,并相应地自动配置DevTools。java

若是您使用的是Maven:react

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

另外,在使用Gradle时:spring

configurations {
    developmentOnly
    runtimeClasspath {
        extendsFrom developmentOnly
    }
}
dependencies {
    developmentOnly("org.springframework.boot:spring-boot-devtools")
}

请注意,该依赖项被声明为可选。这个很重要。这样能够防止将DevTools依赖项过渡性地应用于依赖于项目的其余模块。浏览器

自动重启

只要您的类路径上的文件发生更改,DevTools就会在应用了新更改的状况下自动重启正在运行的应用程序。在本地进行开发时,这颇有用,由于您无需手动从新部署应用程序。缓存

就其自己而言,它并非那么有用,由于从新启动仍会花费大量时间。幸运的是,因为DevTools使用了一个巧妙的技巧,这些重启比常规重启快得多。安全

您会看到,在开发应用程序时,一般会更改一个或几个类,并但愿在运行的应用程序中检查结果以获取反馈。您更改了应用程序的一小部分,由于大多数已加载的类来自框架和第三方库。服务器

引擎盖下,Spring DevTools 使用两个类加载器—— BaseClassLoader 和 RestartClassLoader。不变的类由基本类加载器加载。正在使用的类由从新启动类加载器加载。每当触发从新启动时,从新启动类加载器都会被丢弃并从新建立。这种重启应用程序的速度比日常快得多,而且能够替代使用诸如 JRebel 之类的动态类来从新加载应用程序。session

在IDE中触发重启

只要类路径发生更改,就会触发从新启动。可是,这取决于您的IDE。这意味着仅更改 .java 文件是不够的。重要的是您的IDE实际上会更新 .class 类路径上的文件。

使 IntelliJ IDEA 时,须要构建项目(Ctrl+ F9或Build → Build Project)。您还能够将 IDEA 配置为自动重建。另外,您能够打开Spring Boot运行配置并定义触发应用程序更新(Ctrl+ F10)时发 生的状况:

图片描述

Intellij IDEA Spring Boot 运行配置

在第一个组合框中,能够选择 Update trigger file 在调用 Update 操做时触发 DevTools 从新启动。或者,您甚至能够选择尝试热插拔的选项,而且仅在热插拔失败时才使用 DevTools 从新启动。

在第二个组合框中,您能够配置在 IDEA 窗口失去焦点时(例如,切换到浏览器窗口时)从新加载全部静态资源和模板。

在 Eclipse 中,仅保存文件就足够了。

仅开发

Spring Boot DevTools 的使用仅用于开发,而不用于生产。若是您的应用程序检测到您正在生产中,则将自动禁用 DevTools。

为此,每当您将应用程序做为彻底打包的工件(例如带有嵌入式应用程序服务器的jar)运行时,都将其视为生产应用程序:

java -jar devtools-example-1.0.0.jar

经过特殊的类加载器(例如在应用程序服务器上)启动应用程序时,一样适用。相反,当您运行分解的工件(例如在IDE中)时,您的应用程序将被视为处于开发模式。使用 spring-boot-plugin 运行应用程序时也是如此:

Maven:

mvn spring-boot:run

Gradle:

gradle bootRun

实时重载

LiveReload 是一个有用的工具,它使您能够在更改 HTML,CSS,图像等文件时当即在浏览器中更新页面。它甚至能够根据须要对文件进行预处理-这意味着会自动编译您的 SASS 或 LESS 文件。

实时从新加载

Spring DevTools 自动启动 LiveReload 服务器的本地实例,该实例监视您的文件。您所须要作的就是安装浏览器扩展程序,一切顺利。它不只对开发应用程序的前端颇有用(以防您将其做为Spring应用程序工件的一部分进行分发),并且还能够用于监视和从新加载REST API的输出。
图片描述

属性覆盖

在本地开发应用程序时,一般与在生产环境中运行时具备不一样的配置需求。缓存就是一个例子。在生产中,相当重要的是依赖于各类缓存(例如,模板引擎的缓存,静态资源的缓存头等)。在开发中,它可能会因提供旧数据而没有反映您的最新更改而使您感到痛苦。另外一个示例多是加强的日志记录,它在开发中可能有用,但对于生产而言却过于详细。

本身管理双套配置没必要要地复杂。好消息是,Spring Boot DevTools开箱即用为您的本地开发配置了许多属性。

spring.thymeleaf.cache=false
spring.freemarker.cache=false
spring.groovy.template.cache=false
spring.mustache.cache=false
server.servlet.session.persistent=true
spring.h2.console.enabled=true
spring.resources.cache.period=0
spring.resources.chain.cache=false
spring.template.provider.cache=false
spring.mvc.log-resolved-exception=true
server.servlet.jsp.init-parameters.development=true
spring.reactor.stacktrace-mode.enabled=true

您能够在DevToolsPropertyDefaultsPostProcessor中检查全部属性的列表。

远程链接

除了本地开发以外,您还能够链接到运行DevTools的远程应用程序。这不适用于生产环境,由于它可能会带来严重的安全风险。可是,它在预生产环境中可能很是有用。

启用远程链接

默认状况下不启用远程链接。您须要经过修改pom文件显式启用它:

<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
            <configuration>
                <excludeDevtools>false</excludeDevtools>
            </configuration>
        </plugin>
    </plugins>
</build>

或使用gradle,您须要设置 excludeDevtools = false:

bootWar {
    excludeDevtools = false
}

而后,您须要设置一个秘密密码,以便在链接到远程应用程序时用于身份验证

spring.devtools.remote.secret=somesecret

链接到远程应用

远程应用程序运行后,您能够启动远程链接会话。如今,您所须要作的就是以org.springframework.boot.devtools.RemoteSpringApplication远程应用程序的URL做为参数启动。请注意,若是可能,应使用https。

图片描述

在您的IDE中,运行远程链接很是容易。在IDEA中,您只需建立一个新的运行配置。转到Run → Edit Configurations...并使用左上角的[+]图标建立新配置。选择Application类型。

做为Main类,RemoteSpringApplication从DevTools模块中选择,并做为程序参数传递远程应用程序的URL。

IDEA中的远程链接配置

运行此配置后,若是与远程应用程序的链接成功,您应该会看到相似的输出。

.   ____          _                                              __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _          ___               _      \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` |        | _ \___ _ __  ___| |_ ___ \ \ \ \
 \\/  ___)| |_)| | | | | || (_| []::::::[]   / -_) '  \/ _ \  _/ -_) ) ) ) )
  '  |____| .__|_| |_|_| |_\__, |        |_|_\___|_|_|_\___/\__\___|/ / / /
 =========|_|==============|___/===================================/_/_/_/
 :: Spring Boot Remote ::  (v2.0.6.RELEASE)

2018-11-02 17:24:42.126  INFO 16640 --- [           main] o.s.b.devtools.RemoteSpringApplication   : Starting RemoteSpringApplication v2.0.6.RELEASE on DESKTOP-6NJV4ON with PID 16640 (C:\Users\vojte\.m2\repository\org\springframework\boot\spring-boot-devtools\2.0.6.RELEASE\spring-boot-devtools-2.0.6.RELEASE.jar started by vojte in C:\projects\rest-docs-starter)
2018-11-02 17:24:42.130  INFO 16640 --- [           main] o.s.b.devtools.RemoteSpringApplication   : No active profile set, falling back to default profiles: default
2018-11-02 17:24:42.172  INFO 16640 --- [           main] s.c.a.AnnotationConfigApplicationContext : Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@3daa422a: startup date [Fri Nov 02 17:24:42 CET 2018]; root of context hierarchy
2018-11-02 17:24:42.679  WARN 16640 --- [           main] o.s.b.d.r.c.RemoteClientConfiguration    : The connection to http://localhost:8080 is insecure. You should use a URL starting with 'https://'.
2018-11-02 17:24:42.800  WARN 16640 --- [           main] o.s.b.d.a.OptionalLiveReloadServer       : Unable to start LiveReload server
2018-11-02 17:24:42.829  INFO 16640 --- [           main] o.s.b.devtools.RemoteSpringApplication   : Started RemoteSpringApplication in 1.212 seconds (JVM running for 1.877)

链接到远程应用程序后,DevTools会监视类路径更改,就像本地开发同样。可是,它代替本地重启,而是将更改推送到远程服务器并触发那里的重启。这可能比构建应用程序并将其部署到远程计算机快得多。

全局配置

您能够像其余任何Spring应用程序同样使用配置属性来配置 DevTools。这一般意味着编辑 application.properties 项目。对于每一个应用程序,此配置都是单独的。

可是,在某些状况下,为在同一台计算机上运行的全部应用程序进行全局配置可能会很方便。您能够在 $HOME 目录中建立一个名为 .spring-boot-devtools.properties 的属性文件。该文件中声明的配置适用于全部运行DevTools的应用程序。

局限性

实时重加载

使用 DevTools 的 Spring 应用程序会自动启动 LiveReload 服务器。不幸的是,该服务器只能同时运行一个实例。更准确地说,只有第一个能够工做。这不只适用于带有 DevTools 的 Spring 应用程序的多个实例,并且还适用于任何其余在后台使用LiveReload 的应用程序,例如处于开发模式的Gatsby

若是您想配置 Spring 应用程序使其不启动 LiveReload 服务器,则能够在如下代码中进行操做 application.properties

spring.devtools.livereload.enabled=false

关机钩

DevTools 依赖于关闭挂钩的 SpringApplication。若是您使用如下方式手动禁用了挂接,它将没法正常工做:

springApplication.setRegisterShutdownHook(false);

默认状况下,挂钩是启用的,所以除非明确禁用它,不然您没必要担忧。

与第三方库的冲突
尽管DevTools一般应该能够正常运行,但它可能与第三方库有冲突。特别是,使用standard进行反序列化存在一个已知ObjectInputStream 问题

若是发生此类冲突,能够经过设置如下方式禁用自动重启:

spring.devtools.restart.enabled=false

从新启动将再也不被触发。可是,仍将使用从新启动类加载器。若是您须要彻底禁用类加载器,则须要在启动应用程序以前这样作:

public static void main(String[] args) {
    System.setProperty("spring.devtools.restart.enabled", "false");
    SpringApplication.run(MyApp.class, args);
}

即便您不使用自动重启,您仍然能够从DevTools提供的其余功能中受益。

启用延迟初始化

您可使用 @Lazy 注释将各个bean标记为延迟初始化。这个功能在Spring已经有一段时间了。从 Spring Boot 2.2 开始,您可使用切换全部 bean 的延迟初始化spring.main.lazy-initialization=true。能够单独使用它,也能够将它与 DevTools 组合使用,以更快地重启。

DevTools能够在同一JVM中热重启您的应用程序。热重启的一个重要好处是,它为JIT提供了更多机会来优化启动应用程序所涉及的代码。重启几回后,原来的2500ms时间减小了近80%,接近500ms。经过延迟初始化,咱们能够作得更好。设置 spring.main.lazy-initialization 能够看到咱们的应用程序直接在IDE中在400毫秒内从新启动。

在生产应用程序中对全部bean使用延迟初始化是有问题的。它为启动提供了出色的性能提高,但代价​​是单个 Bean 的首次请求时间较长。更重要的是,您的应用程序再也不快速失败。它不会在启动应用程序时当即崩溃,而只会在直接请求配置错误的bean以后失败。这可能很是危险,由于直到为时已晚,您才发现不少错误。尽管如此,大规模延迟初始化对于加快开发时间仍是颇有用的,由于在使用某些功能时,您一般只在应用程序的一部分上工做,而其他部分则不使用。理想的折衷方法是仅对本地开发启用大规模延迟初始化(假设使用spring配置文件),而对于已部署的更高环境禁用它。

结论

经过提供自动重启和 LiveReload 功能,DevTools 使您的 Spring Boot 应用程序开发更加轻松快捷。除此以外,它还将各类属性设置为更适合本地开发的值。此外,它容许您远程链接到应用程序,而且仍使用其大多数功能。在生产环境中运行时,不使用 DevTools。有关详细信息,请参阅官方文档

相关文章
相关标签/搜索