1
0
mirror of https://github.com/apachecn/spring-boot-doc-zh.git synced 2025-06-06 17:50:57 +00:00
wizardforcel cdd1ca7535 mkdocs
2018-11-26 15:20:07 +08:00

18 KiB
Raw Blame History

20. 开发工具

Spring Boot包括一组额外的工具可以使应用程序开发体验更加愉快。 spring-boot-devtools模块可以包含在任何项目中以提供额外的开发时功能。 要包含devtools支持只需将模块依赖关系添加到您的构建中

Maven

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

Gradle

dependencies {
    compile("org.springframework.boot:spring-boot-devtools")
}

当运行完全打包的应用程序时,开发人员工具将自动禁用。 如果您的应用程序是使用java -jar启动的或者是使用特殊的类加载器启动那么它将会被认为是“生产环境的应用程序”。 将开发工具依赖关系标记为可选(optional)是一种最佳做法可以防止使用项目将devtools传递性地应用于其他模块。 Gradle不支持开箱即用的可选依赖项因此您可能希望在此期间查看propdeps-plugin

重新打包的jar包默认情况下不包含devtools。 如果要使用某些远程devtools功能您需要禁用excludeDevtools 构建下的属性以包含devtools。 该属性支持Maven和Gradle插件。

20.1 属性默认值

Spring Boots支持的几个库使用缓存来提高性能。 例如,模板引擎将缓存编译的模板,以避免重复解析模板文件。 此外Spring MVC可以在返回静态资源时向响应中添加HTTP缓存头。

虽然缓存在生产中非常有益,但它在开发过程中可能会产生反效果,从而阻止您看到刚刚在应用程序中进行的更改。 因此spring-boot-devtools将默认禁用这些缓存选项。

缓存选项通常由您的application.properties文件中的设置配置。 例如Thymeleaf提供了spring.thymeleaf.cache属性。 spring-boot-devtools模块不需要手动设置这些属性而是自动应用更加合理的开发时(development-time)配置。

有关应用的属性的完整列表,请参阅 DevToolsPropertyDefaultsPostProcessor

20.2 自动重启

使用spring-boot-devtools的应用程序将在类路径上的文件发生更改时自动重新启动。 这在IDE中开发时可能是一个有用的功能因为它为代码更改提供了非常快的反馈循环。 默认情况下,将监视指向文件夹的类路径上的任何条目。 请注意,某些资源(如静态资源和视图模板)不需要重新启动应用程序。

触发重启

当DevTools监视类路径资源时触发重新启动的唯一方法是更新类路径中的文件时。 导致类路径更新的方式取决于您正在使用的IDE。 在Eclipse中保存修改的文件将导致类路径被更新并触发重新启动。 在IntelliJ IDEA中构建项目Build→Make Project将具有相同的效果。

只要 forking 被启用您也可以通过支持的构建插件即Maven和Gradle启动应用程序因为DevTools需要一个单独的应用程序类加载器才能正常运行。Gradle和Maven默认情况下在类路径上检DevTools。

自动重启当与LiveReload一起使用时工作非常好。 详见下文。 如果您使用JRebel自动重启将被禁用有利于动态类重新加载。 其他devtools功能仍然可以使用如LiveReload和属性覆盖

DevTools依赖于应用程序上下文的关闭钩子以在重新启动期间关闭它。 如果禁用了关闭挂钩SpringApplication.setRegisterShutdownHookfalseDevTools将无法正常工作。

当判断类路径中的项目是否会在更改时触发重新启动时DevTools会自动忽略名为spring-bootspring-boot-devtoolsspring-boot-autoconfigurespring-boot-actuator和spring-boot-start的项目。

重新启动(Restart) vs 重新加载(Reload)

Spring Boot提供的重新启动技术使用两个类加载器。 不会改的类例如来自第三方的jar被加载到基类加载器中。 您正在开发的类被加载到重新启动(restart)类加载器中。 当应用程序重新启动时,重新启动类加载器将被丢弃,并创建一个新的类加载器。 这种方法意味着应用程序重新启动通常比“冷启动”快得多,因为基类加载器已经可以使用。

如果发现重新启动对应用程序不够快或遇到类加载问题您可以考虑来自ZeroTurnaround的JRebel等重新加载技术。 这些工作通过在加载类时重写(rewriting)类,使其更适合重新加载。 Spring Loaded提供了另一个选项但是它在很多框架上不支持并且不支持商用。

20.2.1 排除资源

在类路径下,某些资源在更改时不一定需要触发重新启动。 例如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属性。

20.2.2 监视额外的路径

有时当您对不在类路径中的文件进行更改时需要重新启动或重新加载应用程序。为此请使用spring.devtools.restart.additional-paths属性来配置其他路径以监视更改。 您可以使用[上述](described above)的spring.devtools.restart.exclude属性来控制附加路径下的更改是否会触发完全重新启动或只是实时重新加载

20.2.3 禁用重启

如果不想使用重新启动功能可以使用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);
}

