3.8 开发者工具

优质
小牛编辑
142浏览
2023-12-01

Spring Boot包含一组额外的工具,可以使应用程序开发体验更加愉快。 spring-boot-devtools模块可以包含在任何项目中,以提供额外的开发时间功能。 要包含devtools支持,请将模块依赖项添加到您的构建中,如以下Maven和Gradle列表中所示:

<dependencies>
	<dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-devtools</artifactId>
		<optional>true</optional>
	</dependency>
</dependencies>
configurations {
	developmentOnly
	runtimeClasspath {
		extendsFrom developmentOnly
	}
}
dependencies {
	developmentOnly("org.springframework.boot:spring-boot-devtools")
}

运行完全打包的应用程序时会自动禁用开发人员工具。 如果您的应用程序是从java -jar启动的,或者它是从特殊的类加载器启动的,那么它将被视为“生产应用程序”。 将依赖项标记为Maven中的可选项或在Gradle中使用自定义“开发”配置(如上所示)是防止devtools传递应用于使用项目的其他模块的最佳实践。

重新打包的归档默认情况下不包含devtools。 如果要使用某个远程devtools功能,则需要禁用excludeDevtoolsbuild属性以包含它。 该属性由Maven和Gradle插件支持。

3.8.1 默认属性

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

虽然缓存在生产中非常有用,但在开发过程中可能会适得其反,使您无法看到刚刚在应用程序中进行的更改。 因此,spring-boot-devtools默认禁用缓存选项。

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

因为在开发Spring MVC和Spring WebFlux应用程序时需要有关Web请求的更多信息,所以开发人员工具将为Web日志记录组启用DEBUG日志记录。 这将为您提供有关传入请求,处理程序正在处理它,响应结果等的信息。如果您希望记录所有请求详细信息(包括可能的敏感信息),您可以打开spring.http.log-request-details配置属性。

如果您不希望应用属性默认值,则可以在application.properties中将spring.devtools.add-properties设置为false。

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

3.8.2 自动重启

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

触发重启 由于DevTools监视类路径资源,因此触发重新启动的唯一方法是更新类路径。导致更新类路径的方式取决于您使用的IDE。在Eclipse中,保存修改后的文件会导致更新类路径并触发重新启动。 在IntelliJ IDEA中,构建项目(Build - > Build Project)具有相同的效果。

只要启用了forking,您也可以使用受支持的构建插件(Maven和Gradle)启动应用程序,因为DevTools需要一个独立的应用程序类加载器才能正常运行。 默认情况下,Gradle和Maven在类路径上检测到DevTools时会这样做

与LiveReload一起使用时,自动重启非常有效。 有关详细信息,请参阅LiveReload部分。 如果使用JRebel,则禁用自动重新启动以支持动态类重新加载。 其他devtools功能(例如LiveReload和属性覆盖)仍然可以使用。

DevTools依赖于应用程序上下文的关闭钩子来在重启期间关闭它。 如果禁用了关闭挂钩(SpringApplication.setRegisterShutdownHook(false)),它将无法正常工作。

当决定类路径上的条目是否应该在更改时触发重新启动时,DevTools会自动忽略名为spring-boot,spring-boot-devtools,spring-boot-autoconfigure,spring-boot-actuator和spring-boot-starter的项目。

DevTools需要自定义ApplicationContext使用的ResourceLoader。 如果您的应用程序已经提供了一个,它将被包装。 不支持在ApplicationContext上直接覆盖getResource方法。

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

如果您发现重新启动对应用程序来说不够快,或者遇到类加载问题,您可以考虑重新加载JRebelfrom ZeroTurnaround等技术。 这些工作通过在加载类时重写类以使它们更适合重新加载。

3.8.2.1 记录条件评估中的更改

默认情况下,每次应用程序重新启动时,都会记录一个显示条件评估增量的报告。 该报告显示了在进行更改(例如添加或删除Bean以及设置配置属性)时应用程序自动配置的更改。

