0
点赞
收藏
分享

微信扫一扫

6. 使用 Spring Boot进行开发(Developing with Spring Boot)

小编 03-02 18:00 阅读 3

6. 使用 Spring Boot进行开发(Developing with Spring Boot)

本节详细介绍了如何使用Spring Boot。它涵盖考虑构建系统、自动配置以及如何运行应用程序等主题。我们还介绍一些 Spring Boot 最新做法。虽然 Spring Boot 没有什么特别之处(它只是你使用的一个库),它会有一些建议,当您遵循这些建议,可以使您的开发过程更容易一些。

如果您从 Spring Boot 开始,在进入本章节之前,你应该阅读 入门指南

6.1 构建系统(Build Systems)

强烈建议您选择一个 依赖管理 来构建项目,而且可以使用发布到 “Maven Central” 库的组件。我们建议您选择 Maven 或 Gradle。你也可以让 Spring Boot 和其它构建系统(例如Ant)配合使用,但是它们的支持并不完善。

6.1.1 依赖管理(Dependency Management)

Spring Boot 的每个版本都会提供其支持的依赖项列表。实际上,你不需要提供构建配置中依赖项的版本,因为Spring Boot 会为您管理这些依赖项。当您升级 Spring Boot 本身时,这些依赖项也会统一升级。

::: tip 提示
如果需要,您仍然可以指定依赖版本并覆盖 Spring Boot 的设置版本。
:::

列表中包含了所有的 Spring 模块,以及第三方库的详细列表。该列表以标准清单spring-boot-dependencies的形式提供,可以与 Maven 和 Gradle 一起使用。

::: warning 警告

Spring Boot 的每个版本都与 Spring Framework 的集成版本息息相关。我们强烈建议你不要指定它的版本。

:::

6.1.2 Maven

要了解如何将 Spring Boot 与 Maven 结合使用,请参阅 Spring Boot 的 Maven 插件文档:

  • 参考资料 (HTML 和 PDF)
  • API

6.1.3 Gradle

要了解如何将 Spring Boot 与 Gradle 结合使用,请参阅 Spring Boot 的 Gradle 插件文档:

  • 参考资料(HTML 和 PDF)
  • API

6.1.4 Ant

使用 Apache Ant+Ivy 可以构建 Spring Boot 项目。此外,“AntLib” 模块 spring-boot-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="2.7.18-SNAPSHOT"/>

    <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>

::: tip 提示
如果不想使用 spring-boot-antlib 模块,请参阅 Build an Executable Archive From Ant without Using spring-boot-antlib
:::

6.1.5 Starters

场景启动器是一组依赖关系的描述,您可以将其包含在应用程序中。你可以获得所需的全部 Spring 以及相关技术的一站式服务,而无需搜索示例代码和复制粘贴依赖描述符。例如,如果您开始使用 Spring 和 JPA 进行数据库访问,请在项目中包含 spring-boot-starter-data-jpa 依赖。

场景启动器包含大量的依赖项,这些依赖项可以让项目快速启动和运行,并提供一套一致的、受支持的依赖项传递。

::: tip What is in a name

所有官方场景启动器都遵循类型的命名模式; spring-boot-starter-*,其中 * 为特定类型的应用程序。这种命名结构的目的是需要查找场景启动器时提供帮助。许多集成开发环境中的 Maven 都可以让您按名称搜索依赖项。例如,如果安装了相应的 Eclipse 或 Spring 插件,就可以在 POM 编辑器中键入 ctrl-space 键,然后键入“spring-boot-starter”,查看完整列表。

在 “创建自己的场景启动器” 部分所述,第三方启动器不应该以spring-boot开头,因为spring-boot是 Spring Boot 官方库的专属开通。相反,第三方启动器通常以项目名称开通,例如,名为 thirdpartyproject 的第三方启动器通常会命名为thirdpartyproject-spring-boot-starter

:::

以下场景启动器是 Spring Boot 官方提供的,都属于 org.springframework.boot 组:

表 1. Spring Boot 应用程序启动器

