轩辕李的博客 轩辕李的博客
首页
  • Java
  • Spring
  • 其他语言
  • 工具
  • HTML&CSS
  • JavaScript
  • 分布式
  • 代码质量管理
  • 基础
  • 操作系统
  • 计算机网络
  • 编程范式
  • 安全
  • 中间件
  • 心得
关于
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

轩辕李

勇猛精进,星辰大海
首页
  • Java
  • Spring
  • 其他语言
  • 工具
  • HTML&CSS
  • JavaScript
  • 分布式
  • 代码质量管理
  • 基础
  • 操作系统
  • 计算机网络
  • 编程范式
  • 安全
  • 中间件
  • 心得
关于
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • Java

  • Spring

    • 基础

    • 框架

    • Spring Boot

      • 开发你的第一个 Spring Boot 应用程序
      • Spring Boot开发初体验
        • 使用 Docker 部署 Spring Boot 应用
        • Spring Boot版本新特性
      • 集成

    • 其他语言

    • 工具

    • 后端
    • Spring
    • Spring Boot
    轩辕李
    2024-08-15
    目录

    Spring Boot开发初体验

    本文将详细介绍如何使用Spring Boot。

    它涵盖了诸如构建系统、自动配置以及如何运行应用程序等主题。

    我们还将介绍一些Spring Boot的最佳实践。尽管Spring Boot并没有什么特别之处(它只是你可以使用的另一个库),但有一些建议,遵循这些建议可以让你的开发过程更轻松一些。

    如果你刚开始使用Spring Boot,在深入阅读本节内容之前,你可能应该先阅读开发你的第一个Spring Boot应用程序教程。

    # 一、构建系统

    强烈建议你选择一个支持依赖管理的构建系统,并且该系统能够使用发布到Maven中央仓库的构件。我们推荐你选择Maven或Gradle。虽然Spring Boot也可以与其他构建系统(例如Ant)配合使用,但这些系统的支持并不完善。

    # 二、依赖管理

    Spring Boot的每个版本都提供了一份精心筛选的它所支持的依赖列表。实际上,在你的构建配置中,你无需为这些依赖指定版本,因为Spring Boot会为你管理这些版本。当你升级Spring Boot本身时,这些依赖也会以一致的方式进行升级。

    注意:如有需要,你仍然可以指定版本来覆盖Spring Boot的建议。

    这份精心筛选的列表包含了你可以与Spring Boot一起使用的所有Spring模块,以及精选的第三方库列表。该列表以标准的物料清单(spring-boot-dependencies)形式提供,可同时用于Maven和Gradle。

    警告:每个Spring Boot版本都与Spring框架的一个基础版本相关联。我们强烈建议你不要指定Spring框架的版本。

    # 三、Starters

    Starters是一组方便的依赖描述符,你可以将其包含在应用程序中。你可以一站式获取所有所需的Spring及相关技术,而无需搜索示例代码并复制粘贴大量依赖描述符。例如,如果你想开始使用Spring和JPA进行数据库访问,只需在项目中包含spring-boot-starter-data-jpa依赖即可。

    Starters包含了很多让项目快速启动并运行所需的依赖,并且提供了一组一致的、受支持的具有传递性的依赖管理。

    # 1、命名规则

    所有官方的Starters都遵循类似的命名模式:spring-boot-starter-*,其中*表示特定类型的应用程序。这种命名结构旨在帮助你查找Starter。许多IDE中的Maven集成允许你按名称搜索依赖。例如,安装了适当的Eclipse或Spring Tools插件后,你可以在POM编辑器中按ctrl - space并输入“spring-boot-starter”以获取完整列表。

    正如创建你自己的Starter部分所解释的,第三方Starter不应以spring-boot开头,因为这是为官方Spring Boot构件保留的。相反,第三方Starter通常以项目名称开头。例如,一个名为thirdpartyproject的第三方Starter项目通常命名为thirdpartyproject-spring-boot-starter。

    以下是Spring Boot在org.springframework.boot组下提供的应用程序Starters:

    名称 描述
    spring-boot-starter 核心Starter,包括自动配置支持、日志记录和YAML
    spring-boot-starter-activemq 用于使用Apache ActiveMQ进行JMS消息传递的Starter
    spring-boot-starter-amqp 用于使用Spring AMQP和Rabbit MQ的Starter
    spring-boot-starter-aop 用于使用Spring AOP和AspectJ进行面向切面编程的Starter
    spring-boot-starter-artemis 用于使用Apache Artemis进行JMS消息传递的Starter
    spring-boot-starter-batch 用于使用Spring Batch的Starter
    spring-boot-starter-cache 用于使用Spring框架缓存支持的Starter
    spring-boot-starter-data-cassandra 用于使用Cassandra分布式数据库和Spring Data Cassandra的Starter
    spring-boot-starter-data-cassandra-reactive 用于使用Cassandra分布式数据库和Spring Data Cassandra Reactive的Starter
    spring-boot-starter-data-couchbase 用于使用Couchbase文档数据库和Spring Data Couchbase的Starter
    spring-boot-starter-data-couchbase-reactive 用于使用Couchbase文档数据库和Spring Data Couchbase Reactive的Starter
    spring-boot-starter-data-elasticsearch 用于使用Elasticsearch搜索和分析引擎以及Spring Data Elasticsearch的Starter
    spring-boot-starter-data-jdbc 用于使用Spring Data JDBC的Starter
    spring-boot-starter-data-jpa 用于结合Hibernate使用Spring Data JPA的Starter
    spring-boot-starter-data-ldap 用于使用Spring Data LDAP的Starter
    spring-boot-starter-data-mongodb 用于使用MongoDB文档数据库和Spring Data MongoDB的Starter
    spring-boot-starter-data-mongodb-reactive 用于使用MongoDB文档数据库和Spring Data MongoDB Reactive的Starter
    spring-boot-starter-data-neo4j 用于使用Neo4j图数据库和Spring Data Neo4j的Starter
    spring-boot-starter-data-r2dbc 用于使用Spring Data R2DBC的Starter
    spring-boot-starter-data-redis 用于使用Redis键值存储、Spring Data Redis和Lettuce客户端的Starter
    spring-boot-starter-data-redis-reactive 用于使用Redis键值存储、Spring Data Redis Reactive和Lettuce客户端的Starter
    spring-boot-starter-data-rest 用于使用Spring Data REST和Spring MVC通过REST暴露Spring Data仓库的Starter
    spring-boot-starter-freemarker 用于使用FreeMarker视图构建MVC Web应用程序的Starter
    spring-boot-starter-graphql 用于使用Spring GraphQL构建GraphQL应用程序的Starter
    spring-boot-starter-groovy-templates 用于使用Groovy模板视图构建MVC Web应用程序的Starter
    spring-boot-starter-hateoas 用于使用Spring MVC和Spring HATEOAS构建基于超媒体的RESTful Web应用程序的Starter
    spring-boot-starter-integration 用于使用Spring Integration的Starter
    spring-boot-starter-jdbc 用于结合HikariCP连接池使用JDBC的Starter
    spring-boot-starter-jersey 用于使用JAX - RS和Jersey构建RESTful Web应用程序的Starter。是spring-boot-starter-web的替代方案
    spring-boot-starter-jooq 用于使用jOOQ结合JDBC访问SQL数据库的Starter。是spring-boot-starter-data-jpa或spring-boot-starter-jdbc的替代方案
    spring-boot-starter-json 用于读写JSON的Starter
    spring-boot-starter-mail 用于使用Java Mail和Spring框架邮件发送支持的Starter
    spring-boot-starter-mustache 用于使用Mustache视图构建Web应用程序的Starter
    spring-boot-starter-oauth2-authorization-server 用于使用Spring Authorization Server功能的Starter
    spring-boot-starter-oauth2-client 用于使用Spring Security的OAuth2/OpenID Connect客户端功能的Starter
    spring-boot-starter-oauth2-resource-server 用于使用Spring Security的OAuth2资源服务器功能的Starter
    spring-boot-starter-pulsar 用于使用Spring for Apache Pulsar的Starter
    spring-boot-starter-pulsar-reactive 用于使用Spring for Apache Pulsar Reactive的Starter
    spring-boot-starter-quartz 用于使用Quartz调度器的Starter
    spring-boot-starter-rsocket 用于构建RSocket客户端和服务器的Starter
    spring-boot-starter-security 用于使用Spring Security的Starter
    spring-boot-starter-test 用于使用JUnit Jupiter、Hamcrest和Mockito等库测试Spring Boot应用程序的Starter
    spring-boot-starter-thymeleaf 用于使用Thymeleaf视图构建MVC Web应用程序的Starter
    spring-boot-starter-validation 用于结合Hibernate Validator使用Java Bean Validation的Starter
    spring-boot-starter-web 用于使用Spring MVC构建Web(包括RESTful)应用程序的Starter。默认使用Tomcat作为嵌入式容器
    spring-boot-starter-web-services 用于使用Spring Web Services的Starter
    spring-boot-starter-webflux 用于使用Spring框架的响应式Web支持构建WebFlux应用程序的Starter
    spring-boot-starter-websocket 用于使用Spring框架的MVC WebSocket支持构建WebSocket应用程序的Starter

    除了应用程序Starters之外,还可以使用以下Starters来添加生产就绪功能:

    名称 描述
    spring-boot-starter-actuator 用于使用Spring Boot的Actuator的Starter,Actuator提供生产就绪功能,帮助你监控和管理应用程序

    最后,如果你想排除或替换特定的技术方面,Spring Boot还提供了以下Starters:

    名称 描述
    spring-boot-starter-jetty 用于使用Jetty作为嵌入式Servlet容器的Starter。是spring-boot-starter-tomcat的替代方案
    spring-boot-starter-log4j2 用于使用Log4j2进行日志记录的Starter。是spring-boot-starter-logging的替代方案
    spring-boot-starter-logging 用于使用Logback进行日志记录的Starter。默认的日志记录Starter
    spring-boot-starter-reactor-netty 用于使用Reactor Netty作为嵌入式响应式HTTP服务器的Starter
    spring-boot-starter-tomcat 用于使用Tomcat作为嵌入式Servlet容器的Starter。是spring-boot-starter-web默认使用的Servlet容器Starter
    spring-boot-starter-undertow 用于使用Undertow作为嵌入式Servlet容器的Starter。是spring-boot-starter-tomcat的替代方案

    提示:有关其他社区贡献的Starters列表,请参阅GitHub上spring-boot-starters模块中的README文件 (opens new window)。

    # 四、代码结构设计

    Spring Boot 并不要求特定的代码布局来运行,但遵循一些最佳实践会有所帮助。

    提示:如果你希望基于领域来强制执行一种结构,可以参考 Spring Modulith (opens new window)。

    # 1、使用“默认”包

    当一个类不包含 package 声明时,它会被视为处于“默认包”中。我们通常不建议使用“默认包”,应尽量避免。对于使用了 @ComponentScan (opens new window)、@ConfigurationPropertiesScan (opens new window)、@EntityScan (opens new window) 或 @SpringBootApplication (opens new window) 注解的 Spring Boot 应用程序来说,使用默认包可能会引发特定的问题,因为此时会读取每个 JAR 中的每一个类。

    提示:我们建议你遵循 Java 推荐的包命名约定,使用反向域名(例如 com.example.project)。

    # 2、定位主应用类

    我们通常建议将主应用类放在其他类之上的根包中。@SpringBootApplication 注解 通常会放在主类上,它会隐式地为某些项定义一个基础“搜索包”。例如,如果你正在编写一个 JPA 应用程序,被 @SpringBootApplication 注解标记的类所在的包会被用于搜索 @Entity (opens new window) 项。使用根包还可以使组件扫描仅应用于你的项目。

    提示:如果你不想使用 @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 注解,示例代码如下:

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

    # 五、配置类

    Spring Boot 更倾向于使用基于 Java 的配置。虽然可以使用 SpringApplication 搭配 XML 源,但通常建议主配置源采用单个 @Configuration 类。一般来说,定义了 main 方法的类很适合作为主 @Configuration 类。

    提示:互联网上有许多使用 XML 配置的 Spring 配置示例。如果可能的话,尽量使用等效的基于 Java 的配置。搜索 Enable* 注解是个不错的切入点。

    # 1、导入额外的配置类

    无需将所有 @Configuration 都放在一个类中。可以使用 @Import 注解来导入额外的配置类。另外,也可以使用 @ComponentScan 自动扫描所有 Spring 组件,包括 @Configuration 类。

    # 2、导入 XML 配置

    如果必须使用基于 XML 的配置,建议仍从一个 @Configuration 类入手。然后可以使用 @ImportResource 注解来加载 XML 配置文件。

    # 六、自动配置

    Spring Boot自动配置会根据你添加的JAR依赖项,尝试自动配置你的Spring应用程序。例如,如果HSQLDB在你的类路径中,并且你没有手动配置任何数据库连接Bean,那么Spring Boot会自动配置一个内存数据库。

    你需要通过在某个@Configuration类上添加@EnableAutoConfiguration或@SpringBootApplication注解来启用自动配置。

    提示:你应该只添加一个@SpringBootApplication或@EnableAutoConfiguration注解。我们通常建议只在主@Configuration类中添加其中一个注解。

    # 1、逐步替换自动配置

    自动配置是非侵入式的。任何时候,你都可以开始定义自己的配置来替换自动配置的特定部分。例如,如果你添加了自己的DataSource Bean,默认的嵌入式数据库支持就会失效。

    如果你想了解当前正在应用哪些自动配置以及原因,可以使用--debug开关启动应用程序。这样做会为一些核心日志记录器启用调试日志,并将条件报告记录到控制台。

    # 2、禁用特定的自动配置类

    如果你发现某些不想要的自动配置类正在被应用,可以使用@SpringBootApplication的exclude属性来禁用它们,如下例所示:

    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方法,仅用于内部使用,我们不建议直接使用它们。

    # 3、自动配置包

    自动配置包是各种自动配置功能在扫描实体和Spring Data仓库等内容时默认查找的包。@EnableAutoConfiguration注解(直接使用或通过@SpringBootApplication存在)决定了默认的自动配置包。可以使用@AutoConfigurationPackage注解配置额外的包。

    # 七、Bean 与依赖注入

    你可以自由使用任何标准的 Spring 框架技术来定义 Bean 及其注入的依赖。我们通常建议使用构造函数注入来连接依赖关系,并使用 @ComponentScan 来查找 Bean。

    如果按照上述建议组织代码(将应用类放置在顶级包中),你可以不添加任何参数地使用 @ComponentScan,或者使用 @SpringBootApplication 注解,该注解隐式包含了 @ComponentScan。你所有的应用组件(@Component、@Service、@Repository、@Controller 等)都会自动注册为 Spring Bean。

    以下示例展示了一个使用构造函数注入来获取所需 RiskAssessor Bean 的 @Service Bean:

    import org.springframework.stereotype.Service;
    
    @Service
    public class MyAccountService implements AccountService {
    
        private final RiskAssessor riskAssessor;
    
        public MyAccountService(RiskAssessor riskAssessor) {
            this.riskAssessor = riskAssessor;
        }
    
        // ...
    
    }
    

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

    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 的,这表明它之后不能被更改。

    # 八、使用 @SpringBootApplication 注解

    许多 Spring Boot 开发者希望他们的应用程序能够使用自动配置、组件扫描功能,并能够在他们的 “应用程序类” 中定义额外的配置。单个 @SpringBootApplication 注解可以用来启用这三项功能,即:

    • @EnableAutoConfiguration:启用 Spring Boot 的自动配置机制
    • @ComponentScan:启用对应用程序所在包的 @Component 扫描
    • @SpringBootConfiguration:启用在上下文中注册额外的 bean 或导入其他配置类。这是 Spring 标准 @Configuration 的替代方案,有助于在集成测试中 检测配置。

    以下是 Java 示例:

    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    
    // 等同于 @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。

    # 十、运行您的应用程序

    将应用程序打包为 JAR 并使用嵌入式 HTTP 服务器的最大优势之一是,您可以像运行其他普通 Java 应用程序一样运行它。这同样适用于调试 Spring Boot 应用程序,您不需要任何特殊的 IDE 插件或扩展。

    注意: 以下选项最适合在本地开发环境中运行应用程序。

    注意: 本节仅涵盖基于 JAR 的打包方式。

    # 1、从 IDE 中运行

    您可以在 IDE 中将 Spring Boot 应用程序作为 Java 应用程序来运行。不过,首先您需要导入项目。导入步骤会因 IDE 和构建系统的不同而有所差异。大多数 IDE 都可以直接导入 Maven 项目。例如,Eclipse 用户可以从“文件”菜单中选择“导入…”→“现有 Maven 项目”。

    如果您无法直接将项目导入到 IDE 中,您可以尝试使用构建插件生成 IDE 元数据。Maven 提供了适用于 Eclipse (opens new window) 和 IDEA (opens new window) 的插件。Gradle 则为 各种 IDE (opens new window) 提供了插件。

    提示: 如果您不小心多次运行同一个 Web 应用程序,您会看到“端口已被占用”的错误信息。Spring Tools 用户可以使用“重新启动”按钮而不是“运行”按钮,以确保关闭任何现有的实例。

    # 2、作为打包应用程序运行

    如果您使用 Spring Boot Maven 或 Gradle 插件创建了可执行 JAR 文件,您可以使用 java -jar 命令来运行应用程序,如下例所示:

    $ java -jar target/myapplication-0.0.1-SNAPSHOT.jar
    

    您还可以在启用远程调试支持的情况下运行打包好的应用程序。这样做可以让您将调试器连接到打包后的应用程序,如下例所示:

    $ java -agentlib:jdwp=server=y,transport=dt_socket,address=8000,suspend=n \
           -jar target/myapplication-0.0.1-SNAPSHOT.jar
    

    # 3、使用 Maven 插件

    Spring Boot Maven 插件包含一个 run 目标,可用于快速编译和运行您的应用程序。应用程序将以扩展形式运行,就像在 IDE 中一样。以下是运行 Spring Boot 应用程序的典型 Maven 命令示例:

    $ mvn spring-boot:run
    

    您可能还想使用 MAVEN_OPTS 操作系统环境变量,如下例所示:

    $ export MAVEN_OPTS=-Xmx1024m
    

    # 4、使用 Gradle 插件

    Spring Boot Gradle 插件同样包含一个 bootRun 任务,可用于以扩展形式运行您的应用程序。只要您应用了 org.springframework.boot 和 java 插件,bootRun 任务就会被添加,如下例所示:

    $ gradle bootRun
    

    您可能还想使用 JAVA_OPTS 操作系统环境变量,如下例所示:

    $ export JAVA_OPTS=-Xmx1024m
    

    # 5、热交换

    由于 Spring Boot 应用程序是普通的 Java 应用程序,JVM 热交换应该可以直接使用。不过,JVM 热交换在可以替换的字节码方面存在一定限制。若要获得更完整的解决方案,可以使用 JRebel (opens new window)。

    spring-boot-devtools 模块还提供了快速应用重启的支持。

    # 十一、开发者工具

    Spring Boot 包含一组额外的工具,可让应用程序开发体验更加愉悦。spring-boot-devtools 模块可包含在任何项目中,以提供额外的开发时特性。要包含开发工具支持,可将该模块依赖添加到你的构建中,以下是 Maven 和 Gradle 的示例:

    # 1、Maven

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

    # 2、Gradle

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

    注意:开发工具可能会导致类加载问题,特别是在多模块项目中。诊断类加载问题 一节解释了如何诊断和解决这些问题。

    注意:运行完全打包的应用程序时,开发工具会自动禁用。如果你的应用程序是通过 java -jar 启动的,或者是从特殊的类加载器启动的,那么它会被视为“生产应用程序”。你可以使用 spring.devtools.restart.enabled 系统属性来控制此行为。要启用开发工具,无论用于启动应用程序的类加载器如何,都可设置 -Dspring.devtools.restart.enabled=true 系统属性。但在生产环境中不应这样做,因为运行开发工具存在安全风险。要禁用开发工具,可排除依赖项或设置 -Dspring.devtools.restart.enabled=false 系统属性。

    提示:在 Maven 中将依赖标记为可选,或在 Gradle 中使用 developmentOnly 配置(如上所示),可防止开发工具被传递应用到使用你的项目的其他模块。

    提示:重新打包的归档文件默认不包含开发工具。如果你想使用 某些远程开发工具特性,则需要包含它。使用 Maven 插件时,将 excludeDevtools 属性设置为 false。使用 Gradle 插件时,配置任务的类路径以包含 developmentOnly 配置 (opens new window)。

    # 十二、诊断类加载问题

    如 重启与重载对比 一节所述,重启功能是通过使用两个类加载器来实现的。对于大多数应用程序来说,这种方法效果很好。但是,它有时可能会导致类加载问题,特别是在多模块项目中。

    要诊断类加载问题是否确实由开发工具及其两个类加载器引起,可 尝试禁用重启。如果这样可以解决问题,则 自定义重启类加载器 以包含整个项目。

    # 十三、属性默认值

    Spring Boot 支持的几个库使用缓存来提高性能。例如,模板引擎 (opens new window) 会缓存编译后的模板,以避免重复解析模板文件。此外,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.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 日志记录。这将为你提供有关传入请求、处理请求的处理程序、响应结果和其他详细信息。如果你希望记录所有请求细节(包括潜在的敏感信息),可以打开 spring.mvc.log-request-details 或 spring.codec.log-request-details 配置属性。

    # 十四、自动重启

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

    # 1、触发重启

    由于开发工具监视类路径资源,触发重启的唯一方法是更新类路径。无论你是使用 IDE 还是构建插件之一,修改后的文件都必须重新编译才能触发重启。更新类路径的方式取决于你使用的工具:

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

    注意:如果你使用构建插件通过 Maven 或 Gradle 重启应用程序,必须将 forking 设置为 enabled。如果禁用分叉,开发工具使用的隔离应用程序类加载器将不会创建,重启将无法正常工作。

    注意:开发工具依赖于应用程序上下文的关闭挂钩在重启期间关闭应用程序。如果你禁用了关闭挂钩(SpringApplication.setRegisterShutdownHook(false)),则它将无法正常工作。

    注意:开发工具需要自定义应用程序上下文使用的 ResourceLoader(请参阅 ResourceLoader (opens new window)),如果你的应用程序已经提供了一个,则会对其进行包装。不支持在应用程序上下文上直接重写 getResource 方法。

    注意:使用 AspectJ 织入时不支持自动重启。

    # 2、重启与重载对比

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

    如果你发现重启对于你的应用程序来说不够快,或者遇到类加载问题,你可以考虑使用 ZeroTurnaround 提供的 JRebel (opens new window) 等重新加载技术。这些技术通过在类加载时重写类来使它们更易于重新加载。

    # 3、记录条件评估的变化

    默认情况下,每次应用程序重启时,都会记录一份显示条件评估差异的报告。该报告显示了你对应用程序自动配置所做的更改,例如添加或删除 bean 以及设置配置属性。

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

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

    YAML

    spring:
      devtools:
        restart:
          log-condition-evaluation-delta: false
    

    # 4、排除资源

    某些资源在更改时不一定需要触发重启。例如,可以直接编辑 Thymeleaf 模板。默认情况下,更改 /META-INF/maven、/META-INF/resources、/resources、/static、/public 或 /templates 中的资源不会触发重启,但会触发 实时重新加载。如果你想自定义这些排除项,可以使用 spring.devtools.restart.exclude 属性。例如,要仅排除 /static 和 /public,可以设置以下属性: Properties

    spring.devtools.restart.exclude=static/**,public/**
    

    YAML

    spring:
      devtools:
        restart:
          exclude: "static/**,public/**"
    

    提示:如果你想保留默认设置并 添加 额外的排除项,可以使用 spring.devtools.restart.additional-exclude 属性。

    # 5、监视额外的路径

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

    # 6、禁用重启

    如果你不想使用重启功能,可以使用 spring.devtools.restart.enabled 属性禁用它。在大多数情况下,你可以在 application.properties 中设置此属性(这样做仍然会初始化重启类加载器,但不会监视文件更改)。

    如果你需要 完全 禁用重启支持(例如,因为它与特定库不兼容),则需要在调用 SpringApplication.run(…) 之前将 spring.devtools.restart.enabled 系统属性 (opens new window) 设置为 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);
        }
    
    }
    

    # 7、使用触发文件

    如果你使用的 IDE 会持续编译更改的文件,你可能希望仅在特定时间触发重启。为此,你可以使用“触发文件”,这是一个特殊文件,只有在你希望实际触发重启检查时才需要修改它。

    注意:对文件的任何更新都会触发检查,但只有当开发工具检测到有需要处理的内容时才会实际重启。

    要使用触发文件,请将 spring.devtools.restart.trigger-file 属性设置为触发文件的名称(不包括任何路径)。触发文件必须出现在类路径的某个位置。

    例如,如果你的项目具有以下结构:

    src
    +- main
       +- resources
          +- .reloadtrigger
    

    那么你的 trigger-file 属性应该是: Properties

    spring.devtools.restart.trigger-file=.reloadtrigger
    

    YAML

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

    现在,只有当 src/main/resources/.reloadtrigger 文件更新时才会发生重启。

    提示:你可能希望将 spring.devtools.restart.trigger-file 设置为 全局设置,以便所有项目的行为一致。

    某些 IDE 具有一些功能,可以让你无需手动更新触发文件。Eclipse 的 Spring Tools (opens new window) 和 IntelliJ IDEA(旗舰版) (opens new window) 都有这样的支持。使用 Spring Tools 时,你可以从控制台视图使用“重新加载”按钮(前提是你的 trigger-file 名为 .reloadtrigger)。对于 IntelliJ IDEA,你可以遵循 其文档中的说明 (opens new window)。

    # 8、自定义重启类加载器

    如前面 重启与重载对比 一节所述,重启功能是通过使用两个类加载器来实现的。如果这导致了问题,你可以使用 spring.devtools.restart.enabled 系统属性诊断问题,如果关闭重启后应用程序可以正常工作,你可能需要自定义哪些内容由哪个类加载器加载。

    默认情况下,IDE 中的任何打开项目都会使用“重启”类加载器加载,任何常规 .jar 文件都会使用“基础”类加载器加载。如果你使用 mvn spring-boot:run 或 gradle bootRun 也是如此:包含 @SpringBootApplication 的项目会使用“重启”类加载器加载,其他所有内容都会使用“基础”类加载器加载。应用程序启动时,类路径会打印在控制台上,这有助于识别任何有问题的条目。反射使用的类,特别是注解,可能会在应用程序类使用它们之前在启动时加载到父(固定)类加载器中,这可能导致 Spring 在应用程序中无法检测到它们。

    你可以通过创建 META-INF/spring-devtools.properties 文件来指示 Spring Boot 使用不同的类加载器加载项目的部分内容。spring-devtools.properties 文件可以包含以 restart.exclude 和 restart.include 为前缀的属性。include 元素是应该提升到“重启”类加载器的项,exclude 元素是应该降级到“基础”类加载器的项。属性的值是一个正则表达式模式,应用于启动时传递给 JVM 的类路径。以下是一个示例,其中排除了一些本地类文件,并在重启类加载器中包含了一些额外的库:

    restart:
      exclude:
        companycommonlibs: "/mycorp-common-[\\w\\d-\\.]/(build|bin|out|target)/"
      include:
        projectcommon: "/mycorp-myproj-[\\w\\d-\\.]+\\.jar"
    

    注意:所有属性键必须唯一。只要属性以 restart.include. 或 restart.exclude. 开头,就会被考虑。

    提示:会加载类路径中所有的 META-INF/spring-devtools.properties 文件。你可以将文件打包在项目中,或项目使用的库中。不能使用系统属性,只能使用属性文件。

    # 9、已知限制

    使用标准 ObjectInputStream (opens new window) 反序列化的对象,重启功能可能无法正常工作。如果你需要反序列化数据,可能需要结合使用 Spring 的 ConfigurableObjectInputStream (opens new window) 和 Thread.currentThread().getContextClassLoader()。

    不幸的是,一些第三方库在反序列化时不考虑上下文类加载器。如果你遇到这样的问题,需要向原作者请求修复。

    # 十五、LiveReload

    spring-boot-devtools 模块包含一个嵌入式 LiveReload 服务器,当资源发生更改时,可用于触发浏览器刷新。LiveReload 浏览器扩展可免费用于 Chrome、Firefox 和 Safari。你可以在所选浏览器的应用商店或扩展市场中搜索“LiveReload”来找到这些扩展。

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

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

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

    # 十六、全局设置

    你可以通过在 $HOME/.config/spring-boot 目录中添加以下任何文件来配置全局开发工具设置:

    1. spring-boot-devtools.properties
    2. spring-boot-devtools.yaml
    3. spring-boot-devtools.yml

    添加到这些文件中的任何属性都将应用于你机器上使用开发工具的 所有 Spring Boot 应用程序。例如,要配置重启始终使用 触发文件,可以在 spring-boot-devtools 文件中添加以下属性: Properties

    spring.devtools.restart.trigger-file=.reloadtrigger
    

    YAML

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

    默认情况下,$HOME 是用户的主目录。要自定义此位置,请设置 SPRING_DEVTOOLS_HOME 环境变量或 spring.devtools.home 系统属性。

    注意:如果在 $HOME/.config/spring-boot 中未找到开发工具配置文件,会在 $HOME 目录的根目录中搜索是否存在 .spring-boot-devtools.properties 文件。这允许你与使用较旧版本 Spring Boot 的应用程序共享开发工具全局配置,这些旧版本的 Spring Boot 不支持 $HOME/.config/spring-boot 位置。

    注意:开发工具属性/ YAML 文件不支持配置文件。在 .spring-boot-devtools.properties 中激活的任何配置文件都不会影响 特定配置文件的加载 (opens new window)。不支持特定配置文件的文件名(格式为 spring-boot-devtools-<profile>.properties)以及 YAML 和属性文件中的 spring.config.activate.on-profile 文档。

    # 1、配置文件系统监视器

    FileSystemWatcher(请参阅 FileSystemWatcher (opens new window))通过以一定的时间间隔轮询类更改来工作,然后等待预定义的安静期,以确保没有更多的更改。由于 Spring Boot 完全依赖于 IDE 来编译和复制文件到 Spring Boot 可以读取它们的位置,你可能会发现在某些时候,开发工具重启应用程序时,某些更改没有得到反映。如果你经常遇到此类问题,可尝试将 spring.devtools.restart.poll-interval 和 spring.devtools.restart.quiet-period 参数增加到适合你开发环境的值: Properties

    spring.devtools.restart.poll-interval=2s
    spring.devtools.restart.quiet-period=1s
    

    YAML

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

    现在,将每 2 秒轮询一次受监视的类路径目录以检查更改,并保持 1 秒的安静期,以确保没有其他类更改。

    # 十七、远程应用程序

    Spring Boot 开发工具不限于本地开发。在远程运行应用程序时,你还可以使用一些特性。远程支持是可选的,因为启用它可能存在安全风险。只有在受信任的网络上运行或通过 SSL 进行保护时,才应启用它。如果这些选项都不可用,你不应使用开发工具的远程支持。永远不要在生产部署中启用此支持。

    要启用它,你需要确保 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 应用程序不支持远程开发工具。

    # 1、运行远程客户端应用程序

    远程客户端应用程序旨在在你的 IDE 中运行。你需要使用与要连接的远程项目相同的类路径来运行 RemoteSpringApplication(请参阅 RemoteSpringApplication (opens new window))。该应用程序的唯一必需参数是它要连接的远程 URL。

    例如,如果你使用的是 Eclipse 或 Spring Tools,并且有一个名为 my-app 的项目部署到了 Cloud Foundry,你可以按以下步骤操作:

    1. 从 Run 菜单中选择 Run Configurations…。
    2. 创建一个新的 Java Application“启动配置”。
    3. 浏览选择 my-app 项目。
    4. 使用 RemoteSpringApplication 作为主类。
    5. 将 https://myapp.cfapps.io(或你的远程 URL)添加到 Program arguments 中。

    运行中的远程客户端可能如下所示:

      .   ____          _                                              __ _ _
     /\\ / ___'_ __ _ _(_)_ __  __ _          ___               _      \ \ \ \
    ( ( )\___ | '_ | '_| | '_ \/ _` |        | _ \___ _ __  ___| |_ ___ \ \ \ \
     \\/  ___)| |_)| | | | | || (_| []::::::[]   / -_) '  \/ _ \  _/ -_) ) ) ) )
      '  |____| .__|_| |_|_| |_\__, |        |_|_\___|_|_|_\___/\__\___|/ / / /
     =========|_|==============|___/===================================/_/_/_/
     :: Spring Boot Remote ::  (v3.4.4)
    
    2025-03-20T13:29:24.223Z  INFO 89132 --- [           main] o.s.b.devtools.RemoteSpringApplication   : Starting RemoteSpringApplication v3.4.4 using Java 17.0.14 with PID 89132 (/Users/myuser/.m2/repository/org/springframework/boot/spring-boot-devtools/3.4.4/spring-boot-devtools-3.4.4.jar started by myuser in /opt/apps/)
    2025-03-20T13:29:24.230Z  INFO 89132 --- [           main] o.s.b.devtools.RemoteSpringApplication   : No active profile set, falling back to 1 default profile: "default"
    2025-03-20T13:29:24.855Z  INFO 89132 --- [           main] o.s.b.d.a.OptionalLiveReloadServer       : LiveReload server is running on port 35729
    2025-03-20T13:29:24.926Z  INFO 89132 --- [           main] o.s.b.devtools.RemoteSpringApplication   : Started RemoteSpringApplication in 1.763 seconds (process running for 2.509)
    

    注意:由于远程客户端使用的类路径与实际应用程序相同,因此它可以直接读取应用程序属性。这就是 spring.devtools.remote.secret 属性被读取并传递到服务器进行身份验证的方式。

    提示:始终建议使用 https:// 作为连接协议,以便对流量进行加密,防止密码被拦截。

    提示:如果你需要使用代理来访问远程应用程序,请配置 spring.devtools.remote.proxy.host 和 spring.devtools.remote.proxy.port 属性。

    # 2、远程更新

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

    在较慢的开发环境中,安静期可能不够,类的更改可能会分成批次。在上传第一批类更改后,服务器会重启。由于服务器正在重启,下一批更改无法发送到应用程序。

    这通常会在 RemoteSpringApplication(请参阅 RemoteSpringApplication (opens new window))日志中显示为一个警告,提示某些类上传失败并随后进行重试。但这也可能导致应用程序代码不一致,并在上传第一批更改后无法重启。如果你经常遇到此类问题,可尝试将 spring.devtools.restart.poll-interval 和 spring.devtools.restart.quiet-period 参数增加到适合你开发环境的值。

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

    # 十八、为生产环境打包应用程序

    当你的 Spring Boot 应用程序准备好进行生产部署时,有多种打包和优化应用程序的方法。请参阅“打包 Spring Boot 应用程序 (opens new window)”部分,以了解这些功能。

    如果你还需要诸如健康检查、审计以及指标 REST 或 JMX 端点等“生产就绪”功能,可以考虑添加 spring-boot-actuator。

    祝你变得更强!

    编辑 (opens new window)
    上次更新: 2025/04/01
    开发你的第一个 Spring Boot 应用程序
    使用 Docker 部署 Spring Boot 应用

    ← 开发你的第一个 Spring Boot 应用程序 使用 Docker 部署 Spring Boot 应用→

    最近更新
    01
    Spring Boot版本新特性
    09-15
    02
    Spring框架版本新特性
    09-01
    03
    开发你的第一个 Spring Boot 应用程序
    08-11
    更多文章>
    Theme by Vdoing | Copyright © 2018-2025 京ICP备2021021832号-2 | MIT License
    • 跟随系统
    • 浅色模式
    • 深色模式
    • 阅读模式