Spring Boot中文手册(9):常用的Spring Boot开发工具(一)

“ 该系列的文章主要参考Spring Boot 2.1.2.RELEASE的官方文档来进行翻译,逐步将官方文档翻译过来,方便大家共同学习和讨论,但是毕竟能力有限,如有问题,感谢大家留言指正。”

Spring Boot包含了一些额外的工具集,用于提升Spring Boot应用的开发体验。 spring-boot-devtools 模块可以被included到任何工程中,以提供development-time特性。想要添加devtools的支持,只需要在你的构建组件中增加依赖即可,下面给出了Maven和Gradle的配置:

Maven:

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

Gradle:

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

在运行一个已打包的程序时,Developer tools是被自动禁用的。如果你的程序是使用java -jar启动的,或者是使用一个特殊的classloader启动的,它会被认为是一个产品级的程序。为了避免devtools被传递到你工程中的其他模块里,在Maven中最好设置该依赖的级别为optional,或者在Gradle中使用developmentOnly配置。

重新打包的产物中默认是不包含devtools的,如果你确定要使用远程devtools特性,你需要禁用“excludeDevtools”这个构建属性来保证将devtools被包含到你的项目中。Maven和Gradle都插件都是支持这个属性的。

1. 默认属性

Spring Boot支持的一些类库会使用缓存来提升性能。比如,模板引擎会缓存编译之后的模板,来避免重复编译。同样,Spring MVC也会增加HTTP缓存头内容,来响应相同的静态资源请求。

虽然缓存技术在产品阶段是非常有意义的,但是在开发阶段却适得其反,它让你看不到你刚刚修改程序之后的效果,所以Spring Boot devtools默认是禁用了缓存属性的。

缓存配置通常是被配置在 application.properties 文件中。比如,Thymeleaf提供了 spring.thymeleaf.cache 这项属性。 spring-boot-devtools 模块会自动应用敏感的development-time配置。

当你在部署Spring MVC程序或者WebFlux程序时,你需要获取更多与web请求相关的信息,devtools可以启用web相关的 DEBUG 日志记录。你可以获取所有请求的跟多信息,哪个handler在处理它,返回的response包含什么等等。如果你希望记录更详细的请求信息(比如潜藏的敏感信息),你可以打开 spring.http.log-request-details 这个属性配置。

如果你不想使用默认的属性配置,你可以在你的程序中设置属性spring.devtools.add-properties为false。

官方网站上也提供了devtools的属性清单,稍后的文章里也会给大家列出。

2. 自动重启

如果你的程序使用了 spring-boot-devtools ,在classpath下的文件发生变化时, spring-boot-devtools 就会自动重启。这在你使用IDE开发时是很有用的,它能给你一个很及时的代码变更反馈。默认情况下,classpath的每个入口都对应着一个目录,这个目录被监听是否发生了变化,注意一些资源的修改比如静态assets,视图模板不需要重启应用。

触发重启

因为DevTools监控classpath下的资源,所以唯一处理重启的方式就是更新classpath。引起classpath被更新的方式取决于你使用的IDE是哪种,在Eclipse中,修改一个文件会引起classpath的更新然后触发重启动作,但是在IntelliJ IDEA中,构建工程 (Build -> Build Project)才会如此。

当fork功能被开启的时候,你也可以通过构建被支持的 (Maven 和 Gradle)构建插件来启动你的程序,因为DevTools需要一个隔离的程序类加载器才能正常运行。默认情况下,当Gradle和Maven在classpath中检测到DevTools时就会生效。

当使用LiveReload机制的时候,自动重启是生效的,你可以在介绍LiveReload的章节获取更多细节。但是如果你使用JRebel,自动重启机制是被禁用的,取而代之的是动态类加载,不过其他的devtools特性(比如LiveReload、属性覆盖)仍然是可以使用的。

DevTools依赖程序上下的shutdown hook来在程序重启时关闭它,但是如果你禁用了shutdown hook(比如你添加了配置:SpringApplication.setRegisterShutdownHook(false)),那么这个就不生效了。

当判定classpath下的改变是否会触发重启时,DevTools会根据工程名称自动忽略以下工程:spring-boot,spring-boot-devtools,spring-boot-autoconfigure,spring-boot-actuator和spring-boot-starter。

DevTools需要定制ApplicationContext使用的那个ResourceLoader。如果你的程序已经提供了另外一个ResourceLoader,它会被再次封装。直接重新ApplicationContext的getResource方法是没用的。

Restart vs Reload
Spring Boot提供的重启技术是通过使用两个类加载器实现的。那些不会发生改变的第三方jar包的类被加载到了一个base类加载器中。你频繁开发编写的那些类被加载到了restart类加载器中。当程序重启时,restart类加载器会被丢弃,并且创建一个新的restart类加载器,这种方式意味着程序重启通常会比冷启动(cold restart)要快得多,因为base类加载器已经已经可用并且在那里了。
如果你发现你的程序重启并没有你想象的那么快,或者遇到了类加载的问题,你可以考虑其他的reload技术,比如 ZeroTurnaround的JRebel。这些技术都是通过重写类加载器实现的,可以在类加载的时候进行更多的优化来提升性能。