NameDescription
spring-boot-starter核心启动器,包括自动配置、日志记录和 YAML
spring-boot-starter-activemq集成 Apache ActiveMQ 的 JMS messaging 启动器
spring-boot-starter-amqp集成 Spring AMQP 和 Rabbit MQ 的启动器
spring-boot-starter-aop集成 Spring AOP 和 AspectJ 进行面向切面编程的启动器
spring-boot-starter-artemis集成 Apache Artemis 的 JMS messaging 启动器
spring-boot-starter-batch集成 Spring Batch 的启动器
spring-boot-starter-cache集成 Spring Framework 缓存支持的启动器
spring-boot-starter-data-cassandra集成 Cassandra 分布式数据库和 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 和 Spring MVC 通过 REST 访问 Spring Data存储库的启动器
spring-boot-starter-freemarker使用 FreeMarker 视图构建 MVC 网络应用程序的启动器
spring-boot-starter-graphql使用 Spring GraphQL 构建 GraphQL 应用程序的启动器
spring-boot-starter-groovy-templates使用 Groovy 模板视图构建 MVC 网络应用程序的启动器
spring-boot-starter-hateoas使用 Spring MVC 和 Spring HATEOAS 构建基于超媒体的 RESTful 网络应用程序的启动器
spring-boot-starter-integration集成 Spring Integration 的启动器
spring-boot-starter-jdbc集成 HikariCP 连接池的JDBC启动器
spring-boot-starter-jersey使用 JAX-RS 和 Jersey 构建 RESTful 网络应用程序的启动器。可以代替 spring-boot-starter-web
spring-boot-starter-jooq使用 jOOQ 通过JDBC 访问 SQL 数据库的启动器。可以代替 spring-boot-starter-data-jpaspring-boot-starter-jdbc
spring-boot-starter-json用于读写 json 的启动器
spring-boot-starter-jta-atomikos使用 Atomikos 进行 JTA 事务的启动器
spring-boot-starter-mail使用 Java Mail 和 Spring Framework 电子邮件支持发送的启动器
spring-boot-starter-mustache使用 Mustache 视图构建网络应用程序的启动器
spring-boot-starter-oauth2-client使用 Spring Security 的 OAuth2/OpenID 连接客户端功能的启动器
spring-boot-starter-oauth2-resource-server使用 Spring Security 的 OAuth2 资源服务功能的启动器
spring-boot-starter-quartz集成 Quartz scheduler 的启动器
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使用 Thymeleaf 视图构建 MVC 应用程序的启动器
spring-boot-starter-validation使用 Hibernate 验证器进行 Java Bean 验证的启动器
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 的 WebSocket 支持构建WebSocket启动器

除应用程序启动器外,还可使用以下启动器添加 production ready 功能:

表 2. Spring Boot 生产环境启动器

NameDescription
spring-boot-starter-actuator使用 Spring Boot 的 Actuator 的启动器,它提供production ready功能,帮助您监控和管理应用程序

最后,Spring Boot 还包括一些用于排除或交换特定技术方向的启动器:

表 3. Spring Boot 技术启动器

NameDescription
spring-boot-starter-jetty使用 Jetty 作为嵌入式 servlet 容器的启动器。可以替代 spring-boot-starter-tomcat
spring-boot-starter-log4j2使用 Log4j2 进行日志记录的启动器。可以替代 spring-boot-starter-logging
spring-boot-starter-logging使用 Logback 进行日志记录的启动器。默认的日志启动器
spring-boot-starter-reactor-netty使用 Reactor Netty 作为嵌入式响应式 HTTP 服务器的启动器
spring-boot-starter-tomcat使用 Tomcat 作为嵌入式 servlet 容器的启动器。使用默认 servlet 容器启动器 spring-boot-starter-web
spring-boot-starter-undertow使用 Undertow 作为嵌入式 servlet 容器的启动器。可以替代 spring-boot-starter-tomcat

要深入了解技术交互方向的知识,请参阅r swapping web server 和 logging system。

::: tip 提示
有关其他社区贡献的启动器列表,请参阅 GitHub 上的spring-boot-starters模块的 README 文件 。
:::

6.2 构建你的代码(Structuring Your Code)

Spring Boot 不需要任何特定的代码结构。然而,也有一些最佳实现是很有帮助的。

6.2.1 使用默认包(Using the “default” Package)

当一个类不包含 package 声明。它通常被认为在一个“默认包”中。一般不建议使用 “默认包” ,应该避免使用。它会给使用 @ComponentScan, @ConfigurationPropertiesScan, @EntityScan@SpringBootApplication 注解的 Spring Boot 应用程序带来很多问题,因为每个 jar 中的每个类都会被读取。

::: tip 提示

我们建议您遵循 Java 推荐的软件包命名约定,并使用相反的域名(例如,com.example.project)。

:::

6.2.2 定位主程序类(Locating the Main Application Class)

