使用Spring boot开发
本节将更详细地介绍您应该如何使用Spring Boot。它涵盖了构建系统、自动配置以及如何运行应用程序等主题。我们还介绍了一些Spring Boot的最佳实践。虽然Spring Boot没有什么特别之处(它只是您可以使用的另一个库),但有一些建议,当遵循时,会使您的开发过程变得更容易一些。
1构建系统
强烈建议您选择一个支持依赖项管理的构建系统,并可以使用发布到“Maven Central”存储库的工件。我们建议您选择Maven或Gradle。可以将Spring Boot与其他构建系统(例如Ant)配合使用,但它们没有得到特别好的支持。
1.1依赖管理
Spring Boot的每个版本都提供了它支持的依赖项的精选列表。在实践中,您无需在构建配置中为任何这些依赖项提供版本,因为Spring Boot会为您管理它。当您升级Spring Boot本身时,这些依赖项也会以一致的方式升级。
注意
如果需要,您仍然可以指定版本并覆盖Spring Boot的建议。
精选列表包含了所有可以与Spring Boot一起使用的Spring模块,以及精炼的第三方库列表。该列表作为标准材料清单(spring-boot-dependencies)提供,可以与Maven和Gradle一起使用。
警告
Spring Boot的每个版本都与Spring Framework的基本版本相关联。我们强烈建议您不要指定其版本。
1.2 maven
要了解如何将Spring Boot与Maven一起使用,请参阅Spring Boot的Maven插件的文档:
网址: https:// docs.spring.io/spring-b oot/docs/3.0.6/maven-plugin/reference/htmlsingle/
1.3 Gradle
要了解如何将Spring Boot与Gradle一起使用,请参阅Spring Boot的Gradle插件的文档:
网址: https:// docs.spring.io/spring-b oot/docs/3.0.6/gradle-plugin/reference/htmlsingle/
1.4 Ant
可以使用Apache Ant+Ivy构建Spring Boot项目。spring-boot-antlib“AntLib”模块也可用于帮助Ant创建可执行jar。
要声明依赖项,典型的ivy.xml文件如下所示
<ivy-module version="2.0">
<info organisation="org.springframework.boot" module="spring-boot-sample-ant" />
<configurations>
<conf name="compile" description="everything needed to compile this module" />
<conf name="runtime" extends="compile" description="everything needed to run this module" />
</configurations>
<dependencies>
<dependency org="org.springframework.boot" name="spring-boot-starter"
rev="${spring-boot.version}" conf="compile" />
</dependencies>
</ivy-module>
典型的build.xml看起来像以下示例:
<project
xmlns:ivy="antlib:org.apache.ivy.ant"
xmlns:spring-boot="antlib:org.springframework.boot.ant"
name="myapp" default="build">
<property name="spring-boot.version" value="3.1.0" />
<target name="resolve" description="--> retrieve dependencies with ivy">
<ivy:retrieve pattern="lib/[conf]/[artifact]-[type]-[revision].[ext]" />
</target>
<target name="classpaths" depends="resolve">
<path id="compile.classpath">
<fileset dir="lib/compile" includes="*.jar" />
</path>
</target>
<target name="init" depends="classpaths">
<mkdir dir="build/classes" />
</target>
<target name="compile" depends="init" description="compile">
<javac srcdir="src/main/java" destdir="build/classes" classpathref="compile.classpath" />
</target>
<target name="build" depends="compile">
<spring-boot:exejar destfile="build/myapp.jar" classes="build/classes">
<spring-boot:lib>
<fileset dir="lib/runtime" />
</spring-boot:lib>
</spring-boot:exejar>
</target>
</project>
如果您不想使用spring-boot-antlib模块,请参阅不使用spring-boot-antlib“how to”即可从Ant构建可执行存档。
1.5 Starters
Starters是一组方便的依赖描述符,您可以将其包含在应用程序中。您可以获得您需要的所有Spring和相关技术的一站式商店,而无需搜索示例代码和复制粘贴大量的依赖描述符。例如,如果您想开始使用Spring和JPA进行数据库访问,请在项目中包含spring-boot-starter-data-jpa依赖项。
Starters包含许多您需要的依赖项,可快速启动和运行项目,并具有一致、受支持的一组可管理的可传递的依赖项。
名字里有什么
所有官方Starters都遵循类似的命名模式;spring-boot-starter-*,其中*是特定类型的应用程序。当您需要找到Starters时,此命名结构旨在提供帮助。许多IDE中的Maven集成允许您按名称搜索依赖项。例如,安装了相称的Eclipse或Spring Tools插件后,您可以在POM编辑器中按ctrl-space,然后键入“spring-boot-starter”以获取完整列表。
正如“创建自己的Starters”部分所解释的,第三方Starters不应以spring-boot开头,因为它是为官方的Spring Boot保留的。相反,第三方Starters通常以项目名称开头。例如,名为thirdpartyproject的第三方Starters项目通常被命名为thirdpartyproject-spring-boot-starter。
以下应用程序Starters是由Spring Boot在org.springframework.boot组下提供的:
名称 | 描述 |
spring-boot-starter | 核心启动器,包括自动配置支持、日志记录和YAML |
spring-boot-starter-activemq | 使用Apache ActiveMQ进行JMS消息 |
spring-boot-starter-amqp | 使用Spring AMQP和Rabbit MQ |
spring-boot-starter-aop | 使用Spring AOP和AspectJ进行面向方面编程 |
spring-boot-starter-artemis | 使用Apache Artemis的JMS消息 |
spring-boot-starter-batch | 使用Spring Batch |
spring-boot-starter-cache | 使用Spring Framework缓存支持 |
spring-boot-starter-data-cassandra | 使用Cassandra 分布式数据库and Spring Data Cassandra |
spring-boot-starter-data-cassandra-reactive | 使用 Cassandra 分布式数据库和 Spring Data Cassandra Reactive |
spring-boot-starter-data-couchbase | 使用Couchbase和Spring Data Couchbase |
spring-boot-starter-data-couchbase-reactive | 使用Couchbase和Spring Data Couchbase Reactive |
spring-boot-starter-data-elasticsearch | 使用Elasticsearch搜索和分析引擎以及Spring Data Elasticsearch |
spring-boot-starter-data-jdbc | 使用Spring Data JDBC |
spring-boot-starter-data-jpa | 使用Spring Data JPA 与Hibernate |
spring-boot-starter-data-ldap | 使用Spring Data LDAP |
spring-boot-starter-data-mongodb | 使用MongoDB和Spring Data MongoDB |
spring-boot-starter-data-mongodb-reactive | 使用MongoDB和Spring Data MongoDB Reactive |
spring-boot-starter-data-neo4j | 使用Neo4j和Spring Data Neo4j |
spring-boot-starter-data-r2dbc | 使用Spring Data R2DBC |
spring-boot-starter-data-redis | 使用Redis和Spring Data Redis 以及Lettuce 客户端 |
spring-boot-starter-data-redis-reactive | 使用Redis和Spring Data Redis reactive以及Lettuce 客户端 |
spring-boot-starter-data-rest | 用于使用Spring Data REST通过REST公开Spring Data存储库 |
spring-boot-starter-freemarker | 使用FreeMarker视图构建MVC web应用程序 |
spring-boot-starter-graphql | 使用Spring GraphQL构建GraphQL应用 |
spring-boot-starter-groovy-templates | 使用Groovy模板视图构建MVC web应用程序 |
spring-boot-starter-hateoas | 用Spring MVC和Spring HATEOS构建基于超媒体的RESTful web应用程序 |
spring-boot-starter-integration | 使用Spring Integration |
spring-boot-starter-jdbc | 将JDBC与HikariCP连接池一起使用 |
spring-boot-starter-jersey | 使用JAX-RS和Jersey构建RESTful web应用程序。spring-boot-starter-web的替代方案 |
spring-boot-starter-jooq | 使用jOOQ通过JDBC访问SQL数据库。spring-boot-starter-data-jpa或spring-boot-starter-jdbc的替代方案 |
spring-boot-starter-json | 读写JSON |
spring-boot-starter-mail | 使用Java Mail和Spring Framework的电子邮件发送支持 |
spring-boot-starter-mustache | 使用Mustache视图构建web应用程序 |
spring-boot-starter-oauth2-authorization-server | 使用Spring授权服务器特性 |
spring-boot-starter-oauth2-client | 使用Spring Security的OAuth2/OpenID 连接客户端功能 |
spring-boot-starter-oauth2-resource-server | 使用Spring Security的OAuth2资源服务器功能 |
spring-boot-starter-quartz | 使用Quartz |
spring-boot-starter-rsocket | 构建RSocket客户端和服务器 |
spring-boot-starter-security | 使用Spring Security |
spring-boot-starter-test | 使用JUnit Jupiter、Hamcrest和Mockito等库测试Spring Boot应用程序 |
spring-boot-starter-thymeleaf | 使用Thymelaf视图构建MVC web应用程序 |
spring-boot-starter-validation | 使用Hibernate Validator进行JavaBean验证 |
spring-boot-starter-web | 使用Spring MVC构建web,包括RESTful应用程序。使用Tomcat作为默认的嵌入式容器 |
spring-boot-starter-web-services | 使用Spring Web Services |
spring-boot-starter-webflux | 使用Spring Framework的Reactive Web支持构建WebFlux应用程序 |
spring-boot-starter-websocket | 使用Spring Framework的MVC WebSocket支持构建WebSocket应用程序 |
除了应用程序Starters外,还可以使用以下Starters,他们也具备生产准备就绪功能:
名称 | 描述 |
spring-boot-starter-actuator | 用于使用Spring Boot Actuator的启动器,该启动器提供可用于生产的功能,帮助您监控和管理应用程序 |
最后,Spring Boot还包括以下Starters,如果您想排除或切换特定的技术,可以使用这些Starters:
名称 | 描述 |
spring-boot-starter-jetty | 用于使用Jetty作为嵌入式servlet容器的Starter。spring-boot-starter-tomcat的替代品 |
spring-boot-starter-log4j2 | 用于使用Log4j2进行日志记录的启动器。spring-boot-starter-logging的替代品 |
spring-boot-starter-logging | 使用Logback进行日志记录的Starter。默认日志记录启动器。 |
spring-boot-starter-reactor-netty | 用于使用Reactor Netty作为嵌入式响应式HTTP服务器的启动器 |
spring-boot-starter-tomcat | 使用Tomcat作为嵌入式servlet容器的启动器。spring-boot-starter-web使用的默认servlet容器启动器 |
spring-boot-starter-undertow | 用于使用Undertow作为嵌入式servlet容器的启动器。spring-boot-starter-tomcat的替代品 |
要了解切换技术这方面内容,请参阅切换Web服务器和日志系统的操作方法文档。
有关其他社区贡献的Starters列表,请参阅GitHub上spring-boot-starters模块中的README文件。
2结构化您的代码
Spring Boot不需要任何特定的代码布局即可工作。然而,有一些最佳做法会有所帮助。
2.1使用“默认”软件包
当一个类不包含软件包声明时,它被认为是在“默认软件包”中。通常不鼓励使用“默认软件包”,并应避免使用。它可能会给使用@ComponentScan、@ConfigurationPropertiesScan、@EntityScan或@SpringBootApplication注释的Spring Boot应用程序造成特殊问题,因为每个jar中的每个类都会被读取。
提示
我们建议您遵循Java推荐的软件包命名约定,并使用反向域名(例如,com.example.project)。
2.2定位主应用程序类
我们通常建议您将主应用程序类放在其他类之上的根包中。@SpringBootApplication注解通常放置在您的主类上,它隐式地为某些项定义了基础“搜索包”。例如,如果您正在编写JPA应用程序,则使用@SpringBootApplication注解类的包被用来搜索@Entity项目。使用根包还允许组件扫描仅应用于您的项目。
提示
如果您不想使用@SpringBootApplication,也可以使用@EnableAutoConfiguration和@ComponentScan,@SpringBootApplication导入了他们。
以下列表显示了典型的布局:
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,如下所示:
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class MyApplication {
public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
}
3 Configuration类
Spring Boot倾向于基于Java的配置。虽然可以将SpringApplication与XML源一起使用,但我们通常建议您的主要源是单个@Configuration类。通常,定义main方法的类是一个很好的候选者,作为主要的@Configuration。
提示
许多使用XML配置的Spring配置示例已在互联网上发布。如果可能的话,请始终尝试使用等效的基于Java的配置。搜索Enable*注解可以是一个很好的起点。
3.1导入其他配置类
您不必将所有@Configuration放入一个类中。@Import注解可用于导入其他配置类。或者,您可以使用@ComponentScan自动选择所有Spring组件,包括@Configuration类。
3.2导入XML配置
如果您必须使用基于XML的配置,我们建议您仍然从@Configuration类开始。然后,您可以使用@ImportResource注解来加载XML配置文件。
4自动配置
Spring Boot自动配置尝试根据您添加的jar依赖项自动配置您的Spring应用程序。例如,如果HSQLDB在您的类路径上,并且您没有手动配置任何数据库连接bean,那么Spring Boot会自动配置内存数据库。
您需要通过将@EnableAutoConfiguration或@SpringBootApplication注解添加到您的@Configuration类之一来选择加入自动配置。
提示
您应该只添加一个@SpringBootApplication或@EnableAutoConfiguration注解。我们通常建议您仅将一个或另一个添加到您的主@Configuration类中。
4.1逐步更换自动配置
自动配置是非侵入性的。在任何时候,您都可以开始定义自己的配置,以替换自动配置的特定部分。例如,如果您添加自己的DataSource bean,默认的嵌入式数据库支持将退出。
如果您需要了解当前正在应用的自动配置,以及原因,请使用--debug开关启动应用程序。这样做可以为选择核心记录器而调试日志,并将条件报告记录到控制台。
4.2禁用特定的自动配置类
如果您发现您不想要的特定自动配置类正被应用,您可以使用@SpringBootApplication的排除属性来禁用它们,如以下示例所示:
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
@SpringBootApplication(exclude = { DataSourceAutoConfiguration.class })
public class MyApplication {
}
如果类不在类路径上,您可以使用注解的excludeName属性,并指定完全限定的名称。如果您更喜欢使用@EnableAutoConfiguration而不是@SpringBootApplication,也可以使用exclude和excludeName。最后,您还可以使用spring.autoconfigure.exclude属性控制要排除的自动配置类列表。
提示
您可以在注解级别和使用属性定义排除项。
注意
尽管自动配置类是public,但被视为公共API的类的唯一方面是可用于禁用自动配置的类的名称。这些类的实际内容,如嵌套配置类或bean方法,仅供内部使用,我们不建议直接使用。
5 Spring Beans和依赖注入
您可以自由使用任何标准的Spring Framework技术来定义您的bean及其注入的依赖关系。我们通常建议使用构造函数注入来连接依赖项,并使用@ComponentScan来查找bean。
如果您按照上述建议构建代码(将启动类放在顶级包中),则可以在没有任何参数的情况下添加@ComponentScan,或者使用隐式包含@ComponentScan的@SpringBootApplication注解。您的所有应用程序组件(@Component、@Service、@Repository、@Controller等)都会自动注册为Spring Beans。
以下示例显示了@Service Bean,它使用构造函数注入来获得所需的RiskAssessor Bean:
import org.springframework.stereotype.Service;
@Service
public class MyAccountService implements AccountService {
private final RiskAssessor riskAssessor;
public MyAccountService(RiskAssessor riskAssessor) {
this.riskAssessor = riskAssessor;
// ...
}
如果一个bean有多个构造函数,您需要标记您希望Spring与@Autowired一起使用的构造函数:
import java.io.PrintStream;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@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字段,表明随后它不能被更改。
6使用@SpringBootApplication注解
许多Spring Boot开发人员喜欢使用自动配置、组件扫描,并能够在他们的“application 类”上定义额外的配置。单个@SpringBootApplication注解可用于启用这三个功能,即:
- @EnableAutoConfiguration:启用Spring Boot的自动配置机制。
- @ComponentScan:在应用程序所在的软件包上启用@Component扫描(请参阅最佳实践)
- @SpringBootConfiguration:启用上下文中额外bean注册或导入其他配置类。Spring标准@Configuration的替代品,有助于在集成测试中进行配置检测。
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
// Same as @SpringBootConfiguration @EnableAutoConfiguration @ComponentScan
@SpringBootApplication
public class MyApplication {
public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
}
注意
@SpringBootApplication还提供了别名来自定义@EnableAutoConfiguration和@ComponentScan的属性。
注意
这些功能都不是强制性的,您可以选择用它启用的任何功能替换此单个注解。例如,您可能不想在应用程序中使用组件扫描或配置属性扫描:
import org.springframework.boot.SpringApplication;
import org.springframework.boot.SpringBootConfiguration;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.Import;
@SpringBootConfiguration(proxyBeanMethods = false)
@EnableAutoConfiguration
@Import({ SomeConfiguration.class, AnotherConfiguration.class })
public class MyApplication {
public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
}
在本例中,MyApplication就像任何其他Spring Boot应用程序一样,只是不会自动检测到@Component注解类和@ConfigurationProperties注解类,并且显式导入用户定义的bean(请参阅@Import)。
7运行您的应用程序
将应用程序打包为jar并使用嵌入式HTTP服务器的最大优势之一是,您可以像运行任何其他应用程序一样运行应用程序。该示例适用于调试Spring Boot应用程序。您不需要任何特殊的IDE插件或扩展。
注意
本节仅涵盖基于jar打包。
7.1从IDE运行
您可以在IDE中像运行Java应用程序一样运行Spring Boot应用程序。但是,您首先需要导入您的项目。导入步骤因您的IDE和构建系统而异。大多数IDE可以直接导入Maven项目。例如,Eclipse用户可以从File菜单中选择Import… → Existing Maven Projects
如果您无法将项目直接导入IDE,则可以使用构建插件生成IDE元数据。Maven包括了Eclipse和IDEA的插件。Gradle为各种IDE提供插件。
提示
如果您不小心运行了两次Web应用程序,您会看到“端口已在使用”错误。Spring Tools用户可以使用重新启动按钮而不是运行按钮,以确保关闭任何现有实例。
7.2运行打包后的应用程序
如果您使用Spring Boot Maven或Gradle插件创建可执行jar,则可以使用java -jar运行应用程序,如以下示例所示:
$ java -jar target/myapplication-0.0.1-SNAPSHOT.jar
也可以在启用远程调试支持的情况下运行打包的应用程序。这样做可以让您将调试器附加到打包的应用程序中,如以下示例所示:
$ java -Xdebug -Xrunjdwp:server=y,transport=dt_socket,address=8000,suspend=n \
-jar target/myapplication-0.0.1-SNAPSHOT.jar
7.3使用Maven插件
Spring Boot Maven插件包括一个运行目标,可用于快速编译和运行您的应用程序。应用程序以爆炸形式运行,就像它们在您的IDE中一样。以下示例显示了运行Spring Boot应用程序的典型Maven命令:
$ mvn spring-boot:run
您可能还想使用MAVEN_OPTS操作系统环境变量,如以下示例所示:
$ export MAVEN_OPTS=-Xmx1024m
7.4使用Gradle插件
Spring Boot Gradle插件还包括一个bootRun任务,可用于以分解的形式运行您的应用程序。每当您应用org.springframework.boot和java插件时,都会添加bootRun任务,并显示在以下示例中:
$ gradle bootRun
您可能还想使用JAVA_OPTS操作系统环境变量,如以下示例所示:
$ export JAVA_OPTS=-Xmx1024m
7.5热替换
由于Spring Boot应用程序是普通的Java应用程序,JVM热替换应该开箱即用。JVM热替换在某种程度上受到它可以替换的字节码的限制。为了获得更完整的解决方案,可以使用JRebel。
Spring-boot-devtools模块还包括对快速应用程序重新启动的支持。有关详细信息,请参阅热替换“操作方法”。
8开发人员工具
Spring Boot包括一套额外的工具,可以使应用程序开发体验更愉快。Spring-boot-devtools模块可以包含在任何项目中,以提供额外的开发期间的特性。要包含devtools支持,请将模块依赖项添加到您的构建中,如Maven和Gradle的以下列表所示:
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启动的,或者从特殊的类加载器启动的,那么它被视为“生产级别的应用程序”。您可以使用spring.devtools.restart.enabled系统属性来控制此行为。要启用devtools,无论用于启动应用程序的类加载器是什么,请设置-Dspring.devtools.restart.enabled=true系统属性。这绝不能在运行devtools存在安全风险的生产环境中进行。要禁用devtools,请排除依赖项或设置-Dspring.devtools.restart.enabled=false系统属性。
提示
在Maven中将依赖项标记为可选或在Gradle中使用developmentOnly配置(如上图所示)可以防止devtools被传递应用于使用您项目的其他模块。
提示
默认情况下,重新打包的存档不包含开发工具。如果您想使用某些远程开发工具功能,您需要将其包含在内。使用Maven插件时,将 excludeDevtools属性设置为false。使用Gradle插件时,将任务的类路径配置为包含developmentOnly配置。
8.1诊断类加载问题
如“重新启动与重新加载”部分所述(8.3节),重新启动功能通过使用两个类加载器来实现。对于大多数应用程序,这种方法效果很好。然而,它有时会导致类加载问题,特别是在多模块项目中。
要诊断类加载问题是否确实是由devtools及其两个类加载器引起的,请尝试禁用重新启动。如果这解决了您的问题,请自定义重新启动classloader以包含您的整个项目。
8.2属性默认值
Spring Boot支持的几个库使用缓存来提高性能。例如,模板引擎缓存编译的模板,以避免重复解析模板文件。此外,Spring MVC可以在提供静态资源时将HTTP缓存头添加到响应中。
虽然缓存在生产中非常有益,但在开发过程中可能会适得其反,使您无法看到刚刚在应用程序中所做的更改。因此,spring-boot-devtools默认禁用缓存选项。
缓存选项通常通过application.properties文件中的设置进行配置。例如,Thymeleaf提供spring.thymeleaf.cache属性。Spring-boot-devtools模块不需要手动设置这些属性,而是自动应用合理的开发时期配置。
下表列出了应用的所有属性:
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.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日志记录。这将为您提供有关传入请求、正在处理请求的处理程序、响应结果和其他详细信息。如果您希望记录所有请求详细信息(包括潜在的敏感信息),您可以打开spring.mvc.log-request-details或spring.codec.log-request-details配置属性。
8.3自动重启
每当类路径上的文件发生变化时,使用spring-boot-devtools的应用程序都会自动重新启动。在IDE中工作时,这可能是一个有用的功能,因为它为代码更改提供了非常快速的反馈循环。默认情况下,指向目录的类路径上的任何条目都会被监控更改。请注意,某些资源,如静态资源和视图模板,不需要重新启动应用程序。
触发重新启动
当DevTools监控类路径资源时,触发重新启动的唯一方法是更新类路径。无论您使用的是IDE还是构建插件之一,修改后的文件都必须重新编译才能触发重新启动。您导致类路径更新的方式取决于您正在使用的工具:
- 在Eclipse中,保存修改后的文件会导致类路径更新并触发重新启动。
- 在IntelliJ IDEA中,构建项目(Build +→+ Build Project)具有相同的效果。
- 如果使用构建插件,为Maven运行mvn compile或为Gradle运行gradle build将触发重新启动。
注意
如果您使用构建插件Maven或Gradle重新启动,则必须将forking设置为enable。如果您禁用forking,devtools使用的应用程序隔离类加载器将不会被创建,重新启动将无法正常运行。
提示
当与LiveReload一起使用时,自动重新启动效果非常好。有关详细信息,请参阅LiveReload部分。如果您使用JRebel,则禁用自动重新启动,以支持动态类重新加载。其他devtools功能(如LiveReload和属性覆盖)仍然可以使用。
注意
DevTools依靠应用程序上下文的关闭钩子在重新启动期间关闭它。如果您禁用了关机钩子(SpringApplication.setRegisterShutdownHook(false)),则无法正常工作。
注意
DevTools需要自定义ApplicationContext使用的ResourceLoader。如果您的应用程序已经提供了一个,它将被打包。不支持在ApplicationContext上直接覆盖getResource方法。
小心
使用AspectJ时不支持自动重新启动。
重新启动与重新加载
Spring Boot提供的重新启动技术通过使用两个类加载器工作。不变的类(例如,来自第三方jar的类)被加载到基础类加载器( base classloader)中。您正在积极开发的类被加载到重新启动类加载器( restart classloader)中。当应用程序重新启动时,重新启动类加载器( restart classloader)被丢弃,并创建一个新的。这种方法意味着应用程序重新启动通常比“冷启动”快得多,因为基础类加载器( base classloader)已经可用并已填充。
如果您发现重新启动对您的应用程序来说不够快,或者您遇到类加载问题,您可以考虑重载技术,例如ZeroTurnaround的JRebel等技术。他们的工作方式是在加载时重写类,使它们更容易重新加载。
8.3.1记录条件评估中的变化
默认情况下,每次应用程序重新启动时,都会记录一个显示条件评估增量的报告。该报告显示在您进行更改(如添加或删除bean以及设置配置属性)时对应用程序的自动配置所做的更改。
要禁用报告的日志记录,请设置以下属性:
spring:
devtools:
restart:
log-condition-evaluation-delta: false
8.3.2排除资源
某些资源在更改时不一定需要触发重新启动。例如,Thymeleaf 模板可以就地编辑。默认情况下,更改/META-INF/maven、/META-IINF/resources、/resources和/static、/public或/templates中的资源不会触发重新启动,但会触发实时重新加载。如果要自定义排除这些,可以使用spring.devtools.restart.exclude属性。例如,要仅排除/static和/public,您需要设置以下属性:
spring:
devtools:
restart:
exclude: "static/**,public/**"
提示
如果要保留这些默认值并添加其他排除项,请改用spring.devtools.restart.additional-exclude属性。
8.3.3监视其他路径
当您对类路径之外的文件进行更改时,您可能希望重新启动或重新加载应用程序。为此,请使用spring.devtools.restart.additional-paths属性配置其他路径以监视更改。您可以使用前面描述的spring.devtools.restart.exclude属性来控制附加路径下的更改是触发完全重新启动还是实时重新加载。
8.3.4禁用重新启动
如果不想使用重新启动功能,可以使用spring.devtools.restart.enabled属性禁用它。在大多数情况下,您可以在application.properties中设置此属性(这样做仍然会初始化重新启动类加载器,但它不会监视文件更改)。
如果需要完全禁用重新启动支持(例如,因为它不适用于特定的库),则需要调用System类的setProperty方法将属性spring.devtools.restart.enabled设置为false, 如下例所示:
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class MyApplication {
public static void main(String[] args) {
System.setProperty("spring.devtools.restart.enabled", "false");
SpringApplication.run(MyApplication.class, args);
}
8.3.5使用触发器文件
如果您使用的IDE持续编译更改的文件,您可能更喜欢只在特定时间触发重新启动。为此,您可以使用“触发器文件”,这是一个特殊的文件,当您想要实际触发重新启动检查时,必须对其进行修改。
注意
对文件的任何更新都会触发检查,但只有当Devtools检测到有事情要做时,才会真正重新启动。
要使用触发器文件,请将spring.devtools.restart.trigger-file属性设置为触发器文件的名称(不包括任何路径)。触发器文件必须出现在类路径上的某个位置。
例如,如果您有一个具有以下结构的项目:
src
+- main
+- resources
+- .reloadtrigger
那么您的trigger-file属性将是:
spring:
devtools:
restart:
trigger-file: ".reloadtrigger"
现在,只有当src/main/resources/.reloadtrigger更新时,才会重新启动。
提示
您可能希望将spring.devtools.restart.trigger-file设置为全局配置,以便所有项目都以相同的方式运行。
有些IDE具有一些功能,可以使您不需要手动更新触发文件。Spring Tools for Eclipse和IntelliJ IDEA(终极版)都有这样的支持。使用Spring Tools,您可以从控制台视图中使用“reload”按钮(只要您的触发器文件名为.reloadtrigger)。对于IntelliJ IDEA,您可以按照其文档中的说明进行操作。
8.3.6自定义重新启动类加载器
正如前面“重新启动与重新加载”部分所述,重新启动功能是通过使用两个类加载器来实现的。如果这导致了问题,您可能需要自定义由哪个类加载器加载写什么内容。
默认情况下,IDE中任何打开的项目都使用“重新启动”类加载器加载,任何常规.jar文件都使用“基本”类加载器装载。如果您使用mvn-spring-boot:run或gradle-bootRun,情况也是如此:包含@SpringBootApplication的项目使用“重新启动”类加载器加载,其他所有内容使用“基本”类加载器。
您可以通过创建META-INF/Spring-devtools.properties文件,指示Spring Boot使用不同的类加载器加载项目的部分内容。spring-devtools.properties文件可以包含以restart.exclude和restart.include为前缀的属性。include元素是应该被拉到“重新启动”类加载器中,exclude元素是应该被推到“基本”类加载器中。该属性的值是应用于类路径的正则表达式模式,如下示例所示:
restart:
exclude:
companycommonlibs: "/mycorp-common-[\\w\\d-\\.]+\\.jar"
include:
projectcommon: "/mycorp-myproj-[\\w\\d-\\.]+\\.jar"
注意
所有属性键都必须是唯一的。只要一个属性以restart.include.或restart.exclude.开头,它就会被考虑。
提示
所有在类路径中的META-INF/spring-devtools.properties都已加载。您可以将文件打包到项目中,也可以打包到项目使用的库中。
8.3.7已知限制
对于使用标准ObjectInputStream反序列化的对象,重新启动功能无法正常工作。如果需要反序列化数据,则可能需要将Spring的ConfigurationObjectInputStream与Thread.currentThread().getContextClassLoader()结合使用。
不幸的是,一些第三方库在不考虑上下文类加载器的情况下进行反序列化。如果您发现这样的问题,您需要向原始作者请求修复。
8.4 LiveReload
spring-boot-devtools模块包括一个嵌入式LiveReload服务器,可用于在资源更改时触发浏览器刷新。LiveReload浏览器扩展可从 http:// LiveReload.com 免费获得,适用于Chrome、Firefox和Safari。
如果您不想在应用程序运行时启动LiveReload服务器,可以将spring.devtools.LiveReload.enabled属性设置为false。
注意
一次只能运行一台LiveReload服务器。在启动应用程序之前,请确保没有其他LiveReload服务器正在运行。如果您从IDE启动多个应用程序,则只有第一个应用程序支持LiveReload。
警告
若要在文件更改时触发LiveReload,必须启用“自动重新启动”。
8.5全局设置
您可以通过将以下任何文件添加到$HOME/.config/spring-boot目录来配置全局devtools设置:
1. spring-boot-devtools.properties
2. spring-boot-devtools.yaml
3. spring-boot-devtools.yml
添加到这些文件中的任何属性都适用于您机器上使用devtools的所有Spring Boot应用程序。例如,要将重新启动配置为始终使用触发器文件,您需要将以下属性添加到spring-boot-devtools文件中:
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文件中不支持配置文件。
在.spring-boot-devtools.properties中激活的任何配置文件都不会影响特定配置文件的加载。不支持YAML和properties文件中的配置文件特定的文件名(形式为spring-boot-devtools-<profile>.properties)和spring.config.activate.on-profile文档。
8.5.1配置文件系统监视程序
FileSystemWatcher的工作方式是以一定的时间间隔轮询类更改,然后等待预定义的静默期以确保不再有更改。由于Spring Boot完全依赖IDE来编译文件并将其复制到Spring Boot可以读取文件的位置,因此您可能会发现,当devtools重新启动应用程序时,有时某些更改没有得到反映。如果您经常观察到这样的问题,请尝试将spring.devtools.restart.poll-interval和spring.devtools.restart.quiet-period参数增加到适合您的开发环境的值:
spring:
devtools:
restart:
poll-interval: "2s"
quiet-period: "1s"
现在,监视的类路径目录每2秒轮询一次以获取更改,并保持1秒的静默期以确保没有其他类更改。
8.6远程应用程序
Spring Boot开发工具并不局限于本地开发。在远程运行应用程序时,您还可以使用一些功能。远程支持是选择加入的,因为启用它可能会带来安全风险。只有在受信任的网络上运行或使用SSL进行安全保护时,才应启用它。如果这两个选项都不可用,则不应使用DevTools的远程支持。您永远不应该在生产部署上启用该支持。
要启用它,您需要确保重新打包的归档文件中包含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属性。像任何重要的密码或秘钥一样,该值应该是唯一的和强的,这样就不会被猜测或暴力破解。
远程开发工具支持分为两部分:一个是接受连接的服务器端端点,另一个是在IDE中运行的客户端应用程序。当设置spring.devtools.remote.secret属性时,服务器组件将自动启用。客户端组件必须手动启动。
注意
Spring WebFlux应用程序不支持远程开发工具。
8.6.1运行远程客户端应用程序
远程客户端应用程序设计为在IDE中运行。您需要使用与所连接的远程项目相同的类路径来运行org.springframework.boot.devtools.RemoteSpringApplication。该应用程序的唯一必需参数是它所连接到的远程URL。
例如,如果您使用的是Eclipse或Spring Tools,并且您有一个名为my-app的项目已部署到CloudFoundry,那么您将执行以下操作:
- 从Run菜单中选择Run Configurations…。
- 创建一个新的Java应用程序“启动配置”。
- 浏览my-app项目。
- 使用org.springframework.boot.devtools.RemoteSpringApplication作为主类。
- 添加 https:// myapp.cfapps.io 到程序参数(或任何远程URL)。
正在运行的远程客户端可能类似于以下列表:
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ ___ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | | _ \___ _ __ ___| |_ ___ \ \ \ \
\\/ ___)| |_)| | | | | || (_| []::::::[] / -_) ' \/ _ \ _/ -_) ) ) ) )
' |____| .__|_| |_|_| |_\__, | |_|_\___|_|_|_\___/\__\___|/ / / /
=========|_|==============|___/===================================/_/_/_/