2.1 在状态评估中记录变化

默认情况下,每次你的程序重新启动,在状态评估中会给你展示一个报告,在报告里会显示你程序的自动配置中哪些发生的变化,比如添加或者删除beans,设置配置属性等。

可以使用下面的属性配置方式来禁用这个功能:

spring.devtools.restart.log-condition-evaluation-delta=false
2.2 资源排除

已经确定的资源文件发生改变时,没必要再出发一次重启。比如Thymeleaf模板可以就地编辑,不需要重新启动服务。默认情况下,修改 /META-INF/maven, /META-INF/resources, /resources, /static, /public, 或者 /templates 这些目录下的文件不会触发一次重启,但是会触发一次热加载。如果你想自定义这些排除规则,你可以使用 spring.devtools.restart.exclude 参数来进行配置,比如只要排除 /static 和 /public 目录,你可以这样配置:

spring.devtools.restart.exclude=static/**,public/**

如果你想保留默认配置的那些目录,并且想增加其他的排除目录,你可以使用 spring.devtools.restart.additional-exclude参数来进行配置。

2.3 查看其他路径

你也想当你改变classpath路径之外的文件时,你的程序也会重启或者重新加载。要达到这个效果,你可以使用spring.devtools.restart.additional-paths 这个参数来监控变化。你可以使用 spring.devtools.restart.exclude来控制额外路径下的变化是否触发一个完整重启或只是一个实时重新加载。

2.4 禁用重启

如果你不想使用重启特性,你可以使用 spring.devtools.restart.enabled 这个参数来禁用它。大多数情况下,你可以在 文件中配置这个属性(这样配置的话依然出初始化这个restart classloader,但是它不会监视文件变化)。

如果你想完全禁用重启特性(例如,当它和另外一个指定的类库冲突时),你需要在调用 SpringApplication.run(…),之前设置 spring.devtools.restart.enabled 这个参数为false,如下面的例子所示:

public static void main(String[] args) {
    
    
    System.setProperty("spring.devtools.restart.enabled", "false");
    SpringApplication.run(MyApp.class, args);
}
2.5 使用文件触发

如果你使用一个IDE来进行开发,你势必会不间断地编译变更的文件,此时你会更倾向于在特定的时间来触发重启动作,使用一个触发文件可以帮助你达到这个效果。触发文件是一个特殊的文件,只有当这个文件被修改时,才会触发重启检查。修改这个文件只会触发检查的动作,只有Devtools监测到它需要这么做时才会触发重启动作。这个触发文件可以使用手动更新,也可以使用IDE插件更新。

要使用触发文件,可以配置 spring.devtools.restart.trigger-file 属性来指定你的触发文件路径。

你可以把spring.devtools.restart.trigger-file添加到全局配置里面,这样你所有的项目都会生效。(下文会提到全局属性如何配置)

2.6 自定义restart类加载器

如前面到的关于Restart vs Reload 中所说,重启功能是通过两个类加载器实现的,对于大多数程序来说是没有问题的。但是有的时候回引发一些类加载的问题。

默认情况,在IDE里打开的项目会通过’restart’类加载器加载,其他常规的.jar文件会使用’basic’类加载器加载。如果你工作在一个多模块的项目下,并且不是每个模块都导入IDE里,你可能需要自定义一些东西。你需要创建一个META-INF/spring-devtools.properties文件,spring-devtools.properties文件可以包含restart.exclude.,restart.include.前缀的属性。include元素定义了那些需要加载进’restart’类加载器中的实体,exclude元素定义了那些需要加载进’basic’类加载器中的实体,这些属性的值是一个将应用到classpath的正则表达式。如下面的例子所示:

restart.exclude.companycommonlibs=/mycorp-common-[\\w-]+\.jar
restart.include.projectcommon=/mycorp-myproj-[\\w-]+\.jar

所有属性的keys必须唯一,只要以restart.include.或restart.exclude.开头都会考虑进去。

所有来自classpath的META-INF/spring-devtools.properties都会被加载,你可以将文件打包进工程或工程使用的库里。

2.7 已知的限制

重启功能不能跟使用标准ObjectInputStream反序列化的对象工作,如果需要反序列化数据,你可能需要使用Spring的ConfigurableObjectInputStream,并结合Thread.currentThread().getContextClassLoader()

不幸的是,一些第三方库反序列化时没有考虑上下文类加载器,如果发现这样的问题,你需要请求原作者给处理下。

END在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/tearofthemyth/article/details/86712201