我们通常建议将主程序类放到根包中。 @SpringBootApplication 注解 会放在主类上,它隐式地为某些项目定义了一个基础的 “search package” 。例如,如果你正在编写一个 JPA 应用程序,那么使用 @SpringBootApplication 注解的类所在的包将会搜索 @Entity 。使用根包还可以让组件只应用到你的项目。

::: tip 提示

如果你不使用 @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,如下所示:

@SpringBootApplication
public class MyApplication {

    public static void main(String[] args) {
        SpringApplication.run(MyApplication.class, args);
    }

}

6.3 配置类(Configuration Classes)

Spring Boot 偏好基于 Java 的配置。虽然可以将. SpringApplication 和 XML 结合使用,但是我们通常建议您将一个 @Configuration 类作为主要来源。通常,定义的 main 方法的类适合作为主要的 @Configuration

::: tip 提示

在互联网上发布了很多使用XML配置的Spring配置示例,如果可能,请尽量使用基于Java的等效配置。搜索 Enable* 注解是一个很多方法。

:::

6.3.1 导入其它配置类(Importing Additional Configuration Classes)

你不需要把全部的 @Configuration 放在一个类中。 @Import 注解可以用于导入其它配置类。或者,您可以使用 @ComponentScan 主动扫描注入全部的Spring组件,包括 @Configuration

6.3.2 导入XML配置(Importing XML Configuration)

如果您一定要使用基于XML的配置,我们建议您从 @Configuration 类开始。然后,您可以使用 @ImportResource 注解来加载XML配置文件。

6.4 自动配置(Auto-configuration)

Spring Boot 自动配置会尝试根据您添加的jar依赖关系自动配置您的 Spring 应用程序。例如,如果 HSQLDB 在类路径上,而您没有手动配置任何数据库连接nean,则 Spring Boot 会自动配置内存数据库。

你需要在其中一个 @Configuration 类中添加@EnableAutoConfiguration@SpringBootApplication 注解,从而添加自动配置功能

::: tip 提示

你只能添加一个 @SpringBootApplication@EnableAutoConfiguration 注解。我们通常建议你只在主要的 @Configuration 添加其中一个组件。

:::

6.4.1 逐步取代自动配置(Gradually Replacing Auto-configuration)

自动配置是非侵入性的。在任何时候,你都可以开始定义自己的配置,用来取代自动配置的特定部分。例如,如果您添加了自己的 DataSource bean,默认嵌入式数据库不在进行支持。

个你需要了解当前应用的自动配置及其原因,请使用 --debug 开关启动应用程序。这样做可以为选定的核心日志记录器启用debug日志,并将报告记录到控制台。

6.4.2 禁用特定的自动配置类(Disabling Specific Auto-configuration Classes)

如果你发现当前应用中您不需要的特定自动配置类,你可以使用 @SpringBootApplication 的exclude属性来禁用它们,如下所示:

@SpringBootApplication(exclude = { DataSourceAutoConfiguration.class })
public class MyApplication {

}

如果类不在classpath上,可以使用注解的 excludeName 属性来指定全限定类名。如果你更倾向于使用 @EnableAutoConfiguration 而不是 @SpringBootApplication,也可以使用excludeexcludeName,最后,你可以使用 spring.autoconfigure.exclude 属性来控制需要排除的自动配置类列表。

::: tip 提示

您可以在注解级别的和使用属性来定义排除项。

:::

::: tip 提示

尽管自动配置类是 public,但是该类唯一被认为公共API的部分是类名,该名称可用于禁用自动配置。这些类的实际内容(比如嵌套配置类或bean方法)仅供内部使用,我们不建议直接使用这些。

:::

6.4.3 自动配置包路径(Auto-configuration Packages)

自动配置包路径是各种自动配置功能扫描实体和Spring Data repositories默认查找的包路径。 @EnableAutoConfiguration 注解(或者直接通过@SpringBootApplication)来决定默认的自动配置包路径。可以使用@AutoConfigurationPackage注解配置其它软件包路径。

6.5 Spring Beans 和依赖注入(Spring Beans and Dependency Injection)

你可以自由使用任何标准的 Spring Framework 技术来定义您的 bean 及其注入的依赖项。我们通常建议使用构造器注入的方式来进行依赖注入,并使用 @ComponentScan 来查找Bean。

