开发者工具
Spring Boot包括一组额外的工具,可以使应用程序开发体验更加友好.spring-boot-devtools模块可以包含在任何项目中,以提供额外的开发时间功能.只需要将依赖添加到你的构建中:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
开发者工具在应用打包运行时会自动禁用.如果你的应用程序是使用java -jar启动的,或者如果它使用特殊的类加载器启动,那么它会被人是一个"生产应用程序".将依赖项标记为可选是一种最佳实践.可以防止devtools被过渡性地应用于项目的其他模块,gradle不支持开箱即用的可选依赖项,因此你可能希望在此期间查看prodeps-plugin. 重新打包的存档默认不包含devtools.如果使用某些远程devtools功能,则需要禁用excludeDevtools构建属性.该属性支持maven和gradle插件
属性默认值
Spring Boot支持的几个库使用缓存来提供性能.例如,Thymeleaf将缓存模板以保存重复解析xml文件.虽然缓存在生产中非常有益,但在开发过程中可能会引起反作用.如果你在ide中对模板文件进行更改,你可能无法立即看到效果
有关应用的属性的完整列表,请参阅DevToolsPropertyDefaultsPostProcessor。
自动重启
使用spring-boot-devtools的应用程序将在classpath上的文件发生更改时自动重新启动。这在使用IDE时可能是一个有用的功能,因为它为代码更改提供了非常快速的反馈回路.默认情况下,Spring boot监视指向文件夹的classpath上的任何内容的更改.请注意,某些资源(如静态资产和视图模板)不需要重新启动应用程序
- 触发重启 由于DevTools监视classpath资源,触发重启的唯一方式是更新classpath.你更新classpath方式取决于你使用的ide。在eclipse中,保存修改的文件将导致classpath更新并触发重新启动.在intellij idea中,构建项目(build->Make Project)也会触发.
- 你也可以通过支持的构建插件(maven或gradle)启动你的应用。因为devtools需要一个隔离的应用程序来加载器来加载它,maven和gradle默认情况下载classpath上检查到devtools时执行
- 当与liveReload一起使用时,自动重启非常有效.如果使用JRebel,自动重启将被禁用,有利于动态类重新加载.其他的devtools(例如LiveReload和属性覆盖)功能任然可以使用
- DevTools依赖于应用程序上下文的关闭挂接,在重启期间关闭它.如果你已经禁用关闭挂接(SpringApplication.setRegisterShutdownHook(false)),它将无法正常工作
- 当决定classpath上的条目应该在更改时触发重启时,devtools会自动忽略名为spring-boot,spring-boot-devtools,spring-boot-autoconfigure,spring-boot-actuator和sping-boot-starter的项目
重新启动vs重新加载 Spring Boot提供的重启技术使用两个类加载器。 不改变的类(例如,来自第三方jar的类)被加载到基类加载器中。 您正在开发的类将加载到重新启动的类加载器中。 当应用程序重新启动时,将重新启动类加载器,并创建一个新的类加载器。 这种方法意味着应用程序重新启动通常比“冷启动”快得多,因为基本类加载器已经可用并已填充。
如果您发现重新启动对于您的应用程序不够快速,或者遇到类加载问题,您可以考虑从ZeroTurnaround重新加载诸如JRebel。它会通过在价值类时重新类,从而使它们梗荣重新加载,Spring Loaded是另一个选项,但它不支持更多的框架,不是商业支持
排除resources
某些资源在更改时不一定需要触发重启。例如,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属性。
监视其他路径
你可能希望对于那些不在classpath路径上的文件进行更改时重启或者重新加载应用程序,你可以使用spring.devtools.restart.additional-paths属性配置其他路径以监视更改.你可以使用上述的spring.devtools.restart.exclude属性来控制额外路径下的更改是否将触发完全重新启动或仅重新加载。
禁用重新启动
如果不想使用重新启动功能,可以使用spring.devtools.restart.enabled属性禁用它。 在大多数情况下,您可以在您的application.properties中设置(这将仍然初始化重新启动类加载器,但它不会监视文件更改)。
如果您需要完全禁用重新启动支持,例如,因为它不适用于特定的库,您需要在调用SpringApplication.run(...)之前设置一个System属性。 例如:
public static void main(String[] args) {
System.setProperty("spring.devtools.restart.enabled", "false");
SpringApplication.run(MyApp.class, args);
}
使用触发文件(trigger file)
如果使用不断编译更改文件的IDE,你可能希望仅在特定时间触发重新启动.为此,你可以使用"触发文件",这是一个特殊文件,当你想要实际触发重新启动检查时,必须对其进行修改.更改文件只触发检查,如果devtolls检查到它必须做某些事,只会发生重启。触发文件可以手动更新,也可以通过IDE插件进行更新。 要使用触发器文件,请使用spring.devtools.restart.trigger-file属性。
您可能希望将spring.devtools.restart.trigger-file设置为全局设置,以便所有项目的行为方式相同。
自定义重新启动类加载器
如上面的重新启动vs重新加载部分所述,重新启动功能是通过使用两个类加载器实现的。 对于大多数应用程序,此方法运行良好,但是,有时它可能会导致类加载问题。 默认情况下,IDE中的任何打开的项目都将使用“restart”类加载器加载,并且任何正常的.jar文件将使用“base”类加载器加载.如果你在多模块项目上工作,而不是每个模块都导入到IDE中,则可能需要自定义加载器.为此,你可以创建一个META-INF/spring-devtools.properties文件 spring-devtools.properties文件可以包含restart.exclude和restart.include预绑定属性.include元素是应该被拉到“restart"类加载器中的项目,而exclude元素应该是被推入"base"类加载器的项目.属性的值是将应用于classpath的正则表达式模式.例如:
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()结合使用
有很多第三库的反序列不考虑上下文的类加载器.如果你发现这种问题,你只能找作者进行修复了
LiveReload
spring-boot-devtools模块包含一个嵌入的LiveReload服务器,可用于在资源更改时触发浏览器刷新。LiveReload浏览器可以从livereload.com免费拓展Chrome,Firefox和Safari。 如果您不想在应用程序运行时启动LiveReload服务器,可以将spring.devtools.livereload.enabled属性设置为false。
一次只能运行一个LiveReload服务器。 在启动应用程序之前,请确保没有其他LiveReload服务器正在运行。 如果从IDE启动多个应用程序,只有第一个应用程序将支持LiveReload。
全局设置
你可以在$HOME目录添加一个名为.spring-boot-devtools.properties的文件来配置全局devtools设置(注意,文件名以"."开头).添加到此文件的任何属性将应用于使用devtools的所有Spring Boot应用.例如需要配置重新启动以使用触发器文件,可以添加如下内容: ~/.spring-boot-devtools.properties.
spring.devtools.reload.trigger-file=.reloadtrigger
远程应用
远程客户端应用程序旨在从IDE中运行。 您需要使用与您要连接的远程项目相同的类路径运行org.springframework.boot.devtools.RemoteSpringApplication。 传递给应用程序的非选项参数应该是要连接到的远程URL.
例如,如果您使用Eclipse或STS,并且您已将一个名为my-app的项目部署到Cloud Foundry,那么您将执行以下操作:
- 从run菜单中选择run configurations
- 创建一个新的java application为“launch configuration”。
- 浏览my-app项目
- 使用 org.springframework.boot.devtools.RemoteSpringApplication作为main类
- 将https://myapp.cfapps.io添加到程序参数(或任何远程URL)。
正在运行的远程客户端将如下所示:
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ ___ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | | _ \___ _ __ ___| |_ ___ \ \ \ \
\\/ ___)| |_)| | | | | || (_| []::::::[] / -_) ' \/ _ \ _/ -_) ) ) ) )
' |____| .__|_| |_|_| |_\__, | |_|_\___|_|_|_\___/\__\___|/ / / /
=========|_|==============|___/===================================/_/_/_/
:: Spring Boot Remote :: 2.0.0.BUILD-SNAPSHOT
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属性。
远程更新
远程客户端将以与本地重新启动相同的方式监视应用程序类路径的更改。 任何更新的资源将被推送到远程应用程序,并且(如果需要)触发重新启动。 如果您对使用您本地没有的云服务的功能进行迭代,这可能非常有用。 通常,远程更新和重新启动比完全重建和部署周期快得多。
仅当远程客户端正在运行时才会监视文件。 如果在启动远程客户端之前更改文件,则不会将其推送到远程服务器。
远程debug
java远程调试在诊断远程应用程序上的问题时很有用.不辛的是,当应用部署在数据中心之外时,并不一定能够启用远程调试.比如说你使用了docer. 为了帮助解决这些限制,devtools支持通过http的远程调试流的隧道(tunnel).远程客户端在端口8000上提供了一个可用附加远程调试器的本地服务器.一旦建立连接,调试流将通过HTTP发送到远程应用.(如果要使用其他端口,可用spring.devtools.remote.debug.local-port属性。)
你需要确保启用远程调试后启动远程应用.通常这些通过配置java_opts来实现.例如,使用cloud foundry,你可以将以下内容添加到manifest.yml:
---
env:
JAVA_OPTS: "-Xdebug -Xrunjdwp:server=y,transport=dt_socket,suspend=n"
请注意,您不需要将address=NNN选项传递给-Xrunjdwp,如果省略,java将简单的选择一个随机空闲端口 通过Internet调试远程服务可能很慢,您可能需要在IDE中增加超时。 例如,在Eclipse中,您可以选择Java→从首选项调试...并将调试器超时(ms)更改为更合适的值(60000在大多数情况下运行良好)。