SpringBoot包含了一套额外的工具集,可以让开发的过程更加愉快。spring-boot-devtools模块可以在任何工程中被添加,以支持一些额外的开发时特性。在构建时添加模块的依赖,这样项目就支持了开发者工具集,Maven和Gradle的示例如下:

Maven:

  1.  
    <dependencies>
  2.  
    <dependency>
  3.  
    <groupId>org.springframework.boot</groupId>
  4.  
    <artifactId>spring-boot-devtools</artifactId>
  5.  
    <optional>true</optional>
  6.  
    </dependency>
  7.  
    </dependencies>

Gradle:

  1.  
    configurations {
  2.  
    developmentOnly
  3.  
    runtimeClasspath {
  4.  
    extendsFrom developmentOnly
  5.  
    }
  6.  
    }
  7.  
    dependencies {
  8.  
    developmentOnly(“org.springframework.boot:spring-boot-devtools”)
  9.  
    }

注意:

        运行一个完全打包的程序时会自动禁用开发者工具,如果你得程序通过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-bootspring-boot-devtoolsspring-boot-autoconfigurespring-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,示例如下:

  1.  
    public static void main(String[] args) {
  2.  
    System.setProperty(“spring.devtools.restart.enabled”, “false”);
  3.  
    SpringApplication.run(MyApp.class, args);
  4.  
    }

使用触发器文件

        当你使用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.excluderestart.include的属性,include属性中的项目是应该放进“重启类加载器”中的,而exclude中的项目是应该放进“基础类加载器”中的。这个属性的值应该是一个类路径的正则表达,示例如下:

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

注意:

        所有属性的关键字必须是唯一的,只要属性前缀是restart.include.restart.exclude.就会被认为是自定义项。

提示:

        所有来自类路径下的META-INF/spring-devtools.properties文件都会被加载,你可以在项目内部中或者项目使用的库中打包文件。(这句没看懂)

已知的限制

        当使用标准ObjectInputStream流反序列化的对象时,重启机制不会正常的工作。可以使用Spring的ConfigurableObjectInputStreamThread.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包含在重打包的文档中,如下;

  1.  
    <build>
  2.  
    <plugins>
  3.  
    <plugin>
  4.  
    <groupId>org.springframework.boot</groupId>
  5.  
    <artifactId>spring-boot-maven-plugin</artifactId>
  6.  
    <configuration>
  7.  
    <excludeDevtools>false</excludeDevtools>
  8.  
    </configuration>
  9.  
    </plugin>
  10.  
    </plugins>
  11.  
    </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)

        正在运行的远程客户端可能像下面这样:

  1.  
    . ____ _ __ _ _
  2.  
    /\\ / ___’_ __ _ _(_)_ __ __ _ ___ _ \ \ \ \
  3.  
    ( ( )\___ | ‘_ | ‘_| | ‘_ \/ _` | | _ \___ _ __ ___| |_ ___ \ \ \ \
  4.  
    \\/ ___)| |_)| | | | | || (_| []::::::[] / -_) ‘ \/ _ \ _/ -_) ) ) ) )
  5.  
    ‘ |____| .__|_| |_|_| |_\__, | |_|_\___|_|_|_\___/\__\___|/ / / /
  6.  
    =========|_|==============|___/===================================/_/_/_/
  7.  
    :: Spring Boot Remote :: 2.1.5.RELEASE
  8.  
     
  9.  
    2015-06-10 18:25:06.632 INFO 14938 — [ main] o.s.b.devtools.RemoteSpringApplication :
  10.  
    Starting RemoteSpringApplication on pwmbp with PID 14938 (/Users/pwebb/projects/spring-boot/code/
  11.  
    spring-boot-devtools/target/classes started by pwebb in /Users/pwebb/projects/spring-boot/code/spring-
  12.  
    boot-samples/spring-boot-sample-devtools)
  13.  
    2015-06-10 18:25:06.671 INFO 14938 — [ main] s.c.a.AnnotationConfigApplicationContext :
  14.  
    Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@2a17b7b6: startup
  15.  
    date [Wed Jun 10 18:25:06 PDT 2015]; root of context hierarchy
  16.  
    2015-06-10 18:25:07.043 WARN 14938 — [ main] o.s.b.d.r.c.RemoteClientConfiguration : The
  17.  
    connection to http://localhost:8080 is insecure. You should use a URL starting with ‘https://’.
  18.  
    2015-06-10 18:25:07.074 INFO 14938 — [ main] o.s.b.d.a.OptionalLiveReloadServer :
  19.  
    LiveReload server is running on port 35729
  20.  
    2015-06-10 18:25:07.130 INFO 14938 — [ main] o.s.b.devtools.RemoteSpringApplication :
  21.  
    Started RemoteSpringApplication in 0.74 seconds (JVM running for 1.105)

注意:

        因为远程客户端使用了和真是项目相同的路径,所以可以直接读取项目的配置。这是spring.devtools.remote.secret属性如何被读取以及如何通过服务器验证的原因。

提示:

        通常建议使用https://协议进行连接,这样就可以对通信进行加密,密码也不会被拦截。

提示:

        如果你需要通过代理访问远程项目,需要对spring.devtools.remote.proxy.hostspring.devtools.remote.proxy.port属性进行配置。

远程更新

        远程客户端通过和本地“重启”机制相同的方式监视类路径文件的变化。任何更新后的文件会被push进远程应用并且触发重启(如果需要的话)。如果你使用本地应用没有的云服务特性来更新迭代,这将非常有用。通常来说,远程更新和重启比完整的构建部署的周期快很多。

注意:

        文件只在远程客户端开启的时候会被监控,如果你在远程客户端启动之前改变文件,则更新不会推送到远程服务器上。