20.2.4 使用触发文件

如果您使用IDE工具编写代码更改文件则您可能希望仅在特定时间触发重新启动。 为此,您可以使用“触发文件”,这是一个特殊文件,当您要实际触发重新启动检查时,必须修改它。 更改文件只会触发检查只有在Devtools检测到它必须执行某些操作时才会重新启动。 触发文件可以手动更新也可以通过IDE插件更新。

要使用触发器文件请使用spring.devtools.restart.trigger-file属性。

您可能希望将spring.devtools.restart.trigger-file设置为全局设置,以使所有项目的行为方式相同。

20.2.5 自定义重新启动类加载器

如上面的 Restart vs Reload 部分所述,重新启动功能是通过使用两个类加载器实现的。 对于大多数应用程序,此方法运行良好,但有时可能会导致类加载问题。

默认情况下IDE中的任何打开的项目将使用“重新启动”类加载器加载任何常规.jar文件将使用“base”类加载器加载。 如果您在多模块项目上工作而不是每个模块都导入到IDE中则可能需要自定义事件。 为此您可以创建一个META-INF / spring-devtools.properties文件。

spring-devtools.properties文件可以包含restart.exclude 和 restart.include.prefixed属性。 include元素是应该被拉入“重新启动(restart)”类加载器的项目,排除元素是应该向下推入“基本(base)”类加载器的项目。 属性的值是将应用于类路径的正则表达式模式。

例如:

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

所有属性键必须是唯一的。 只要一个属性从restart.include. 或restart.exclude. 开始,将被考虑。

将加载类路径中的所有META-INF/spring-devtools.properties。 您可以在项目中打包文件,或者在项目所使用的库中打包文件。

20.2.6 已知的限制

重新启动功能对于使用标准ObjectInputStream反序列化的对象无效。 如果需要反序列化数据可能需要使用Spring的ConfigurableObjectInputStream与Thread.currentThread()。getContextClassLoader()组合使用。

不幸的是,几个第三方库在不考虑上下文类加载器的情况下反序列化。 如果您发现这样的问题,您需要向原始作者请求修复。

20.3 LiveReload

spring-boot-devtools模块包括一个嵌入式LiveReload服务器可以在资源更改时用于触发浏览器刷新。 LiveReload浏览器扩展程序可以从 http://livereload.com免费获取ChromeFirefox和Safari的插件。

如果您不想在应用程序运行时启动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

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支持分为两部分 有一个接受连接的服务器端和您在IDE中运行的客户端应用程序。 当spring.devtools.remote.secret属性设置时服务器组件将自动启用。 客户端组件必须手动启动。

20.5.1 运行远程客户端应用程序

远程客户端应用程序旨在从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作为主类。

运行的远程客户端将如下所示:

.   ____          _                                              __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _          ___               _      \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` |        | _ \___ _ __  ___| |_ ___ \ \ \ \
 \\/  ___)| |_)| | | | | || (_| []::::::[]   / -_) '  \/ _ \  _/ -_) ) ) ) )
  '  |____| .__|_| |_|_| |_\__, |        |_|_\___|_|_|_\___/\__\___|/ / / /
 =========|_|==============|___/===================================/_/_/_/
 :: Spring Boot Remote :: 1.5.2.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属性。

20.5.2 远程更新

远程客户端将以与本地相同的方式监视应用程序类路径的更改。 任何更新的资源将被推送到远程应用程序,并且(如果需要的话)触发重新启动。 如果您正在迭代使用您当地没有的云服务的功能,这可能会非常有用。 通常,远程更新和重新启动比完全重建和部署周期要快得多。

仅在远程客户端运行时才监视文件。 如果在启动远程客户端之前更改文件,则不会将其推送到远程服务器。

20.5.3 远程调试隧道

在远程应用程序诊断问题时Java远程调试非常有用。 不幸的是,当您的应用程序部署在数据中心之外时,并不总是能够进行远程调试。 如果您正在使用基于容器的技术如Docker远程调试也可能难以设置。

为了帮助解决这些限制devtools支持基于HTTP隧道的传输远程调试传输。 远程客户端在端口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=NNNN 选项传递给-Xrunjdwp。 如果省略Java将随机选择一个的空闲端口。

通过网络调试远程服务可能很慢您可能需要在IDE中增加超时时间。 例如在Eclipse中您可以从Preferences...中选择Java→Debug 并将Debugger timeout (ms)更改为更合适的值大多数情况下60000可以正常工作

当使用IntelliJ IDEA的远程调试隧道时必须将所有调试断点配置为挂起线程而不是挂起VM。 默认情况下IntelliJ IDEA中的断点会挂起整个VM而不是仅挂起触发断点的线程。 这会导致挂起管理远程调试通道的线程等不必要的副作用,导致调试会话冻结。 当使用IntelliJ IDEA的远程调试隧道时应将所有断点配置为挂起线程而不是VM。 有关详细信息,请参阅IDEA-165769