如果你按照上面的建议(将主程序类放到顶级包中)修改代码架构,你就可以添加 @ComponentScan (无需任何参数)或者使用 @SpringBootApplication (包含前者)。所有的应用程序组件(@Component, @Service, @Repository, @Controller等)都会自动注入成 Spring Bean。

下面的示例显示了一个使用构造器注入获取所需 RiskAssessor Bean 的 @Service Bean:

@Service
public class MyAccountService implements AccountService {

    private final RiskAssessor riskAssessor;

    public MyAccountService(RiskAssessor riskAssessor) {
        this.riskAssessor = riskAssessor;
    }

    // ...

}

如果一个Bean有多个构造函数,则需要用 @Autowired来标记您希望Spring使用的构造函数:

@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;
    }

    // ...

}

::: tip 提示

请注意,使用构造器注入可以将 riskAssessor 字段标记为 final 字段,表示以后不能更改。

:::

6.6 使用@SpringBootApplication注解(Using the @SpringBootApplication Annotation)

许多 Spring Boot 开发人员都希望自己的应用程序能够使用自动配置、组件扫描,并能在 "application class"定义额外的配置。只需要使用 @SpringBootApplication 注解就可以启用这三个功能,即:

  • @EnableAutoConfiguration:启用 Spring Boot 的自动配置机制
  • @ComponentScan:在应用程序所在包路径上启动 @Component 扫描 (参阅 the best practices)
  • @SpringBootConfiguration:启用在上下文中注册额外的 Bean 或导入额外的配置类。她是Spring标准 @Configuration 的替代品,有助于集成测试红的 configuration detection 。
// Same as @SpringBootConfiguration @EnableAutoConfiguration @ComponentScan
@SpringBootApplication
public class MyApplication {

    public static void main(String[] args) {
        SpringApplication.run(MyApplication.class, args);
    }

}

::: tip 提示

@SpringBootApplication 提供了别名来自定义 @EnableAutoConfiguration@ComponentScan 的属性。

:::

::: tip 提示

这些功能都不是强制性的,你可以选择用它所启用的任何功能来替代这个单一注解。例如,您可能不想在应用程序中使用组件扫描或配置属性扫描:

@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-annotated 类和 @ConfigurationProperties-annotated 类不会被自动扫描到,而用户定义Bean的会被显式导入 (参阅 @Import)。

:::

6.7 运行应用程序(Running Your Application)

将应用程序打包成jar并使用嵌入式HTTP服务器是最大优势之一,您可以像运行其它服务器一样运行应用程序。调试Spring Boot应用程序也很容易。您不需要任何特殊的IDE插件或扩展。

::: tip 备注

本章节仅涉及打包成jar文件。如果您选择将应用程序打包成war文件吗,请参阅服务器和IDE文档。

:::

6.7.1 使用IDE运行(Running From an IDE)

您可以将 Spring Boot 应用程序作为一个 Java 应用程序在IDE中运行。然而,您首先需要导入您的项目。导入步骤因IDE和构建系统而异。大多数 IDE 可以直接导入 Maven 项目。例如,Eclipse 用户可以 File 菜单中选择 Import…Existing Maven Projects

如果无法直接将项目导入 IDE,则可以使用build插件生成IDE基础开发架构。Maven 包含很多用于 Eclipse 和 IDEA 的插件。 Gradle 为 various IDEs 也提供了插件。

::: tip 提示

如果无意中运行了Web应用程序两次,就会看到 “Port already in use” 错误。Spring 工具用户可以使用 重新启动(Relaunch)按钮而不是运行(Run)按钮以确保关闭任何现有实例。

:::

6.7.2 作为打包程序运行(Running as a Packaged Application)

如果您使用 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

6.7.3 使用Maven插件(Using the Maven Plugin)

Spring Boot Maven 插件包含 run 命令,可以用于快速编译和运行您的应用程序。应用程序以 exploded 形式运行,就像在 IDE 中一样。下面示例展示了运行SpringBoot应用程序的命令:

$ mvn spring-boot:run

您可以需要使用 MAVEN_OPTS 操作系统环境变量,如下所示:

$ export MAVEN_OPTS=-Xmx1024m

6.7.4 使用Gradle插件(Using the Gradle Plugin)

Spring Boot Gradle 插件包括 bootRun 任务,可以以1 exploded 的形式运行您的应用程序。每当您应用 org.springframework.bootjava 插件时,都会添加 bootRun 任务,如下所示:

$ gradle bootRun

您可以需要使用 JAVA_OPTS 操作系统环境变量,如下所示:

$ export JAVA_OPTS=-Xmx1024m

6.7.5 热插拔(Hot Swapping)

由于 Spring Boot 应用程序只是普通的 Java 应用程序,因此,JVM 热插拔可以开箱即用。 JVM 热插拔在某种程度上受限于它可以替换的字节码。要获得更完整的解决方案,可以使用 JRebel 。

spring-boot-devtools 模块也支持快速重启应用程序。详情参阅 Hot swapping “How-to” 。

6.8 Developer Tools

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

configurations {
	developmentOnly
	runtimeClasspath {
		extendsFrom developmentOnly
	}
}
dependencies {
	developmentOnly("org.springframework.boot:spring-boot-devtools")
}

::: tip 注意事项

Devtools 可能会导致类加载问题,尤其是在多模块项目中。 Diagnosing Classloading Issues 解释了如何诊断和解决这些问题。

:::

::: tip 提示

运行打包之后的应用程序是,会自动禁用devtools。

如果您的应用程序是使用 java -jar 启动,或者使用一个特定的类加载器启动,那么它将被视为“production application”。您可以使用 spring.devtools.restart.enabled 属性来控制是否启用 devtools。

如果要启用,而不考虑类加载器,请设置 -Dspring.devtools.restart.enabled=true 。在生产环境运行devtools 会带来安全风险.

如果要禁用 devtools,请排除依赖关系或设置 -Dspring.devtools.restart.enabled=false

:::

::: tip 提示

在 Maven 中将依赖关系标记为可选,或在Gradle 中使用 developmentOnly 配置(如上图所示),可以防止devtools 被应用到项目的其它模块中。

:::

::: tip 提示

重新打包的归档文件默认不包括 devtools 。如果需要使用 某些远程 devtools 功能,则需要包含它。当使用 Maven 插件时,将 excludeDevtools 属性设置为 false。当使用 Gradle 插件时,配置依赖的类路径包含 developmentOnly 配置.

<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
            <configuration>
                <!--确保项目打包是将Devtools包含进去-->
                <excludeDevtools>false</excludeDevtools>
            </configuration>
        </plugin>
    </plugins>
</build>

:::

6.8.1 诊断类加载问题(Diagnosing Classloading Issues)

正如 重启 vs 重载 部分所述,重启功能是通过使用两个类加载器实现的,对于大多数应用程序,这种方法效果良好。然而,又是会导致类加载问题,特别是在多模块项目中。

判断类加载问题是否由devtools 和两个类加载器,可以尝试禁用重启. 如果问题得到解决,请 customize the restart classloader 使其包含整个项目。

6.8.2 Propert默认值(Property Defaults)

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

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

缓存选项通常由 application.properties 文件来进行配置的。例如,Thymeleaf 提供了 spring.thymeleaf.cache 属性。无需手动配置这些属性, spring-boot-devtools 模块会提供开发时合理的配置

下表列出了应用的所有属性:

NameDefault Value
server.error.include-binding-errorsalways
server.error.include-messagealways
server.error.include-stacktracealways
server.servlet.jsp.init-parameters.developmenttrue
server.servlet.session.persistenttrue
spring.freemarker.cachefalse
spring.graphql.graphiql.enabledtrue
spring.groovy.template.cachefalse
spring.h2.console.enabledtrue
spring.mustache.servlet.cachefalse
spring.mvc.log-resolved-exceptiontrue
spring.reactor.netty.shutdown-quiet-period0s
spring.template.provider.cachefalse
spring.thymeleaf.cachefalse
spring.web.resources.cache.period0
spring.web.resources.chain.cachefalse

::: tip 备注

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

:::

在开发 Spring MVC 和 Spring WebFlux 应用程序时,您需要更多有关 Web 请求的信息,因此开发工具建议您为 web logging group启用 DEBUG 日志。这将为您提供有关传入请求、处理程序、响应结果和其他详细信息。如果希望记录所有请求的详细信息(包括潜在的敏感信息),您可以打开 spring.mvc.log-request-details
spring.codec.log-request-details 配置属性.

6.8.3 自动重启(Automatic Restart)

只要类路径上的文件发生改变,使用 spring-boot-devtools 的应用程序就会自动重启。在IDE中这是一个非常有用的功能,因为它为代码修改提供了非常快速的反馈体验。默认情况下,类路径指向的目录中所有文件都会受到控制,以防发生变化。请注意,对于某些资源(如静态资源和视图模板),不需要重新启动应用程序。

