赞
踩
目录
6. 使用 @SpringBootApplication 注解
8.3.6. 自定义重启类加载器(Restart Classloader)
强烈建议你选择一个支持依赖管理的构建系统,并且它可以从 “Maven Central” 拉取依赖。我们建议你选择Maven或Gradle。选择其他构建系统(例如Ant),也不是不行,但它们的支持并不特别好。
Spring Boot的每个版本都提供了一个它所支持的依赖的列表。 在实践中,你不需要在构建配置中为这些依赖声明版本,因为Spring Boot会帮你管理这些。 当你升级Spring Boot本身时,这些依赖也会一同升级。
你仍然可以指定某个依赖的版本,来覆盖spring boot默认的版本。
这份精心策划依赖清单包含了所有可以在Spring Boot中使用的Spring模块,以及一份第三方库的列表。该列表以依赖( spring-boot-dependencies )的形式提供,可在Maven和Gradle中使用。
Spring Boot的每个版本都与Spring框架的基本版本有关。 我们 强烈建议 你不要修改Spring的版本。
Maven就是是专门为Java项目打造的管理和构建工具,它的主要功能有:
一个使用Maven管理的普通的Java项目,它的目录结构默认如下:
- a-maven-project
- ├── pom.xml
- ├── src
- │ ├── main
- │ │ ├── java
- │ │ └── resources
- │ └── test
- │ ├── java
- │ └── resources
- └── target
项目的根目录a-maven-project
是项目名,它有一个项目描述文件pom.xml
,存放Java源码的目录是src/main/java
,存放资源文件的目录是src/main/resources
,存放测试源码的目录是src/test/java
,存放测试资源的目录是src/test/resources
,最后,所有编译、打包生成的文件都放在target
目录里。这些就是一个Maven项目的标准目录结构。
所有的目录结构都是约定好的标准结构,我们千万不要随意修改目录结构。使用标准结构不需要做任何配置,Maven就可以正常使用。
Starter是一系列开箱即用的依赖,你可以在你的应用程序中导入它们。 通过你Starter,可以获得所有你需要的Spring和相关技术的一站式服务,免去了需要到处大量复制粘贴依赖的烦恼。 例如,如果你想开始使用Spring和JPA进行数据库访问,那么可以直接在你的项目中导入 spring-boot-starter-data-jpa 依赖。
Starter含了很多你需要的依赖,以使项目快速启动和运行,并拥有一套一致的、受支持的可管理的过渡性依赖。
关于Starter的命名
所有官方的Starter都遵循一个类似的命名模式;spring-boot-starter-*,其中 * 是一个特定类型的应用程序。 这种命名结构是为了在你需要寻找Starter时提供帮助。 许多IDE中集成的Maven可以让你按名称搜索依赖。 例如,如果安装了相应的Eclipse或Spring Tools插件,你可以在POM编辑器中按下 ctrl-space ,然后输入 “spring-boot-starter” 来获取完整的列表。
正如 “创建你自己的 Starter” 一节所解释的,第三方启动器不应该以 spring-boot 开头,因为它是留给Spring Boot官方组件的。 相反,第三方启动器通常以项目的名称开始。 例如,一个名为 thirdpartyproject 的第三方启动器项目通常被命名为 thirdpartyproject-spring-boot-starter。
以下是Spring Boot在 org.springframework.boot 这个 groupId 下提供的starter组件。
Table 1. Spring Boot 应用 starter | |
Name | Description |
spring-boot-starter | Core starter, including auto-configuration support, logging and YAML |
spring-boot-starter-activemq | Starter for JMS messaging using Apache ActiveMQ |
spring-boot-starter-amqp | Starter for using Spring AMQP and Rabbit MQ |
spring-boot-starter-aop | Starter for aspect-oriented programming with Spring AOP and AspectJ |
spring-boot-starter-artemis | Starter for JMS messaging using Apache Artemis |
spring-boot-starter-batch | Starter for using Spring Batch |
spring-boot-starter-cache | Starter for using Spring Framework’s caching support |
spring-boot-starter-data-cassandra | Starter for using Cassandra distributed database and Spring Data Cassandra |
spring-boot-starter-data-cassandra-reactive | Starter for using Cassandra distributed database and Spring Data Cassandra Reactive |
spring-boot-starter-data-couchbase | Starter for using Couchbase document-oriented database and Spring Data Couchbase |
spring-boot-starter-data-couchbase-reactive | Starter for using Couchbase document-oriented database and Spring Data Couchbase Reactive |
spring-boot-starter-data-elasticsearch | Starter for using Elasticsearch search and analytics engine and Spring Data Elasticsearch |
spring-boot-starter-data-jdbc | Starter for using Spring Data JDBC |
spring-boot-starter-data-jpa | Starter for using Spring Data JPA with Hibernate |
spring-boot-starter-data-ldap | Starter for using Spring Data LDAP |
spring-boot-starter-data-mongodb | Starter for using MongoDB document-oriented database and Spring Data MongoDB |
spring-boot-starter-data-mongodb-reactive | Starter for using MongoDB document-oriented database and Spring Data MongoDB Reactive |
spring-boot-starter-data-neo4j | Starter for using Neo4j graph database and Spring Data Neo4j |
spring-boot-starter-data-r2dbc | Starter for using Spring Data R2DBC |
spring-boot-starter-data-redis | Starter for using Redis key-value data store with Spring Data Redis and the Lettuce client |
spring-boot-starter-data-redis-reactive | Starter for using Redis key-value data store with Spring Data Redis reactive and the Lettuce client |
spring-boot-starter-data-rest | Starter for exposing Spring Data repositories over REST using Spring Data REST and Spring MVC |
spring-boot-starter-freemarker | Starter for building MVC web applications using FreeMarker views |
spring-boot-starter-graphql | Starter for building GraphQL applications with Spring GraphQL |
spring-boot-starter-groovy-templates | Starter for building MVC web applications using Groovy Templates views |
spring-boot-starter-hateoas | Starter for building hypermedia-based RESTful web application with Spring MVC and Spring HATEOAS |
spring-boot-starter-integration | Starter for using Spring Integration |
spring-boot-starter-jdbc | Starter for using JDBC with the HikariCP connection pool |
spring-boot-starter-jersey | Starter for building RESTful web applications using JAX-RS and Jersey. An alternative to spring-boot-starter-web |
spring-boot-starter-jooq | Starter for using jOOQ to access SQL databases with JDBC. An alternative to spring-boot-starter-data-jpa or spring-boot-starter-jdbc |
spring-boot-starter-json | Starter for reading and writing json |
spring-boot-starter-mail | Starter for using Java Mail and Spring Framework’s email sending support |
spring-boot-starter-mustache | Starter for building web applications using Mustache views |
spring-boot-starter-oauth2-authorization-server | Starter for using Spring Authorization Server features |
spring-boot-starter-oauth2-client | Starter for using Spring Security’s OAuth2/OpenID Connect client features |
spring-boot-starter-oauth2-resource-server | Starter for using Spring Security’s OAuth2 resource server features |
spring-boot-starter-quartz | Starter for using the Quartz scheduler |
spring-boot-starter-rsocket | Starter for building RSocket clients and servers |
spring-boot-starter-security | Starter for using Spring Security |
spring-boot-starter-test | Starter for testing Spring Boot applications with libraries including JUnit Jupiter, Hamcrest and Mockito |
spring-boot-starter-thymeleaf | Starter for building MVC web applications using Thymeleaf views |
spring-boot-starter-validation | Starter for using Java Bean Validation with Hibernate Validator |
spring-boot-starter-web | Starter for building web, including RESTful, applications using Spring MVC. Uses Tomcat as the default embedded container |
spring-boot-starter-web-services | Starter for using Spring Web Services |
spring-boot-starter-webflux | Starter for building WebFlux applications using Spring Framework’s Reactive Web support |
spring-boot-starter-websocket | Starter for building WebSocket applications using Spring Framework’s MVC WebSocket support |
除了应用starter外,以下启动器可用于添加 生产就绪 功能。
Table 2. Spring Boot 生产(环境) starter | |
Name | Description |
spring-boot-starter-actuator | Starter for using Spring Boot’s Actuator which provides production ready features to help you monitor and manage your application |
最后,Spring Boot还包括以下starter,如果你想排除或更换特定的技术实现,那么可以使用它们。
Table 3. Spring Boot 技术(实现) starter | |
Name | Description |
spring-boot-starter-jetty | Starter for using Jetty as the embedded servlet container. An alternative to spring-boot-starter-tomcat |
spring-boot-starter-log4j2 | Starter for using Log4j2 for logging. An alternative to spring-boot-starter-logging |
spring-boot-starter-logging | Starter for logging using Logback. Default logging starter |
spring-boot-starter-reactor-netty | Starter for using Reactor Netty as the embedded reactive HTTP server. |
spring-boot-starter-tomcat | Starter for using Tomcat as the embedded servlet container. Default servlet container starter used by spring-boot-starter-web |
spring-boot-starter-undertow | Starter for using Undertow as the embedded servlet container. An alternative to spring-boot-starter-tomcat |
Spring Boot对代码的布局,没有特别的要求。 但是,有一些最佳实践。
当一个类不包括 package 的声明时,它被认为是在 “default package” 中。 通常应避免使 “default package”。 对于使用了 @ComponentScan, @ConfigurationPropertiesScan, @EntityScan 或者 @SpringBootApplication 注解的Spring Boot应用程序来说,它可能会造成一个问题:项目中的所有jar里面的所有class都会被读取(扫描)。
我们建议你遵循Java推荐的包的命名惯例,使用域名反转作为包名(例如, com.example.project)。
我们通常建议你将你启动类放在一个根package中,高于其他的类,@SpringBootApplication 注解一般都是注解在启动类上的。它默认会扫描当前类下的所有子包。例如,如果你正在编写一个JPA应用程序,你的 @Entity 类只有定义在启动类的子包下才能被扫描加载到。这样的好处也显而易见,@SpringBootApplication 默认只会扫描加载你项目工程中的组件。
如果你不想使用 @SpringBootApplication ,它所导入的 @EnableAutoConfiguration 和 @ComponentScan 注解定义了该行为,所以你也可以使用这些来代替。
一个项目典型的布局如下。
- com
- +- example
- +- myapplication
- +- MyApplication.java
- |
- +- customer
- | +- Customer.java
- | +- CustomerController.java
- | +- CustomerService.java
- | +- CustomerRepository.java
- |
- +- order
- +- Order.java
- +- OrderController.java
- +- OrderService.java
- +- OrderRepository.java
MyApplication.java 文件声明了 main 方法,以及标识了基本的 @SpringBootApplication 注解,如下所示。
Java
- @SpringBootApplication
- public class MyApplication {
-
- public static void main(String[] args) {
- SpringApplication.run(MyApplication.class, args);
- }
-
- }
Spring Boot倾向于通过Java代码来进行配置的定义。 虽然也可以使用XML来配置 SpringApplication ,但还是建议你通过 @Configuration 类来进行配置。 通常,可以把启动类是作为主要的 @Configuration 类。
网上有很多关于“通过XML配置Spring”的示例,如果可以的话,还是尽量使用Java代码的方式来实现相同的配置。你可以尝试着搜索 Enable* 注解。
你不需要把所有的 @Configuration 放在一个类中。 @Import 注解可以用来导入额外的配置类。 另外,你可以使用 @ComponentScan 来自动扫描加载所有Spring组件,包括 @Configuration 类。
如果你确实需要使用基于XML的配置,我们建议你仍然从 @Configuration 类开始,然后通过 @ImportResource 注解来加载XML配置文件。
Spring Boot的自动装配机制会试图根据你所添加的依赖来自动配置你的Spring应用程序。 例如,如果你添加了 HSQLDB 依赖,而且你没有手动配置任何DataSource Bean,那么Spring Boot就会自动配置内存数据库。
你需要将 @EnableAutoConfiguration 或 @SpringBootApplication 注解添加到你的 @Configuration 类中,从而开启自动配置功能。
你应该只添加一个 @SpringBootApplication 或 @EnableAutoConfiguration 注解。 建议添加到主要的 @Configuration 类上。
自动配置是非侵入性的。 在任何时候,你都可以开始定义你自己的配置来取代自动配置的特定部分。 例如,如果你添加了你自己的 DataSource bean,默认的嵌入式数据库支持就会“退步”从而让你的自定义配置生效。
如果你想知道在应用中使用了哪些自动配置,你可以在启动命令后添加 --debug 参数。 这个参数会为核心的logger开启debug级别的日志,会在控制台输出自动装配项目以及触发自动装配的条件。
如果你想禁用掉项目中某些自动装配类,你可以在 @SpringBootApplication 注解的 exclude 属性中指定,如下例所示。
Java
- @SpringBootApplication(exclude = { DataSourceAutoConfiguration.class })
- public class MyApplication {
-
- }
如果要禁用的自动装配类不在classpath上(没有导入),那么你可以在注解的 excludeName 属性中指定类的全路径名称。 exclude 和 excludeName 属性在 @EnableAutoConfiguration 中也可以使用。 最后,你也可以在配置文件中通过 spring.autoconfigure.exclude[] 配置来定义要禁用的自动配置类列表。
你可以同时使用注解 + 配置的方式来禁用自动装配类。
自动配置类一般都是 public 的,除了这个类的名称以外(用来禁用它)的任何东西,例如它的方法和属性,包括嵌套的配置类。都不建议你去使用。 |
你可以使用任何标准的Spring技术来定义你的Bean以及依赖注入关系。 推荐使用构造函数注入,并使用 @ComponentScan 注解来扫描Bean。
如果你按照上面的建议构造你的代码(将你的启动类定位在顶级包中),你可以在启动类添加 @ComponentScan 注解,也不需要定义它任何参数, 你的所有应用组件(@Component、@Service、@Repository、@Controller 和其他)都会自动注册为Spring Bean。
也可以直接使用 @SpringBootApplication 注解(该注解已经包含了 @ComponentScan)。
下面的例子展示了一个 @Service Bean,它使用构造器注入的方式注入了 RiskAssessor Bean。
Java
- @Service
- public class MyAccountService implements AccountService {
-
- private final RiskAssessor riskAssessor;
-
- public MyAccountService(RiskAssessor riskAssessor) {
- this.riskAssessor = riskAssessor;
- }
-
- // ...
-
- }
如果一个Bean有多个构造函数,你需要用 @Autowired 注解来告诉Spring该用哪个构造函数进行注入。
Java
- @Service
- public class MyAccountService implements AccountService {
-
- private final RiskAssessor riskAssessor;
-
- private final PrintStream out;
-
- @Autowired
- public MyAccountService(RiskAssessor riskAssessor) {
- this.riskAssessor = riskAssessor;
- this.out = System.out;
- }
-
- public MyAccountService(RiskAssessor riskAssessor, PrintStream out) {
- this.riskAssessor = riskAssessor;
- this.out = out;
- }
-
- // ...
-
- }
上面示例中通过构造器注入的 riskAssessor 字段被标识为了 final,表示一旦Bean创建这个字段就不被改变了。这也是我们推荐的做法。 |
许多Spring Boot开发者希望他们的应用程序能够使用自动配置、组件扫描,并且能够在他们的 "application class "上定义额外的配置。 一个 @SpringBootApplication 注解就可以用来启用这三个功能,如下。
Java
- // Same as @SpringBootConfiguration @EnableAutoConfiguration @ComponentScan
- @SpringBootApplication
- public class MyApplication {
-
- public static void main(String[] args) {
- SpringApplication.run(MyApplication.class, args);
- }
-
- }
@SpringBootApplication 也提供了属性别名来定制 @EnableAutoConfiguration 和 @ComponentScan 中的属性。 |
这些功能都不是强制必须的,你可以随时只使用其中任意功能的注解。 例如,你不需要在你的应用程序中使用组件扫描或配置属性扫描。 Java 在这个例子中,MyApplication 和其他Spring Boot应用程序一样,只是不能自动检测到 @Component 和 @ConfigurationProperties 注解的类,而是明确导入用户定义的Bean(见 @Import)。 |
把应用打包成可执行jar,并且使用嵌入式HTTP服务器的最大优势,就是可以像其他程序一样运行应用。
该样本适用于调试Spring Boot应用程序。 你不需要任何特殊的IDE插件或扩展。
本节只涉及基本的jar打包。 如果你选择将你的应用程序打包成war文件,请参阅你所使用的Server和IDE的文档。 |
你可以在IDE中像运行普通Java程序一样运行你的Spring Boot应用。 不过,你首先需要导入你的项目。 不同的IDE导入方式可能不同, 大多数IDE可以直接导入Maven项目。 例如,Eclipse用户可以从 File 菜单中选择 Import… → Existing Maven Projects 。
如果你不能直接将项目导入IDE,你可以通过构建插件来生成IDE的元数据。包括用于 Eclipse 和 IDEA 的 Maven 插件。Gradle为各种 IDE 都提供了插件。
如果你不小心把一个Web应用程序运行了两次,你会看到 “Port already in use” 这个异常提示。 Spring Tools用户可以使用 Relaunch 按钮而不是 Run 按钮来实现“重启”(如果程序已经在运行,那么会先关闭它再启动)。 |
如果你使用Spring Boot的Maven或Gradle插件来创建可执行jar,你可以使用 java -jar 来运行你的打包后应用程序,如下例所示。
$ java -jar target/myapplication-0.0.1-SNAPSHOT.jar
打包后的jar程序,也支持通过命令行参数开启远程调试服务,如下。
- $ java -Xdebug -Xrunjdwp:server=y,transport=dt_socket,address=8000,suspend=n \
- -jar target/myapplication-0.0.1-SNAPSHOT.jar
Spring Boot Maven 插件包括一个 run 目标(goal),可用于快速编译和运行你的应用程序。 应用程序以 exploded 的形式运行,就像在IDE中一样。 运行Spring Boot应用的Maven命令如下。
$ mvn spring-boot:run
如果项目的构建需要消耗很大的内存,你可以考虑使用 MAVEN_OPTS 环境变量来修改最大内存,参考如下。
$ export MAVEN_OPTS=-Xmx1024m
Spring Boot Gradle插件还包括一个 bootRun 任务,可以用来以 exploded 的形式运行你的应用程序。 只要你应用了了 org.springframework.boot 和 java 插件,就会添加 bootRun 任务,如下例所示。
$ gradle bootRun
同上,如果Gradle构建项目出现内存不足,可以通过 JAVA_OPTS 环境变量来增加JVM的内存。
$ export JAVA_OPTS=-Xmx1024m
由于Spring Boot应用程序是普通的Java应用程序,JVM的热替换功能可以直接使用。但是,JVM的热替换能替换的字节码有限。要想获得更完整的解决方案,可以使用 JRebel 。
spring-boot-devtools 模块提供了快速重启应用程序的支持。详情请见 热部署 “How-to”
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 {
- developmentOnly("org.springframework.boot:spring-boot-devtools")
- }
Devtools可能会导致类加载相关的一些问题,特别是在多模块项目中。“ 诊断类加载问题” 解释了如何诊断和解决这些问题。 |
如果你的应用程序是通过 java -jar 启动的,或者是从一个特殊的classloader启动的,那么它就被认为是一个 "生产级别的应用程序",开发者工具会被自动禁用。 你可以通过 spring.devtools.restart.enabled 配置属性来控制这一行为。 要启用devtools,无论用于启动应用程序的类加载器是什么,请设置启动参数 -Dspring.devtools.restart.enabled=true 。 在生产环境中不能这样做,因为运行devtools会有安全风险。 要禁用devtools,请删除该依赖或者设置启动参数 -Dspring.devtools.restart.enabled=false。 |
应该在Maven中把这个依赖的scope标记为 optional,或在Gradle中使用 developmentOnly 配置(如上所示)。以防止使用你的项目的其他模块,传递地依赖了devtools。 |
重新打包的压缩文件默认不包含devtools。如果你想使用某个远程devtool功能,,你需要包含它。使用Maven插件时,将 excludeDevtools 属性设为false。使用Gradle插件时, 配置任务的classpath,使其包括 developmentOnly 配置。 |
如 重启 Vs 重载 一节所述,重启功能是通过使用两个classloader实现的。 对于大多数应用程序来说,这种方法效果很好。 然而,它有时会导致类加载问题,特别是在多模块项目中。
为了诊断类加载问题是否确实是由devtools和它的两个类加载器引起的,请试着禁用 restart。如果这能解决你的问题,请定制 restart 类加载器 以包括你的整个项目。
在Spring Boot支持的一些库中,会使用缓存来提高性能。例如,模板引擎会缓存已编译的模板,以避免重复解析模板文件。另外,Spring MVC可以在响应静态资源时往响应中添加HTTP缓存头。
虽然缓存在生产中是非常有益的,但在开发过程中可能会产生反作用,使你无法看到你在应用程序中刚做的改动。 由于这个原因,spring-boot-devtools 默认禁用了缓存选项。
缓存的选项通常是通过 application.properties 文件中的属性来配置的。 例如,Thymeleaf提供了 spring.thymeleaf.cache[] 属性。 与其需要手动设置这些属性,spring-boot-devtools 模块会在开发场景下合理的设置这些属性。
下表列出了所有被设置的属性。
Name | Default Value |
server.error.include-binding-errors | always |
server.error.include-message | always |
server.error.include-stacktrace | always |
server.servlet.jsp.init-parameters.development | true |
server.servlet.session.persistent | true |
spring.docker.compose.readiness.wait | only-if-started |
spring.freemarker.cache | false |
spring.graphql.graphiql.enabled | true |
spring.groovy.template.cache | false |
spring.h2.console.enabled | true |
spring.mustache.servlet.cache | false |
spring.mvc.log-resolved-exception | true |
spring.reactor.netty.shutdown-quiet-period | 0s |
spring.template.provider.cache | false |
spring.thymeleaf.cache | false |
spring.web.resources.cache.period | 0 |
spring.web.resources.chain.cache | false |
如果你不希望设置属性的默认值,你可以在你的 application.properties 中把 spring.devtools.add-properties[] 设置为 false。 |
在开发Spring MVC和Spring WebFlux应用程序时,你可能需要更多关于Web请求的信息,开发者工具建议你为Web日志组启用DEBUG日志。这将给你提供关于客户端的请求信息,哪个handler正在处理它,响应结果,以及其他细节。如果你希望记录所有的请求细节(包括潜在的敏感信息),你可以打开 spring.mvc.log-request-details[] 或 spring.codec.log-request-details[] 配置。
使用spring-boot-devtools的应用程序会在classpath上的文件发生变化时自动重启。当在IDE中工作时,这可能是一个有用的功能,因为它为代码变化提供了一个非常快速的反馈。默认情况下,classpath上任何指向目录的条目都会被监测到变化。注意,某些资源,如静态资源和视图模板发生变化时,不需要重启应用程序。
触发重启
由于DevTools监控classpath资源,触发重启的唯一方法是更新classpath。 无论你使用的是IDE还是构建插件,被修改的文件都必须被重新编译以触发重启。 导致更新classpath的方式取决于你所使用的工具。
如果你用Maven或Gradle的构建插件重启,你必须将 forking 设置为 enabled。 如果你禁用 forking,devtools使用的“应用隔离类加载器(isolated application classloader)”将不会被创建,重启功能将无法正常运行。 |
与LiveReload一起使用时,自动重启的效果非常好。 详见 LiveReload 部分。 如果你使用JRebel,自动重启被禁用,而采用动态类重载。 其他devtools特性(如LiveReload和属性覆盖)仍然可以使用。 |
DevTools依靠应用程序上下文的关机hook来在重启期间关闭它。 如果你禁用了关机钩子( SpringApplication.setRegisterShutdownHook(false) ),它就不能正确工作。 |
DevTools需要定制 ApplicationContext 所使用的 ResourceLoader。 如果你的应用程序已经提供了一个,它将被“包装”(装饰者设计模式)起来。 不支持直接覆盖 ApplicationContext 上的 getResource 方法。 |
在使用AspectJ 切面时,不支持自动重启。 |
重启 vs 重载
Spring Boot通过两个类加载器实现了重启。 不变的类(例如,来自第三方jar的类)被加载到一个 base classloader。 你正在开发的类被加载到 restart classloader中。 当应用程序被重新启动时, restart classloader 被丢弃,并被创建一个新的。 这种方法意味着应用程序的重启通常比 “冷启动” 快得多,因为 base classloader 已经可用并被填充。
如果你发现重启对你的应用程序来说不够快,或者你遇到了类加载相关的问题,你可以考虑重载技术,如ZeroTurnaround的 JRebel。这些技术的工作原理是在类被加载时对其进行重写,使其更容易被重载。
默认情况下,每次你的应用程序重新启动时,都会记录一份显示条件评估delta的报告。 该报告显示了你的应用程序的自动配置的变化,因为你做了一些改变,如添加或删除Bean和设置配置属性。
要禁用报告的记录,请设置以下属性。
Properties
Yaml
spring.devtools.restart.log-condition-evaluation-delta=false
某些资源在被改变时不一定需要触发重启。例如,Thymeleaf模板可以就地编辑。默认情况下,改变 /META-INF/maven, /META-INF/resources, /resources, /static, /public, /templates 中的资源不会触发重启,但会触发实时重载.。如果你想自定义这些排除项,可以使用 spring.devtools.restart.exclude 属性。例如,要只排除 /static 和 /public ,你可以设置以下属性。
Properties
Yaml
spring.devtools.restart.exclude=static/**,public/**
如果你想保留这些默认值并增加额外的排除资源,请使用 spring.devtools.restart.extra-exclude 属性来代替。 |
当你对不在classpath上的文件进行修改时,你可能希望你的应用程序被重新启动或重新加载。为此,使用 spring.devtools.restart.extra-paths 属性来配置监控变化的额外路径。你可以使用前面说过的的 spring.devtools.restart.exclude 属性来控制额外路径下的变化是触发完全重启还是实时重载。
如果你不想使用重启功能,你可以通过使用 spring.devtools.restart.enabled 属性来禁用它。在大多数情况下,你可以在你的 application.properties 中设置这个属性(这样做仍然会初始化restart 类加载器,但它不会监控文件变化)。
如果你需要完全禁用重启支持(例如,因为它不能与特定的库一起工作),你需要在调用 SpringApplication.run(…) 之前将 spring.devtools.restart.enabled 属性设置为 false ,如下面的例子中所示。
Java
- @SpringBootApplication
- public class MyApplication {
-
- public static void main(String[] args) {
- System.setProperty("spring.devtools.restart.enabled", "false");
- SpringApplication.run(MyApplication.class, args);
- }
-
- }
如果你只想在在特定时间触发重启,你可以使用 “trigger file”,这是一个特殊的文件,当你想实际触发重启检查时,那你就对这个文件进行修改。
对文件的任何更新都会触发检查,但只有当Devtools检测到它有改动发生时,才会实际重新启动。 |
通过属性 spring.devtools.restart.trigger-file 设置trigger file 文件的名称(不包括任何路径)。 trigger file必须在classpath路径上。
例如,如果你有一个结构如下的项目。
- src
- +- main
- +- resources
- +- .reloadtrigger
那么你的 “trigger-file” 属性应该设置为如下。
Yaml
- spring:
- devtools:
- restart:
- trigger-file: ".reloadtrigger"
现在只有当 src/main/resources/.reloadtrigger 被更新时才会重新启动。
你可能想把 spring.devtools.restart.trigger-file 设置为全局设置,这样你的所有项目都会以同样的方式行事。 |
有些IDE有一些功能,使你不需要手动更新你的触发器文件。 Spring Tools for Eclipse 和 IntelliJ IDEA (Ultimate Edition))都有这种支持。对于Spring Tools,你可以使用控制台视图中的 “reload” 按钮(需要把你的 trigger-file 命名为 .reloadtrigger)。对于IntelliJ IDEA,你可以按照其文档中的说明进行操作。
正如前面在"Restart vs Reload"所描述的,重启功能是通过使用两个classloader实现的。如果这导致了其他的问题,你可能需要自定义类加载器。
默认情况下,你的IDE中任何打开的项目都是用 “restart” 类加载器加载的,而任何常规的 .jar 文件都是用 “base” 类加载器加载。 如果你使用 mvn spring-boot:run 或 gradle bootRun 也是一样:包含了 @SpringBootApplication 的项目用 “restart” 类加载器加载,其他都用 “base” 类加载器。
你可以通过创建 META-INF/spring-devtools.properties 文件来指定Spring Boot用不同的类加载器来加载你的项目的不同部分。 spring-devtools.properties 文件可以包含以 restart.exclude 和 restart.include 开头的属性。 include 元素是应该被“拉”到 “restart” 类加载器中的项目,而 exclude 元素是应该被“推”到 “base” 类加载器中的项目。 该属性的值是一个基于classpath的正则表达式,如以下例子所示。
Yaml
- restart:
- exclude:
- companycommonlibs: "/mycorp-common-[\\w\\d-\\.]+\\.jar"
- include:
- projectcommon: "/mycorp-myproj-[\\w\\d-\\.]+\\.jar"
所有的key必须是唯一的。只要一个属性以 restart.include. 或 restart.exclude. 开头,就会被考虑进去。 |
所有在classpath的 META-INF/spring-devtools.properties 都会被加载。 你可以把它打包到你的项目中,或者打包进你项目依赖的项目中。 |
如果你使用标准的 ObjectInputStream 来反序列化对象,那么重启功能的效果可能并不好。 如果你需要反序列化数据,你可能需要使用到Spring的 ConfigurableObjectInputStream 与 Thread.currentThread().getContextClassLoader()。
不幸的是,一些第三方库在反序列化时没有考虑到上下文的类加载器。 如果你发现这样的问题,你需要向原作者请求修复。
spring-boot-devtools 模块包括一个内嵌的LiveReload服务器,可以用来在资源发生变化时触发浏览器刷新。LiveReload浏览器扩展可以从 livereload.com免费获得,支持Chrome、Firefox和Safari。
如果你不想在应用程序运行时启动LiveReload服务器,你可以将 spring.devtools.livereload.enabled 属性设置为 false 。
你一次只能运行一个LiveReload服务器。 在启动你的应用程序之前,确保没有其他LiveReload服务器正在运行。 如果你从你的IDE启动多个应用程序,只有第一个有LiveReload支持。 |
为了在文件变化时触发LiveReload,必须启用 “自动重启”。 |
你可以通过在 $HOME/.config/spring-boot 目录下添加以下任何文件来配置全局的devtools设置。
添加到这些文件中的任何属性都适用于你机器上使用devtools的 所有 Spring Boot应用程序。 例如,如果要将重启配置为总是使用trigger file,你可以在 spring-boot-devtools 文件中添加以下属性。
Yaml
- spring:
- devtools:
- restart:
- trigger-file: ".reloadtrigger"
默认情况下,$HOME 是用户的主目录。 要自定义这个位置,请设置 SPRING_DEVTOOLS_HOME 环境变量或 spring.devtools.home 系统属性。
如果在 $HOME/.config/spring-boot 中找不到devtools配置文件,则会在 $HOME 目录的根部搜索是否有 .spring-boot-devtools.properties 文件。 这允许你与那些不支持 $HOME/.config/spring-boot 位置的旧版Spring Boot的应用程序共享devtools全局配置。 |
devtools properties/yaml文件中不支持Profiles。 任何在 .spring-boot-devtools.properties 中激活的Profiles都不会影响指定配置文件的加载。不支持在YAML和Properties文件中配置Profiles(形式为 spring-boot-devtools-<profile>.properties )和 spring.config.activate.on-profile。 |
FileSystemWatcher 的工作方式是以一定的时间间隔轮询类的变化,然后等待一个预定义的安静期,以确保不再有变化。 由于Spring Boot完全依赖IDE来编译并将文件复制到Spring Boot可以读取的位置,你可能会发现有时devtools重新启动应用程序时,某些变化并没有反映出来(没有立即生效)。 如果你经常观察到这样的问题,可以尝试增加 spring.devtools.restart.poll-interval 和 spring.devtools.restart.quiet-period 参数到适合你开发环境的值。
Yaml
- spring:
- devtools:
- restart:
- poll-interval: "2s"
- quiet-period: "1s"
受监控的classpath目录现在每2秒轮询一次变化,并保持1秒的安静期以确保没有额外的类变化。
Spring Boot的开发者工具并不局限于本地开发。 你也可以在远程运行应用程序时使用一些功能。 远程支持是可选的,因为启用它可能会有安全风险。 只有在受信任的网络上运行时,或在用SSL保护时,才应启用它。 如果这两个选项对你来说都不可用,你就不应该使用DevTools的远程支持。 你更不应该在生产环境中启用它。
要启用它,你需要确保 devtools 包含在重新打包的归档文件(jar)中,如以下所示。
- <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 属性。 就像任何重要的密码或密钥一样,这个值应该是唯一的和足够强大的,以至于它不能被猜到或被暴力破解。
Remote devtools support is provided in two parts: a server-side endpoint that accepts connections and a client application that you run in your IDE. The server component is automatically enabled when the spring.devtools.remote.secret property is set. The client component must be launched manually.
远程devtools支持由两部分组成:一个接受连接的服务器端端点和一个你在IDE中运行的客户端应用程序。 当 spring.devtools.remote.secret 属性被设置时,服务器组件会自动启用。 客户端组件必须手动启动。
Spring WebFlux应用程序不支持远程devtools。 |
远程客户端应用程序被设计成可以在你的IDE中运行。 你需要运行 org.springframework.boot.devtools.RemoteSpringApplication ,其classpath与你所连接的远程项目相同。 该应用程序的唯一必要参数是它所连接的远程URL。
例如,如果你使用的是 Eclipse 或 Spring Tools,并且你有一个名为 my-app 的项目,并已将其部署到 Cloud Foundry,你可以执行以下操作。
一个正在运行的远程客户端可能类似于如下。
- . ____ _ __ _ _
- /\\ / ___'_ __ _ _(_)_ __ __ _ ___ _ \ \ \ \
- ( ( )\___ | '_ | '_| | '_ \/ _` | | _ \___ _ __ ___| |_ ___ \ \ \ \
- \\/ ___)| |_)| | | | | || (_| []::::::[] / -_) ' \/ _ \ _/ -_) ) ) ) )
- ' |____| .__|_| |_|_| |_\__, | |_|_\___|_|_|_\___/\__\___|/ / / /
- =========|_|==============|___/===================================/_/_/_/
- :: Spring Boot Remote :: (v3.2.0-SNAPSHOT)
-
- 2023-06-26T13:23:55.928+08:00 INFO 12660 --- [ main] o.s.b.devtools.RemoteSpringApplication : Starting RemoteSpringApplication v3.2.0-SNAPSHOT using Java 17 with PID 12660 (/Users/myuser/.m2/repository/org/springframework/boot/spring-boot-devtools/3.2.0-SNAPSHOT/spring-boot-devtools-3.2.0-SNAPSHOT.jar started by myuser in /opt/apps/)
- 2023-06-26T13:23:55.935+08:00 INFO 12660 --- [ main] o.s.b.devtools.RemoteSpringApplication : No active profile set, falling back to 1 default profile: "default"
- 2023-06-26T13:23:56.300+08:00 INFO 12660 --- [ main] o.s.b.d.a.OptionalLiveReloadServer : LiveReload server is running on port 35729
- 2023-06-26T13:23:56.333+08:00 INFO 12660 --- [ main] o.s.b.devtools.RemoteSpringApplication : Started RemoteSpringApplication in 0.978 seconds (process running for 1.753)
因为远程客户端使用的是与真实应用程序相同的classpath,它可以直接读取应用程序属性。 spring.devtools.remote.secret 属性就是这样被读取并传递给服务器进行验证的。 |
始终建议使用 https:// 作为连接协议,这样流量会被加密,密码也不会被截获。 |
如果你需要使用代理来访问远程应用程序,可以配置 spring.devtools.remote.proxy.host 和 spring.devtools.remote.proxy.port 属性。 |
远程客户端以与本地 restart相同的方式监控你的应用程序classpath的变化。任何更新的资源都会被推送到远程应用程序,并(如果需要)触发重启。如果你在一个云服务上进行功能迭代,而你在本地没有云服务,这可能会很有帮助。一般来说,远程更新和重启要比完整的重建和部署周期快得多。
在一个较慢的开发环境中,可能会发生“等待时间”不够的情况,类的变化可能被分成几批。 在第一批类的变化被上传后,服务器被重新启动。 下一批则不能被发送到应用程序,因为服务器正在重启。
这通常表现为 RemoteSpringApplication 日志中的警告,即未能上传一些类,并随之重试。 但它也可能导致应用程序代码不一致,以及在第一批修改上传后无法重新启动。 如果你经常观察到这样的问题,可以尝试增加 spring.devtools.restart.poll-interval 和 spring.devtools.restart.quiet-period 参数到适合你开发环境的值。 参见"配置文件系统监听器"一节,以配置这些属性。
文件只在远程客户端运行时被监控。 如果你在启动远程客户端之前改变了一个文件,它不会被推送到远程服务器上。 |
可执行jar可以用于生产环境,由于它们是独立的,非常适合部署到云服务中。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。