SpringBoot包含了一套额外的工具集,可以让开发的过程更加愉快。spring-boot-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 {
-
-
}
注意:
运行一个完全打包的程序时会自动禁用开发者工具,如果你得程序通过java -jar或者通过一个特殊的类加载器启动,则会被认为是一个“生产”程序(会禁用开发者工具集)。如果这个对你不适用(你是通过容器启动的程序),可以考虑排除开发者工具或者设置程序的配置-Dspring.devtools.restart.enabled=false。
提示:
在Maven中标记依赖为可选或者在Gradle中设置自定义属性“仅开发”(如上所示),可以很好的避免过度的在你得项目其他模块应用开发工具。
提示:
默认情况,打包的文件中不包含开发工具,如果想远程的使用一些开发工具的功能,可以在构建属性值时禁用excludeDevtools来包含开发工具,这个属性Maven和Gradle都支持。
20.1 属性默认值
SpringBoot支持一些库使用缓存来提高性能。例如模板引擎可以缓存已编译的模板,避免对模板的反复解析。SpringMVC还可以将HTTP的头文件添加到缓存中,这样当访问静态资源时可以快速响应。
虽然缓存在生产环境效果显著,但是在开发时可能产生相反的效果,当你对程序进行更改后缓存机制会导致不会及时的刷新更改。由于这个的原因,SpringBoot开发工具会默认的禁用缓存。
通常来说,缓存选项的设置在你的application.properties文件中,开发者工具会自动得配置最优得开发时选项,而不是需要你手动得去设置。
由于在开发SpringMVC或Spring WebFlux程序时,我们需要看到更多得web请求信息,所以开发者工具会开启web日志组得调试日志功能。这个功能可以让你看到包括请求信息、正在处理请求得程序以及相应结果等信息。如果你需要对所有的信息(包括一些敏感得信息)记录日志,可以将spring.http.log-request-details属性打开。
注意:
如果你不想要自动的应用默认配置,可以将application.properties文件中的spring.devtools.addproperties属性设为false。
提示:
对于开发者工具应用的完整属性列表,可以参考DevToolsPropertyDefaultsPostProcessor。
20.2 自动重启
开发者工具会在任意在类路径内的文件有变化时自动重启系统,这个功能在使用IDE工具时非常有用,因为它可以快速的反馈代码更改带来的变化。默认情况下,任何指向类路径的文件都会被监控是否更改。另外注意有些资源的更改不需要重启程序,例如静态资源和试图模板。
引发重启:
因为开发者监视器监视的是类路径下的资源,所以唯一会引起重启的是更新了类路径(下的内容)。如何更新类路径取决于你使用的是什么IDE工具,例如,Eclipse在保存文件更改的时候会触发,而IDEA在构建项目时(Build -> Build Project)也会触发更改。
注意:
由于开发者工具需要一个独立的类加载器才能正确运行,所以只要分支是开启的,你同样可以通过受支持的插件(Maven或Gradle)来启动程序。当Gradle或Maven检测到类路径下含有开发工具,就会默认这样做。
提示:
自动重启和热加载一起使用往往有更好的效果,具体的细节看“热加载”部分。如果使用了JRebel,为了支持动态类加载会关闭自动重启功能,其他的开发工具功能(如热加载、属性覆盖等)依然可以使用。
注意:
在重启期间开发工具依赖应用上下文的关机钩子(shutdown hook)来关闭程序,如果关闭了关机钩子,则开发工具可能不会正确的进行重启。(SpringApplication.setRegisterShutdownHook(false))
注意:
判断任何一个实体内容发生改变时是否需要重启,开发工具会忽略含有spring-boot、spring-boot-devtools、spring-boot-autoconfigure、spring-boot-actuator以及spring-boot-starter名字的文件。
注意:
开发工具需要定制ApplicationContext上的ResourceLoader。如果程序已经提供了一个ApplicationContext,开发工具会覆盖ApplicationContext,而不会直接重写ApplicationContext上的getResource方法。
“重启”或是“重载”
Spring Boot通过两个类加载器来提供“重启”的技术。不会更改的类(例如第三方jar包里的类)会被加载进一个“基础类加载器”,而你正在开发中的类会被加载进一个“重启类加载器”。当应用重启时,(正在使用的)“重启类加载器”会被废弃掉,一个新的(重启类加载器)将会被创建。由于“基础类加载器”已经是可用状态,这意味着程序使用这种方式会比“冷启动”方式更快的重启。
如果你发现“重启”的速度不能够满足程序的需求,或者遇到了类加载问题,可以尝试使用ZeroTurnaround公司的JRebel的“重载”技术。这个插件通过重写class文件来快速的重载项目。
记录条件评估中的变化
默认情况下,每次程序重启时,都有一个条件评估增量的报告被记录。这份报告显示了你更改的自动配置项如增添/删减的bean,以及设置的配置属性。
如果想禁用记录报告的功能,设置属性如下:
spring.devtools.restart.log-condition-evaluation-delta=false
排除资源
某些资源的改变没有必要触发重启机制,例如Thymeleaf模板的就地编辑等。默认情况下,位于/META-INF/maven、/META-INF/resources、/resources、/static、/public和/templates下的文件发生的更改并不会触发重启机制,不过会触发重载(live reload)事件。如果你想自定义这些排除项,可以配置spring.devtools.restart.exclude属性。例如只想排除/static和/public文件夹,可以设置如下:
spring.devtools.restart.exclude=static/**,public/**
提示:
如果你想在保留这些默认配置的情况下添加额外的排除项,可以在spring.devtools.restart.additional-exclude属性代替上面的配置。
监测其他路径
如果你想让“重启”机制监视一个不在类路径下的文件,即当其改变内容时触发重启,可以通过设置spring.devtools.restart.additional-paths属性来实现额外的监视路径。你可以通过上面提到的spring.devtools.restart.exclude属性来控制额外路径下文件内容改变时是进行重启还是重载。
禁用重启机制
如果你不想使用重启功能,可以通过spring.devtools.restart.enabled属性禁用它。你可以在application.properties文件中设置这些属性(设置后仍会初始化“重启类加载器”,只是不会监控文件的改变了)。
如果你想完全的禁用重启功能(例如因为重启功能和某些类库不能一起工作),可以在调用SpringApplication.run(…)方法之前设置spring.devtools.restart.enabled System属性值为false,示例如下:
-
public static void main(String[] args) {
-
System.setProperty(“spring.devtools.restart.enabled”, “false”);
-
SpringApplication.run(MyApp.class, args);
-
}
使用触发器文件
当你使用IDE工具不断地重新编译更改的文件时,你可能更想要在特殊的时间触发重启。为了达到这种效果,你可以使用一个“触发文件”,只有当触发文件法生更改时,才会实际的触发重启机制。修改文件只会触发检查,而只有Devtools认为必要的时候才会进行重启。触发文件的可以手工修改或是通过IDE插件进行修改。
通过在spring.devtools.restart.trigger-file属性中设置你的触发文件路径,来使用“触发文件”。
提示:
你可能会希望将spring.devtools.restart.trigger-file属性设置为全局属性,这样保证所有的项目保持行为的一致。
自定义“重启类加载器”
在上面的“重启或重载”部分提到了,“重启”是通过两个类加载器实现的。大部分项目中,这种方式可以很好的工作,然而有时也会导致类加载异常。
默认情况下,所有在IDE中打开的项目都是通过“重启类加载器”加载的,而所有不变的.jar文件都是通过“基础类加载器”进行加载的。当你正在开发一个多模块的应用时,不是每个模块都会导入进IDE中,这时候你需要自定义一些属性。可以通过创建一个META-INF/spring-devtools.properties文件来实现自定义。
spring-devtools.properties文件包含了前缀为restart.exclude和restart.include的属性,include属性中的项目是应该放进“重启类加载器”中的,而exclude中的项目是应该放进“基础类加载器”中的。这个属性的值应该是一个类路径的正则表达,示例如下:
-
restart.exclude.companycommonlibs=/mycorp-common-[\\w-]+\.jar
-
restart.include.projectcommon=/mycorp-myproj-[\\w-]+\.jar
注意:
所有属性的关键字必须是唯一的,只要属性前缀是restart.include.或restart.exclude.就会被认为是自定义项。
提示:
所有来自类路径下的META-INF/spring-devtools.properties文件都会被加载,你可以在项目内部中或者项目使用的库中打包文件。(这句没看懂)
已知的限制
当使用标准ObjectInputStream流反序列化的对象时,重启机制不会正常的工作。可以使用Spring的ConfigurableObjectInputStream和Thread.currentThread().getContextClassLoader()的结合来进行数据的反序列化。
不幸的是,有些第三方类库反序列化时没考虑到使用context classloader,如果你发现了这样的问题,你需要和类库的作者联系修复。
20.3 LiveReload
spring-boot-devtools包含了一个嵌入式的LiveReload服务器,它可以在资源修改时触发浏览器的刷新。可以在livereload.com中找到Chrome、Firefox和Safari免费的LiveReload插件。
如果你不想使用LiveReload服务,可以设置spring.devtools.livereload.enabled属性为false。
注意:
在同一时间只能使用一个LiveReload服务,在开启你得程序之前确保没有其他的LiveReload服务正在运行。如果你通过IDE工具打开了多个项目,只有第一个项目支持LiveReload服务。
20.4 全局设置
你可以通过向$HOME文件夹添加名为.spring-boot-devtools.properties的文件来配置全局devtools设置(请注意,文件名以“.”开头)。 添加到此文件的任何属性将适用于你的计算机上使用devtools的所有 Spring Boot应用程序。 例如,要配置重启始终使用触发器文件 ,你可以在~/.spring-boot-devtools.properties中添加以下内容:
spring.devtools.reload.trigger-file=.reloadtrigger
注意:
在.spring-boot-devtools.properties文件中激活的属性不会影响profile-specific configuration files的加载。
20.5 远程应用
Spring Boot的开发者工具并不限制于本地开发,在运行远程程序时也可以使用一些功能。远程支持是可选择的,想开启支持,首先你要确认devtools包含在重打包的文档中,如下;
-
<build>
-
<plugins>
-
<plugin>
-
<groupId>org.springframework.boot</groupId>
-
<artifactId>spring-boot-maven-plugin</artifactId>
-
<configuration>
-
<excludeDevtools>false</excludeDevtools>
-
</configuration>
-
</plugin>
-
</plugins>
-
</build>
然后如下的配置spring.devtools.remote.secret属性:
spring.devtools.remote.secret=mysecret
警告:
在一个远程的应用中启动spring-boot-devtools是存在安全风险的,不要再生产环境中启动该支持。
远程devtools支持包括两部分:1.接受连接的服务端;2.在IDE中运行的客户端。服务端在设置spring.devtools.remote.secret后自动开启,客户端则必须手动开启。
运行远程客户端程序
远程客户端程序是为了在IDE中运行而设计的,你需要使用与你连接的远程项目相同的类路径来运行org.springframework.boot.devtools.RemoteSpringApplication。这个程序需要的唯一的参数就是它连接的URL。
例如,当你使用Eclipse或STS时,有一个在Cloud Foundry上的my-app项目,按下面的步骤操作:
- 在Run菜单中选择Run Configurations…
- 创建一个新的Java项目“launch configuration”
- 浏览my-app项目
- 把org.springframework.boot.devtools.RemoteSpringApplication当成main类
- 添加https://myapp.cfapps.io到程序参数中(或者你得远程URL)
正在运行的远程客户端可能像下面这样:
-
. ____ _ __ _ _
-
/\\ / ___’_ __ _ _(_)_ __ __ _ ___ _ \ \ \ \
-
( ( )\___ | ‘_ | ‘_| | ‘_ \/ _` | | _ \___ _ __ ___| |_ ___ \ \ \ \
-
\\/ ___)| |_)| | | | | || (_| []::::::[] / -_) ‘ \/ _ \ _/ -_) ) ) ) )
-
‘ |____| .__|_| |_|_| |_\__, | |_|_\___|_|_|_\___/\__\___|/ / / /
-
=========|_|==============|___/===================================/_/_/_/
-
:: Spring Boot Remote :: 2.1.5.RELEASE
-
-
2015-06-10 18:25:06.632 INFO 14938 — [ main] o.s.b.devtools.RemoteSpringApplication :
-
Starting RemoteSpringApplication on pwmbp with PID 14938 (/Users/pwebb/projects/spring-boot/code/
-
spring-boot-devtools/target/classes started by pwebb in /Users/pwebb/projects/spring-boot/code/spring-
-
boot-samples/spring-boot-sample-devtools)
-
2015-06-10 18:25:06.671 INFO 14938 — [ main] s.c.a.AnnotationConfigApplicationContext :
-
Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@2a17b7b6: startup
-
date [Wed Jun 10 18:25:06 PDT 2015]; root of context hierarchy
-
2015-06-10 18:25:07.043 WARN 14938 — [ main] o.s.b.d.r.c.RemoteClientConfiguration : The
-
connection to http://localhost:8080 is insecure. You should use a URL starting with ‘https://’.
-
2015-06-10 18:25:07.074 INFO 14938 — [ main] o.s.b.d.a.OptionalLiveReloadServer :
-
LiveReload server is running on port 35729
-
2015-06-10 18:25:07.130 INFO 14938 — [ main] o.s.b.devtools.RemoteSpringApplication :
-
Started RemoteSpringApplication in 0.74 seconds (JVM running for 1.105)
注意:
因为远程客户端使用了和真是项目相同的路径,所以可以直接读取项目的配置。这是spring.devtools.remote.secret属性如何被读取以及如何通过服务器验证的原因。
提示:
通常建议使用https://协议进行连接,这样就可以对通信进行加密,密码也不会被拦截。
提示:
如果你需要通过代理访问远程项目,需要对spring.devtools.remote.proxy.host和spring.devtools.remote.proxy.port属性进行配置。
远程更新
远程客户端通过和本地“重启”机制相同的方式监视类路径文件的变化。任何更新后的文件会被push进远程应用并且触发重启(如果需要的话)。如果你使用本地应用没有的云服务特性来更新迭代,这将非常有用。通常来说,远程更新和重启比完整的构建部署的周期快很多。
注意:
文件只在远程客户端开启的时候会被监控,如果你在远程客户端启动之前改变文件,则更新不会推送到远程服务器上。