::: tip 触发重启

由于 DevTools 监控类路径上的资源,因此触发重启的唯一方式就是更新类路径上的资源。无论你使用的是 IDE还是构build插件,修改后的文件都必须重新编译才能触发重启,更新类路径的方式取决于所使用的工具:

  • 在Eclipse中,保存修改后的文件会更新类路径资源并触发重启。
  • 在IntelliJ IDEA中,构建项目(Build +→+ Build Project) 具体相同效果。
  • 如果使用build插件,运行Maven插件的 mvn compile 命令或Gradle插件的 gradle build 命令会触发重启。

:::

::: tip 备注

如果使用build插件Maven 或 Gradle进行重启,则必须将 forking 设置为 enabled。如果禁用 forking,因为devtools 需要一个独立的应用程序类加载器可以使用,所以重启功能将无法使用。

:::

::: tip 提示

自动重启和LiveReload一起使用时效果非常好,详情参阅 LiveReload 部分 。如果使用 JRebel,自动重启功能将会被禁用,以支持动态类重新加载功能。其它devtools 功能(例如LiveReload 和属性覆盖)仍然可以使用。

:::

::: tip 备注

DevTools 依赖于应用程序上下文的shutdown hook 在重启的时候关闭它。如果禁用了shutdown hook (SpringApplication.setRegisterShutdownHook(false)),它将无法正常使用。

:::

::: tip 备注

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

:::

::: tip 注意事项

使用 AspectJ weaving时不支持自动重启。

:::

::: tip 重启 vs 重载

Spring Boot 提供的重启技术是通过使用两个类加载器来实现的。不会更改的类(例如,来自第三方jar的类)会被加载到 base classloader。您正在开发的类将会被加载到 restart classloader 中,当应用程序重启时,restart classloader 将会被丢弃,然后创建一个新的。这种方法意味着应用程序重启的速度比 “cold starts” 要快的多,因为 base classloader 在重启之前已经是可用且已加载。

如果你发现重启对于你的应用程序来说不够快,或者你遇到类加载问题,你可以考虑重载技术,比如 JRebel 。这些技术的原理是在加载类时对其进行重写,使其更易于重载。

:::

记录状态评估中的变化(Logging Changes in Condition Evaluation)

默认情况下,每次重新启动应用程序时,都会记录一份状态评估的报告。该报告会显示应用程序自动配置的更改情况,如添加或删除bean,和配置属性

要禁用状态评估记录,请设置以下属性:

spring:
  devtools:
    restart:
      log-condition-evaluation-delta: false
排除资源(Excluding Resources)