要禁用报告的日志记录,请设置以下属性:

spring.devtools.restart.log-condition-evaluation-delta=false

3.8.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属性。

3.8.2.3 观察其他路径

当您对不在类路径中的文件进行更改时,您可能希望重新启动或重新加载应用程序。 为此,请使用spring.devtools.restart.additional-paths属性配置其他路径以监视更改。 您可以使用前面描述的spring.devtools.restart.exclude属性来控制其他路径下的更改是触发完全重新启动还是实时重新加载。

3.8.2.4 禁用重启

如果需要完全禁用重新启动支持(例如,因为它不能与特定库一起使用),则需要在调用SpringApplication.ru(...)之前将spring.devtools.restart.enabled System属性设置为false,如下例所示:

public static void main(String[] args) {
	System.setProperty("spring.devtools.restart.enabled", "false");
	SpringApplication.run(MyApp.class, args);
}

3.8.2.5 使用触发器文件

如果使用不断编译已更改文件的IDE,则可能更喜欢仅在特定时间触发重新启动。 为此,您可以使用“触发器文件”,这是一个特殊文件,当您想要实际触发重新启动检查时,必须对其进行修改。 更改文件只会触发检查,只有在Devtools检测到必须执行某些操作时才会重新启动。 触发器文件可以手动更新,也可以使用IDE插件更新。

要使用触发器文件,请将spring.devtools.restart.trigger-file属性设置为触发器文件的路径。

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

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

如前面在Restart vs Reload部分中所述,使用两个类加载器实现了重启功能。 对于大多数应用程序,这种方法很有效。 但是,它有时会导致类加载问题。

默认情况下,IDE中的任何打开项目都使用“restart”类加载器加载,并且任何常规.jar文件都使用“base”类加载器加载。 如果您处理多模块项目,并且并非每个模块都导入到IDE中,则可能需要自定义内容。 为此,您可以创建META-INF/spring-devtools.properties文件。

spring-devtools.properties文件可以包含以restart.exclude和restart.include为前缀的属性。 include元素是应该被提取到“restart”类加载器中的项,而exclude元素是应该被下推到“base”类加载器中的项。 属性的值是应用于类路径的正则表达式模式,如以下示例所示:

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

所有属性键必须是唯一的。 只要属性以restart.include开头即可。 或者restart.exclude。 已经被考虑了。

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

3.8.2.7 已知限制

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

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

3.8.3 LiveReload

spring-boot-devtools模块包含一个嵌入式LiveReload服务器,可用于在更改资源时触发浏览器刷新。 LiveReload浏览器扩展程序可从livereload.com免费用于Chrome,Firefox和Safari。

您一次只能运行一个LiveReload服务器。 在启动应用程序之前,请确保没有其他LiveReload服务器正在运行。 如果从IDE启动多个应用程序,则只有第一个具有LiveReload支持。<

3.8.4 全局设置

您可以通过将名为.spring-boot-devtools.properties的文件添加到$ HOME文件夹来配置全局devtools设置(请注意,文件名以“.”开头)。 添加到此文件的任何属性都适用于计算机上使用devtools的所有Spring Boot应用程序。 例如,要将restart配置为始终使用触发器文件,您将添加以下属性:

~/.spring-boot-devtools.properties. 
spring.devtools.reload.trigger-file=.reloadtrigger

在.spring-boot-devtools.properties中激活的配置文件不会影响特定于配置文件的配置文件的加载。

3.8.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属性时,将自动启用服务器组件。 必须手动启动客户端组件。

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

远程客户端应用程序旨在从IDE中运行。 您需要运行org.springframework.boot.devtools.RemoteSpringApplication,其类路径与您连接的远程项目相同。 应用程序的单个必需参数是它连接的远程URL。

例如,如果您使用的是Eclipse或STS,并且已经部署到Cloud Foundry的项目名为my-app,那么您将执行以下操作:

正在运行的远程客户端可能类似于以下列表:

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

3.8.5.2 远程更新

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

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