某些资源在更改时不一定需要触发重启。例如,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/**"

::: tip 提示

如果要保留这些默认值并添加其它排除项,请使用 spring.devtools.restart.additional-exclude 属性代替。

:::

监控其它路径(Watching Additional Paths)

当修改不在类路径上的文件时,您可能希望应用程序重启或重载。为此,可以使用 spring.devtools.restart.additional-paths 属性配置其它路径,以便监视修改。您可以使用 the spring.devtools.restart.exclude 属性(如上所诉) 来控制其它路径上的修改是否会触发重启和live reload.

禁用重启(Disabling Restart)

如果不想使用重启功能,您可以使用 spring.devtools.restart.enabled 属性来禁用它。多数情况下,可以在 application.properties 文件配置该属性(这样做仍会初始化restart classloader,但不会监控文件的更改)。

如果您需要完全禁用重启功能(例如,因为它无法和某些特定库一起使用),则需要在调用 SpringApplication.run(…)之前将 系统 属性 spring.devtools.restart.enabled设置为 false ,如下所示:

@SpringBootApplication
public class MyApplication {

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

}
使用触发器文件(Using a Trigger File)

如果您使用的IDE会持续编译已修改的文件,但是您更希望只在特定时间触发重启。为此,你可以使用“触发器文件”,这是一个特殊文件,当需要实际触发重启时,必须对其进行修改。

::: tip 备注

修改文件只会触发检查,只有在Devtools 检测到必须执行某些操作时,才会重启。

:::

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

例如,如果您有一个结构如下的项目:

src
+- main
   +- resources
      +- .reloadtrigger

那么您的 trigger-file 属性如下所示:

spring:
  devtools:
    restart:
      trigger-file: ".reloadtrigger"

现在,只有更新 src/main/resources/.reloadtrigger 时,才会重启。

::: tip 提示

您可能希望将 spring.devtools.restart.trigger-file 设置成 全局设置,这样所有项目的行为方式都是一样的。

:::

有些 IDE 具有不需要手动修改触发器文件的功能。 Spring Tools for Eclipse 和 IntelliJ IDEA (Ultimate Edition) 都支持这种功能,你可以在控制台使用 “reload” 按钮(只要您的 trigger-file 命名为 .reloadtrigger)。对于 IntelliJ IDEA,您可以按照 文档中的说明进行使用。

自定义重启类加载器(Customizing the Restart Classloader)

正如 重启 vs 重载 部分所诉,重启功能是通过两个类加载器来实现的。如果它导致了问题,你可以需要自定义类加载器需要加载哪些内容。

默认情况下,IDE中任何打开的项目都会使用 “restart” classloader,而 .jar 文件会使用“base” classloader。使用 mvn spring-boot:rungradle bootRun 时也是如此:包含 @SpringBootApplication 的项目使用 “restart” classloader加载,而其它项目则使用 “base” classloader 加载。

你可以通过创建 META-INF/spring-devtools.properties 文件,来指定Spring Boot使用不同的类加载器加载项目的部分内容。spring-devtools.properties 文件可以包含以 restart.excluderestart.include为前缀的属性。include 属性配置的文件应该放到 “restart” classloader 中,而 exclude 属性配置的文件应该放到 “base” classloader。该属性值是一个 regex 格式,应用在类路径上,如下所示:

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

::: tip 备注

所有属性key都必须是唯一的。只要是 restart.include.restart.exclude. 为前缀的属性都要被加载。

:::

::: tip 提示

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

:::

已知限制(Known Limitations)

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

遗憾的是,一些第三方库在进行反序列化时没有考虑上下文类加载器。如果发现此类问题,需要向原作者申请修复。

6.8.4 LiveReload

spring-boot-devtools 模块包含一个嵌入式 LiveReload 服务器,可以用于在资源发生变化是触发浏览器刷新。LiveReload 浏览器扩展可以免费用于 Chrome, Firefox 和 Safari。您可以在所用浏览器的市场或商店中搜索 ‘LiveReload’ ,找到这些扩展。

如果不想在应用程序运行时启动 LiveReload 服务器,可以将 spring.devtools.livereload.enabled 属性设置为 false

::: tip 备注

一次只能运行一个 LiveReload 服务器。启动应用程序前,请确保没有其他 LiveReload 服务器在运行。如果从集成开发环境启动多个应用程序,只有第一个支持 LiveReload。

:::

::: warning 警告
需要在更改文件时触发 LiveReload,必须启用 自动重启 。
:::

6.8.5 全局配置(Global Settings)

$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

::: tip 备注

如果在 $HOME/.config/spring-boot 中找不到 devtools 配置文件,则会搜索 $HOME 目录中是否存在 .spring-boot-devtools.properties 文件。这样您就可以使用不支持$HOME/.config/spring-boot位置的旧版 Spring Boot 应用程序共享 devtools 全局配置。

:::

::: tip 备注

devtools properties/yaml 文件不支持Profiles。.spring-boot-devtools.properties 中激活的任何profiles 都不会影响 特定 profile 的配置文件 的加载。YAML 和 Properties 类型文件的特定 Profile 文件名(例如 spring-boot-devtools-<profile>.properties)和 spring.config.activate.on-profile 文件均不支持。

:::

配置文件系统监视器(Configuring File System Watcher)

FileSystemWatcher 的工作原理是以一定时间间隔轮询观察类的修改,然后等待预定义的静默期,以确保不再有修改。由于 Spring Boot 完全依赖 IDE 来编译文件并将其复制到 Spring Boot 可以读取到的位置,因此您可能会发现当 devtools 重启应用程序是,有时某些修改不会被反映出来。如果您经常遇见此类问题,请尝试将 spring.devtools.restart.poll-intervalspring.devtools.restart.quiet-period 属性参数设置为您需要的值:

spring:
  devtools:
    restart:
      poll-interval: "2s"
      quiet-period: "1s"

现在,每2秒钟就会轮询一次,观察受监控的类路径目录是否有变化,并保持1秒钟的静默期,以确保没有其他类变化。

6.8.6 远程应用程序(Remote Applications)

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 属性。就像设置重要的密码或密码一样,该值应是唯一且为强密码,以防被猜测或暴力破解。

远程 devtools 支持由两部分组成:一个接受连接的服务端端点和在IDE运行的客户端程序。服务端组件会在设置了 spring.devtools.remote.secret 属性后自动启用。客户端组件必须手动启动。

::: tip 备注

Spring WebFlux 应用程序不支持远程 devtools。

:::

运行远程客户端程序(Running the Remote Client Application)

远程客户端程序可以在IDE中运行。运行 org.springframework.boot.devtools.RemoteSpringApplication 时,需要与所连接的远程项目使用相同的类路径。该应用程序的唯一必要参数是它所连接的远程URL。

例如,如果您使用 Eclipse 或 Spring Tools,并且有一个名为 my-app 的项目已部署到 Cloud Foundry,您将执行以下操作:

  • Run菜单中选择 Run Configurations…
  • 创建一个新的 Java Application “启动配置”。
  • 浏览 my-app 项目。
  • 使用 org.springframework.boot.devtools.RemoteSpringApplication 作为主类。
  • https://myapp.cfapps.io 添加到 Program arguments (或者任何远程URL)。

正在远程的远程客户端可能如下所示:

  .   ____          _                                              __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _          ___               _      \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` |        | _ \___ _ __  ___| |_ ___ \ \ \ \
 \\/  ___)| |_)| | | | | || (_| []::::::[]   / -_) '  \/ _ \  _/ -_) ) ) ) )
  '  |____| .__|_| |_|_| |_\__, |        |_|_\___|_|_|_\___/\__\___|/ / / /
 =========|_|==============|___/===================================/_/_/_/
 :: Spring Boot Remote ::  (v2.7.18-SNAPSHOT)

2023-11-22 15:38:10.397  INFO 916 --- [           main] o.s.b.devtools.RemoteSpringApplication   : Starting RemoteSpringApplication v2.7.18-SNAPSHOT using Java 1.8.0_392 on myhost with PID 916 (/Users/myuser/.m2/repository/org/springframework/boot/spring-boot-devtools/2.7.18-SNAPSHOT/spring-boot-devtools-2.7.18-SNAPSHOT.jar started by myuser in /opt/apps/)
2023-11-22 15:38:10.401  INFO 916 --- [           main] o.s.b.devtools.RemoteSpringApplication   : No active profile set, falling back to 1 default profile: "default"
2023-11-22 15:38:10.702  INFO 916 --- [           main] o.s.b.d.a.OptionalLiveReloadServer       : LiveReload server is running on port 35729
2023-11-22 15:38:10.724  INFO 916 --- [           main] o.s.b.devtools.RemoteSpringApplication   : Started RemoteSpringApplication in 0.736 seconds (JVM running for 1.14)

::: tip 备注

因为远程客户端与真正的应用程序使用相同的类路径,所有它可以直接读取应用程序属性。这就是读取 spring.devtools.remote.secret 属性并将其传递给服务器进行身份验证的方式。

:::

::: tip 提示

始终建议使用 https:// 作为连接协议,以便加密通信信息并且密码无法被截获。

:::

::: tip 提示

如果需要使用代理访问远程应用程序,请配置 spring.devtools.remote.proxy.hostspring.devtools.remote.proxy.port 属性。

:::

远程升级(Remote Update)

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

在速度较慢的开发环境中,可能会出现静默期不够的情况,这时类中的更改可能会被分批进行。第一批更改上传后,服务器将重新启动。由于服务器正在重启,下一批更改无法发送到应用程序。

这种情况通常会在 "RemoteSpringApplication "日志中出现警告,提示无法上传某些类,并随之重试。但它也可能导致应用程序代码不一致,以及在上传第一批更改后无法重启。如果经常出现此类问题,请尝试将 spring.devtools.restart.poll-intervalspring.devtools.restart.quiet-period 属性参数设置为您需要的值。请参阅 配置文件系统监视器 来配置这些属性。

::: tip 备注

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

:::

6.9 打包应用程序(Packaging Your Application for Production)

可执行 jar 可用于生产部署。由于它们是独立的,因此也非常适合基于云的部署。

对于其它的 “production ready” 功能,例如运行状况,审计和度量标准REST或JMX端点,请考虑添加 spring-boot-actuator。 详情参阅 Production-ready Features

6.10 接下来要阅读的内容(What to Read Next)

您现在应该了解如何使用Spring Boot和一些您应该遵循的最佳实践。现在,您可以继续深入了解特定的 Spring Boot 功能 ,也可以跳到前面阅读Spring Boot的 “production ready” 部分。

举报

相关推荐

0 条评论