本章节将详细介绍如何使用 Spring Boot. 它覆盖了诸如构建系统、自动配置和如何运行应用等主题. 我们还介绍一些 Spring Boot 最佳实践. 虽然 Spring Boot 并没有什么特别 (它只是另一个您可以使用的类库) ,但仍然有一些建议可以让您的开发工作变得更加容易.

如果您是刚开始使用 Spring Boot,那么在深入本部分之前,您应该先阅读 入门部分 .

1. 构建系统

强烈推荐您选择一个支持依赖管理的构建系统, 您可以使用它将 artifact 发布到 Maven Central 仓库. 我们建议您选择 Maven 或者 Gradle. 虽然可以让 Spring Boot 与其它构建系统 (如 Ant) 配合工作,但它们不会得到特别好的支持.

1.1. 依赖管理

每一次 Spring Boot 发行都提供了一个它所支持的依赖清单. 实际上,您不需要为构建配置提供任何依赖的版本,因为 Spring Boot 已经帮您管理这些了. 当您升级 Spring Boot 时,这些依赖也将以一致的方式进行升级.

如果您觉得有必要,您仍然可以指定一个版本并覆盖 Spring Boot 所推荐的.

该清单包含了全部可以与 Spring Boot 一起使用的 spring 模块以及第三方类库,可作为 标准依赖清单 (spring-boot-dependencies) ,并且可以与 MavenGradle 一起使用.

Spring Boot 的每一次发行都会基于一个 Spring Framework 版本,因此我们强烈建议您不要指定它的版本.

1.2. Maven

Maven 用户可以继承 spring-boot-starter-parent 项目以获取合适的默认值,父项目提供了以下功能:

  • Java 1.8 作为默认编译器.

  • 源代码使用 UTF-8 编码.

  • 依赖管理部分, 继承自 spring-boot-dependencies 的 POM,允许您省略常见依赖的 <version> 标签.

  • 执行 repackage id 重新执行 repackage goal

  • 合理的 资源过滤. .

  • 合适的插件配置 (exec plugin, Git commit ID, and shade).

  • application.propertiesapplication.yml 资源的合理过滤,包括特定 profile 的文件(例如 , application-dev.propertiesapplication-dev.yml)

注意: 由于 application.propertiesapplication.yml 文件接受 Spring 风格的占位符 (${​…​}) ,因此 Maven 改为使用 @..@ 占位符 (您可以使用 Maven 的 resource.delimiter 属性重写它)

1.2.1. 继承 Starter Parent

配置项目继承 spring-boot-starter-parent,只需要按以下方式设置 parent:

<!-- Inherit defaults from Spring Boot -->
<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.2.5.RELEASE</version>
</parent>
您只需要在此依赖上指定 Spring Boot 的版本号. 如果您要导入其它 starter,则可以放心地省略版本号.

通过该设置,您还可以重写自己项目中的配置属性来覆盖个别依赖. 例如,要升级到另一个 Spring Data 发行版本,您需要将以下内容添加到 pom.xml 文件中.

<properties>
    <spring-data-releasetrain.version>Fowler-SR2</spring-data-releasetrain.version>
</properties>
查看 spring-boot-dependencies pom 以获取受支持的属性清单.

1.2.2. 不使用父 POM

不是每个人都喜欢从 spring-boot-starter-parent 继承 POM. 您可能需要使用自己公司标准的父 POM,或者您可能只是希望明确地声明所有 Maven 配置.

如果您不想使用 spring-boot-starter-parent,则仍然可以通过使用 scope=import 依赖来获得依赖管理 (但不是插件管理) 的好处:

<dependencyManagement>
    <dependencies>
        <dependency>
            <!-- Import dependency management from Spring Boot -->
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-dependencies</artifactId>
            <version>2.2.5.RELEASE</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

如上所述,上述示例设置不会让您使用属性来覆盖个别依赖. 要达到相同的目的,需要在 spring-boot-dependencies 项之前在项目的 dependencyManagement 中添加一项. 例如,要升级到另一个 Spring Data 发行版,您可以将以下元素添加到 pom.xml 中:

<dependencyManagement>
    <dependencies>
        <!-- Override Spring Data release train provided by Spring Boot -->
        <dependency>
            <groupId>org.springframework.data</groupId>
            <artifactId>spring-data-releasetrain</artifactId>
            <version>Fowler-SR2</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-dependencies</artifactId>
            <version>2.2.5.RELEASE</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>
以上示例中,我们指定了一个 BOM,但是任何的依赖类型都可以用这个方法来重写.

1.2.3. 使用 Spring Boot Maven 插件

Spring Boot 包括了一个 Maven 插件 ,它可以将项目打包成一个可执行 jar. 如果要使用它,请将插件添加到您的 <plugins> 中:

<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
        </plugin>
    </plugins>
</build>
如果您使用了 Spring Boot starter 的父 pom,则只需要添加插件. 除非您要修改父级中定义的设置,否则不需要进行配置.

1.3. Gradle

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

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="2.2.5.RELEASE" />

    <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 模块,请参阅 使用 Ant 构建可执行归档文件,无需使用 spring-boot-antlib.

1.5. Starters

Starter 是一组惯例依赖描述资源,可以包含在应用中. 从 starter 中,您可以获得所需的所有 Spring 和相关技术的一站式支持,无须通过示例代码和复制粘贴来获取依赖. 比如,如果您要使用 Spring 和 JPA 进行数据库访问,那么只需要在项目中包含 spring-boot-starter-data-jpa 依赖即可.

starter 包含了许多您需要用于使项目快速启动和运行,并且需要一组受支持的可传递依赖关系的依赖.

命名含义

官方的所有 starter 都遵循类似的命名规则: spring-boot-starter-,其中 是特定类型的应用. 这个命名结构旨在帮助您找到 starter. 许多 IDE 中 Maven 集成允许您按名称搜索依赖. 例如,安装了 Eclipse 或者 STS 插件后,您可以简单地在 POM 编辑器中按下 ctrl-space 并输入 spring-boot-starter 来获取完整的列表.

正如 “创建自己的 starter” 章节所述,第三方的 starter 命名不应该以 spring-boot 开头,因为它是官方 Spring Boot 构件所保留的规则. 例如,有一个第三方 starter 项目叫做 thirdpartyproject,它通常会命名为 thirdpartyproject-spring-boot-starter.

Spring Boot 在 org.springframework.boot group 下提供了以下应用 starter:

Table 1. Spring Boot 应用类 Starter
Name Description Pom

spring-boot-starter

Core starter, including auto-configuration support, logging and YAML

Pom

spring-boot-starter-activemq

Starter for JMS messaging using Apache ActiveMQ

Pom

spring-boot-starter-amqp

Starter for using Spring AMQP and Rabbit MQ

Pom

spring-boot-starter-aop

Starter for aspect-oriented programming with Spring AOP and AspectJ

Pom

spring-boot-starter-artemis

Starter for JMS messaging using Apache Artemis

Pom

spring-boot-starter-batch

Starter for using Spring Batch

Pom

spring-boot-starter-cache

Starter for using Spring Framework’s caching support

Pom

spring-boot-starter-cloud-connectors

Starter for using Spring Cloud Connectors which simplifies connecting to services in cloud platforms like Cloud Foundry and Heroku. Deprecated in favor of Java CFEnv

Pom

spring-boot-starter-data-cassandra

Starter for using Cassandra distributed database and Spring Data Cassandra

Pom

spring-boot-starter-data-cassandra-reactive

Starter for using Cassandra distributed database and Spring Data Cassandra Reactive

Pom

spring-boot-starter-data-couchbase

Starter for using Couchbase document-oriented database and Spring Data Couchbase

Pom

spring-boot-starter-data-couchbase-reactive

Starter for using Couchbase document-oriented database and Spring Data Couchbase Reactive

Pom

spring-boot-starter-data-elasticsearch

Starter for using Elasticsearch search and analytics engine and Spring Data Elasticsearch

Pom

spring-boot-starter-data-jdbc

Starter for using Spring Data JDBC

Pom

spring-boot-starter-data-jpa

Starter for using Spring Data JPA with Hibernate

Pom

spring-boot-starter-data-ldap

Starter for using Spring Data LDAP

Pom

spring-boot-starter-data-mongodb

Starter for using MongoDB document-oriented database and Spring Data MongoDB

Pom

spring-boot-starter-data-mongodb-reactive

Starter for using MongoDB document-oriented database and Spring Data MongoDB Reactive

Pom

spring-boot-starter-data-neo4j

Starter for using Neo4j graph database and Spring Data Neo4j

Pom

spring-boot-starter-data-redis

Starter for using Redis key-value data store with Spring Data Redis and the Lettuce client

Pom

spring-boot-starter-data-redis-reactive

Starter for using Redis key-value data store with Spring Data Redis reactive and the Lettuce client

Pom

spring-boot-starter-data-rest

Starter for exposing Spring Data repositories over REST using Spring Data REST

Pom

spring-boot-starter-data-solr

Starter for using the Apache Solr search platform with Spring Data Solr

Pom

spring-boot-starter-freemarker

Starter for building MVC web applications using FreeMarker views

Pom

spring-boot-starter-groovy-templates

Starter for building MVC web applications using Groovy Templates views

Pom

spring-boot-starter-hateoas

Starter for building hypermedia-based RESTful web application with Spring MVC and Spring HATEOAS

Pom

spring-boot-starter-integration

Starter for using Spring Integration

Pom

spring-boot-starter-jdbc

Starter for using JDBC with the HikariCP connection pool

Pom

spring-boot-starter-jersey

Starter for building RESTful web applications using JAX-RS and Jersey. An alternative to spring-boot-starter-web

Pom

spring-boot-starter-jooq

Starter for using jOOQ to access SQL databases. An alternative to spring-boot-starter-data-jpa or spring-boot-starter-jdbc

Pom

spring-boot-starter-json

Starter for reading and writing json

Pom

spring-boot-starter-jta-atomikos

Starter for JTA transactions using Atomikos

Pom

spring-boot-starter-jta-bitronix

Starter for JTA transactions using Bitronix

Pom

spring-boot-starter-mail

Starter for using Java Mail and Spring Framework’s email sending support

Pom

spring-boot-starter-mustache

Starter for building web applications using Mustache views

Pom

spring-boot-starter-oauth2-client

Starter for using Spring Security’s OAuth2/OpenID Connect client features

Pom

spring-boot-starter-oauth2-resource-server

Starter for using Spring Security’s OAuth2 resource server features

Pom

spring-boot-starter-quartz

Starter for using the Quartz scheduler

Pom

spring-boot-starter-rsocket

Starter for building RSocket clients and servers.

Pom

spring-boot-starter-security

Starter for using Spring Security

Pom

spring-boot-starter-test

Starter for testing Spring Boot applications with libraries including JUnit, Hamcrest and Mockito

Pom

spring-boot-starter-thymeleaf

Starter for building MVC web applications using Thymeleaf views

Pom

spring-boot-starter-validation

Starter for using Java Bean Validation with Hibernate Validator

Pom

spring-boot-starter-web

Starter for building web, including RESTful, applications using Spring MVC. Uses Tomcat as the default embedded container

Pom

spring-boot-starter-web-services

Starter for using Spring Web Services

Pom

spring-boot-starter-webflux

Starter for building WebFlux applications using Spring Framework’s Reactive Web support

Pom

spring-boot-starter-websocket

Starter for building WebSocket applications using Spring Framework’s WebSocket support

Pom

除了应用 starter,以下 starter 可用于添加 生产就绪 特性:

Table 2. Spring Boot 生产类 starter
Name Description Pom

spring-boot-starter-actuator

Starter for using Spring Boot’s Actuator which provides production ready features to help you monitor and manage your application

Pom

最后,Spring Boot 还包含以下 starter,如果您想要排除或切换特定技术,可以使用以下 starter:

Table 3. Spring Boot 技术类 starter
Name Description Pom

spring-boot-starter-jetty

Starter for using Jetty as the embedded servlet container. An alternative to spring-boot-starter-tomcat

Pom

spring-boot-starter-log4j2

Starter for using Log4j2 for logging. An alternative to spring-boot-starter-logging

Pom

spring-boot-starter-logging

Starter for logging using Logback. Default logging starter

Pom

spring-boot-starter-reactor-netty

Starter for using Reactor Netty as the embedded reactive HTTP server.

Pom

spring-boot-starter-tomcat

Starter for using Tomcat as the embedded servlet container. Default servlet container starter used by spring-boot-starter-web

Pom

spring-boot-starter-undertow

Starter for using Undertow as the embedded servlet container. An alternative to spring-boot-starter-tomcat

Pom

有关其它社区贡献的 starter 列表,请参阅 GitHub 上的 spring-boot-starters 模块中的 README file 文件.

2. 组织代码

Spring Boot 不需要任何特定的代码布局,但是有一些最佳实践是很有用的.

2.1. 使用 “default” 包

当一个类没有 package 声明时,它就被认为是在 default 包中. 通常不鼓励使用 default 包,应该避免使用. 对于使用 @ComponentScan@EntityScan 或者 @SpringBootApplication 注解的 Spring Boot 应用,这样可能会导致特殊问题发生, 因为每一个 jar 中的每一个类将会被读取到.

我们建议您使用 Java 推荐的包命名约定,并使用域名的反向形式命名 (例如 com.example.project) .

2.2. 定位主应用类

我们通常建议您将主应用类放在其它类之上的根包中, @SpringBootApplication 注解 注解通常放在主类上,它隐式定义了某些项目的 包搜索的基准起点. 例如,如果您在编写一个 JPA 应用程序,则被 @SpringBootApplication 注解的类所属的包将被用于搜索标记有 @Entity 注解的类.

使用根包还可以允许使用没有指定 basePackage 属性的 @ComponentScan 注解. 如果您的主类在根包中,也可以使用 @SpringBootApplication 注解.

如果您不想使用 @SpringBootApplication,则可以通过导入的 @EnableAutoConfiguration@ComponentScan 注解来定义该行为,因此也可以使用它们.

以下是一个经典的包结构:

com
 +- example
     +- myapplication
         +- Application.java
         |
         +- customer
         |   +- Customer.java
         |   +- CustomerController.java
         |   +- CustomerService.java
         |   +- CustomerRepository.java
         |
         +- order
             +- Order.java
             +- OrderController.java
             +- OrderService.java
             +- OrderRepository.java

Application.java 文件声明了 main 方法,附带了 @SpringBootApplication 注解.

package com.example.myapplication;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class Application {

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

}

3. 配置类

Spring Boot 支持基于 Java 的配置. 虽然可以在 SpringApplication 中使用 XML 配置源,但我们通常建议主配置源为 @Configuration 类. 通常,一个很好的选择是将定义了 main 方法的类作为 @Configuration.

许多 Spring 的 XML 配置示例已经在 Internet 上发布了. 如果可能的话,您无论如何都应该尝试着使用等效的基于 Java 的配置方式,搜索 Enable* 注解可以帮到您不少忙.

3.1. 导入额外的配置类

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

3.2. 导入 XML 配置

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

4. 自动配置

Spring Boot 自动配置尝试根据您添加的 jar 依赖自动配置 Spring 应用. 例如,如果 classpath 下存在 HSQLDB,并且您没有手动配置任何数据库连接 bean,那么 Spring Boot 将自动配置一个内存数据库.

您需要通过将 @EnableAutoConfiguration 或者 @SpringBootApplication 注解添加到其中一个 @Configuration 类之上以启用自动配置.

您应该只添加一个 @SpringBootApplication@EnableAutoConfiguration 注解. 我们通常建议您仅将一个或另一个添加到您的主要 @Configuration 类中.

4.1. 平滑替换自动配置

自动配置是非入侵的,您可以随时定义自己的配置来代替自动配置的特定部分. 例如,如果您添加了自己的 DataSource bean,默认的嵌入式数据库支持将不会自动配置.

如果您需要了解当前正在应用的自动配置,以及为什么使用,请使用 --debug 开关启动应用. 这样做可以为核心 logger 启用调试日志,并记录到控制台.

4.2. 禁用指定的自动配置类

如果您发现在正在使用不需要的自动配置类,可以通过使用 @SpringBootApplicationexclude 属性来禁用它们.

import org.springframework.boot.autoconfigure.*;
import org.springframework.boot.autoconfigure.jdbc.*;

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

如果类不在 classpath 下,您可以使用注解的 excludeName 属性并指定完全类名. 最后,您还可以通过 spring.autoconfigure.exclude property 控制要排除的自动配置类列表.

如果您更喜欢使用 @EnableAutoConfiguration 而不是 @SpringBootApplication ,则还可以使用 excludeexcludeName.

您可以同时使用注解和 property 定义排除项
即使自动配置类是 public 的,该类的被认为是 public API的唯一方面是可用于禁用自动配置的类的名称. 这些类的实际内容 (例如嵌套配置类或Bean方法) 仅供内部使用,我们不建议直接使用它们. ,

5. Spring Bean 与依赖注入

您可以自由使用任何标准的 Spring Framework 技术来定义您的 bean 以及它们注入的依赖. 我们发现使用 @ComponentScan 来寻找 bean 和结合 @Autowired 构造器注入可以很好地工作.

如果您按照上述的建议 (将应用类放在根包中) 来组织代码,则可以添加无参的 @ComponentScan. 所有应用组件 (@Component@Service@Repository@Controller 等) 将自动注册为 Spring Bean.

以下是一个 @Service Bean,其使用构造注入方式获取一个必需的 RiskAssessor bean.

package com.example.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class DatabaseAccountService implements AccountService {

    private final RiskAssessor riskAssessor;

    @Autowired
    public DatabaseAccountService(RiskAssessor riskAssessor) {
        this.riskAssessor = riskAssessor;
    }

    // ...

}

如果 bean 中只有一个构造方法,您可以忽略掉 @Autowired 注解.

@Service
public class DatabaseAccountService implements AccountService {

    private final RiskAssessor riskAssessor;

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

    // ...

}
请注意,构造注入允许 riskAssessor 字段被修饰为 final,这表示以后它不能被更改.

6. 使用 @SpringBootApplication 注解

很多 Spring Boot 开发者总是使用 @Configuration@EnableAutoConfiguration@ComponentScan 注解标记在主类上. 由于 这些注解经常一起使用 (特别是如果您遵循上述的最佳实践) . Spring Boot 提供了一个更方便的 @SpringBootApplication 注解可用来替代这个组合.

package com.example.myapplication;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication // same as @Configuration @EnableAutoConfiguration @ComponentScan
public class Application {

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

}
@SpringBootApplication 还提供别名以自定义 @EnableAutoConfiguration@ComponentScan 的属性.

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

package com.example.myapplication;

import org.springframework.boot.SpringApplication;
import org.springframework.context.annotation.ComponentScan
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;

@Configuration(proxyBeanMethods = false)
@EnableAutoConfiguration
@Import({ MyConfig.class, MyAnotherConfig.class })
public class Application {

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

}

在此示例中,除了程序没有自动检测到 @Component 注解的类和 @ConfigurationProperties 注解的类和显式导入了用户定义的Bean之外,Application 就像其他任何Spring Boot应用程序一样 (请参阅 @Import) .

7. 运行您的应用

将应用程序打包成 jar 可执行文件并使用嵌入式 HTTP 服务器的最大有点之一就是可以按照您想使用的其它方式来运行应用. 调试 Spring Boot 也是很简单,您不需要任何特殊的 IDE 插件或者扩展.

本章节仅涵盖基于 jar 的打包方式,如果您选择将应用打包为 war 文件,则应该参考您的服务器和 IDE 文档.

7.1. 使用 IDE 运行

您可以使用 IDE 运行 Spring Boot应用,就像运行一个简单的 Java 应用程序一样,但是首先您需要导入项目,导入步骤取决于您的 IDE 和构建系统. 大多数 IDE 可以直接导入 Maven 项目,例如 Eclipse 用户可以从 File 菜单中选择 Import…​Existing Maven Projects .

如果您无法将项目直接导入到 IDE 中,则可以使用构建插件生成 IDE 元数据 (metadata) . Maven 包含了 EclipseIDEA 的插件,Gradle 也为 各种 IDE 提供了插件.

如果您不小心运行了两次 web 应用,您将看到一个 Port already in use (端口已经被使用) 错误. STS 用户可以使用 Relaunch 按钮运行以确保现有的任何实例都已关闭,而不是使用 Run 按钮.

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 插件包含一个可用于快速编译和运行应用程序的 run goal. 应用程序以快速形式运行,就像在 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 模块包含了对快速重新启动应用程序的支持. 有关详细信息,请参阅本章后面的 开发人员工具部分以及热插拔的 How-to 部分.

8. 开发者工具

Spring Boot 包含了一套工具,可以使应用开发体验更加愉快. spring-boot-devtools 模块可包含在任何项目中,以提供额外的开发时 (development-time) 功能. 要启用 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")
}
当运行完全打包的应用时,开发者工具将会自动禁用. 如果您的应用使用了 java -jar 方式或者特殊的类加载器启动,那么它会被认为是一个生产级别应用. 如果这不适用于您 (即,如果您从容器中运行应用程序) ,请考虑排除 devtools 或设置 -Dspring.devtools.restart.enabled = false 系统属性.
将 Maven 的依赖标记为可选或者在 Gradle 中使用 developmentOnly 是防止您的项目被其他模块使用时 devtools 被应用到其它模块的最佳方法.
重新打包的归档默认情况下不包含 devtools. 如果要使用某些远程 devtools 功能, 你需要禁用 excludeDevtools 构建属性以把 devtools 包含进来. 该属性支持 Maven 和 Gradle 插件.

8.1. Property 默认值

Spring Boot 所支持的一些库使用了缓存来提高性能. 例如, 模板引擎 将缓存编译后的模板,以避免重复解析模板文件. 此外,Spring MVC 可以在服务静态资源时添加 HTTP 缓存头.

虽然缓存在生产中非常有用,但它在开发过程可能会产生相反的效果,让您不能及时看到刚才在应用中作出的更改. 因此,spring-boot-devtools 将默认禁用这些缓存选项.

一般是在 application.properties 文件中设置缓存选项. 例如,Thymeleaf 提供了 spring.thymeleaf.cache 属性. 您不需要手动设置这些属性,spring-boot-devtools 会自动应用合适的开发时 (development-time) 配置.

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

如果您不希望应用默认属性,则可以在 application.properties 中将 spring.devtools.add-properties 设置为 false.
有关devtools应用的属性的完整列表,请参见 DevToolsPropertyDefaultsPostProcessor. .

8.2. 自动重启

使用 spring-boot-devtools 的应用在 classpath 下的文件发生更改时会自动重启. 这对于使用 IDE 工作而言可能是一个非常棒的功能,因为它为代码变更提供了非常快的反馈. 默认情况下,将监视 classpath 指向的所有文件夹. 请注意,某些资源 (如静态资源和视图模板) 不需要重启应用.

触发重启

当 DevTools 监视 classpath 资源时,触发重启的唯一方式是更新 classpath. 使 classpath 更新的方式取决于您使用的 IDE. 在 Eclipse 中,保存修改的文件将更新 classpath,从而触发重启. 在 IntelliJ IDEA 中,构建项目 (Build → Make Project) 将产生相同的效果.

只要 forking 被开启,您可以使用受支持的构建工具 (如 Maven 或 Gradle) 来启用应用,因为 DevTools 需要隔离应用类加载器才能正常运行. 默认情况下,当在 classpath 下检测到 DevTools 时,Gradle 和 Maven 会这么做.
自动重启功能与 LiveReload (实时重载) 一起使用效果更棒. 阅读 LiveReload 章节以获取更多信息. 如果您使用 JRebel,自动重启将会被禁用,以支持动态类重载,但其他 devtools 功能 (如 LiveReload 和 property 覆盖) 仍然可以使用.
DevTools 依赖于应用上下文的关闭钩子,以在重启期间关闭自己. 如果禁用了关闭钩子 (SpringApplication.setRegisterShutdownHook(false) ) ,它将不能正常工作.
当 classpath 下的内容发生更改,决定是否触发重启时,DevTools 会自动忽略名为 spring-boot, spring-boot-devtools, spring-boot-autoconfigure, spring-boot-actuator, 和 spring-boot-starter 的项目.
DevTools 需要自定义 ApplicationContext 使用到的 ResourceLoader. 如果您的应用已经提供了一个,它将被包装起来,因为不支持在 ApplicationContext 上直接覆盖 getResource 方法.
重启 (Restart) 与重载 (Reload)

Spring Boot 通过使用两个类加载器来提供了重启技术. 不改变的类 (例如,第三方 jar) 被加载到 base 类加载器中. 经常处于开发状态的类被加载到 restart 类加载器中. 当应用重启时,restart 类加载器将被丢弃,并重新创建一个新的. 这种方式意味着应用重启比冷启动要快得多,因为省去 base 类加载器的处理步骤,并且可以直接使用.

如果您觉得重启还不够快,或者遇到类加载问题,您可以考虑如 ZeroTurnaround 的 JRebel 等工具. 他们是通过在加载类时重写类来加快重新加载.

8.2.1. 条件评估变更日志

默认情况下,每次应用重启时,都会记录显示条件评估增量的报告. 该报告展示了在您进行更改 (如添加或删除 bean 以及设置配置属性) 时对应用自动配置所作出的更改.

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

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

8.2.2. 排除资源

某些资源在更改时不一定需要触发重启. 例如,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/**
如果要保留这些默认值并添加其他排除项 ,请改用 spring.devtools.restart.additional-exclude 属性.

8.2.3. 监视附加路径

如果您想在对不在 classpath 下的文件进行修改时重启或重载应用,请使用 spring.devtools.restart.additional-paths 属性来配置监视其他路径的更改情况. 您可以使用上述spring.devtools.restart.exclude 属性来控制附加路径下的文件被修改时是否触发重启或只是 live reload.

8.2.4. 禁用重启

您如果不想使用重启功能,可以使用 spring.devtools.restart.enabled 属性来禁用它. 一般情况下,您可以在 application.properties 中设置此属性 (重启类加载器仍将被初始化,但不会监视文件更改) .

如果您需要完全禁用重启支持 (例如,可能它不适用于某些类库) ,您需要在调用 SpringApplication.run(​…​) 之前将 System 属性 spring.devtools.restart.enabled System 设置为 false. 例如:

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

8.2.5. 使用触发文件

如果您使用 IDE 进行开发,并且时时刻刻在编译更改的文件,或许您只是希望在特定的时间内触发重启. 为此,您可以使用触发文件,这是一个特殊文件,您想要触发重启检查时,必须修改它.

更改文件只会触发检查,只有在 Devtools 检查到它需要做某些操作时才会触发重启,可以手动更新触发文件,也可以通过 IDE 插件更新.

要使用触发文件,请设置 spring.devtools.restart.trigger-file 属性指向触发文件的路径.

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

src
+- main
   +- resources
      +- .reloadtrigger

然后,您的触发文件属性将是:

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

现在仅在更新 src/main/resources/.reloadtrigger 时才发生重启.

您也许想将 spring.devtools.restart.trigger-file 设置成一个全局配置,以使得所有的项目都能应用此方式.

某些IDE具有使您不必手动更新触发器文件的功能. Spring Tools for Eclipse 的Spring工具和 IntelliJ IDEA (Ultimate Edition) 都具有这种支持. 使用Spring Tools, 您可以从控制台视图使用 "重新加载" 按钮 (只要您的 trigger-file 名为 .reloadtrigger) . 对于IntelliJ,您可以按照其 文档中的说明 进行操作.

8.2.6. 自定义重启类加载器

正如之前的 重启和重载 部分所述,重启功能是通过使用两个类加载器来实现的. 对于大多数应用而言,这种方式很好,然而,有时可能会导致类加载出现问题.

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

spring-devtools.properties 文件可以包含以 restart.exclude. 和 restart.include. 为前缀的属性. include 元素是加载到 restart 类加载器的项,exclude 元素是加载到 “base” 类加载器的项. 属性值是一个应用到 classpath 的正则表达式. 例如:

restart.exclude.companycommonlibs=/mycorp-common-[\\w\\d-\.]+\.jar
restart.include.projectcommon=/mycorp-myproj-[\\w\\d-\.]+\.jar
所有属性键名必须是唯一的. 只要有一个属性以 restart.include. 或 restart.exclude. 开头,它将会被考虑.
classpath 下的所有 META-INF/spring-devtools.properties 文件将被加载,您可以将它们打包进工程或者类库中为项目所用.

8.2.7. 已知限制

重新启动功能对使用标准 ObjectInputStream 反序列化的对象无效. 您如果需要反序列化数据,可能需要使用 Spring 的 ConfigurableObjectInputStream 配合 Thread.currentThread().getContextClassLoader().

遗憾的是,一些第三方类库在没有考虑上下文类加载器的情况下使用了反序列化. 您如果遇到此问题,需要向原作者提交修复请求.

8.3. LiveReload

spring-boot-devtools 模块包括了一个内嵌 LiveReload 服务器,它可在资源发生更改时触发浏览器刷新. 您可以从 livereload.com 上免费获取 Chrome、Firefox 和 Safari 平台下对应的 LiveReload 浏览器扩展程序.

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

您一次只能运行一个 LiveReload 服务器. 在启动应用之前,请确保没有其他 LiveReload 服务器正在运行. 如果在 IDE 中启动了多个应用,那么只有第一个应用的 LiveReload 生效.

8.4. 全局设置

您可以通过将以下任何文件添加到 $HOME/.config/spring-boot 文件夹来配置全局devtools设置:

  1. spring-boot-devtools.properties

  2. spring-boot-devtools.yaml

  3. spring-boot-devtools.yml

在此文件中添加的任何属性将应用到您的计算机上所有使用了 devtools 的 Spring Boot 应用. 例如,始终使用触发文件来配置重启功能,您可以添加以下内容:

~/.config/spring-boot/spring-boot-devtools.properties
spring.devtools.restart.trigger-file=.reloadtrigger
如果在 $HOME/.config/spring-boot 中找不到devtools配置文件,则在$ HOME文件夹的根目录中搜索是否存在 .spring-boot-devtools.properties 文件. 这使您可以与不支持 $HOME/.config/spring-boot 位置的较旧版本的Spring Boot上的应用程序共享devtools全局配置.
在上述文件中激活的配置文件不会影响 指定 profile 的配置文件的加载. .

8.5. 远程应用

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

8.5.1. 运行远程客户端应用

假设远程客户端应用运行在 IDE 中. 您需要在与要连接的远程项目相同的 classpath 下运行 org.springframework.boot.devtools.RemoteSpringApplication . 把要连接的远程 URL 作为必须参数传入.

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

  • Run 菜单中选择选择 Run Configurations…​​.

  • 创建一个新的 Java Application “launch configuration”.

  • 浏览 my-app 项目.

  • 使用 org.springframework.boot.devtools.RemoteSpringApplication 作为主类.

  • https://myapp.cfapps.io 作为 Program arguments (或者任何远程 URL) 传入.

运行的远程客户端将如下所示:

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

2015-06-10 18:25:06.632  INFO 14938 --- [           main] o.s.b.devtools.RemoteSpringApplication   : Starting RemoteSpringApplication on pwmbp with PID 14938 (/Users/pwebb/projects/spring-boot/code/spring-boot-project/spring-boot-devtools/target/classes started by pwebb in /Users/pwebb/projects/spring-boot/code)
2015-06-10 18:25:06.671  INFO 14938 --- [           main] s.c.a.AnnotationConfigApplicationContext : Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@2a17b7b6: startup date [Wed Jun 10 18:25:06 PDT 2015]; root of context hierarchy
2015-06-10 18:25:07.043  WARN 14938 --- [           main] o.s.b.d.r.c.RemoteClientConfiguration    : The connection to http://localhost:8080 is insecure. You should use a URL starting with 'https://'.
2015-06-10 18:25:07.074  INFO 14938 --- [           main] o.s.b.d.a.OptionalLiveReloadServer       : LiveReload server is running on port 35729
2015-06-10 18:25:07.130  INFO 14938 --- [           main] o.s.b.devtools.RemoteSpringApplication   : Started RemoteSpringApplication in 0.74 seconds (JVM running for 1.105)
由于远程客户端与实际应用使用的是同一个 classpath,因此可以直接读取应用的 properties. 这也是 spring.devtools.remote.secret 属性为什么能被读取和传递给服务器进行身份验证的原因.
建议使用 https:// 作为连接协议,以便加密传输并防止密码被拦截.
如果您需要通过代理来访问远程应用,请配置 spring.devtools.remote.proxy.hostspring.devtools.remote.proxy.port 属性.

8.5.2. 远程更新

远程客户端使用了与本地重启相同的方式来监控应用 classpath 下发生的更改. 任何更新的资源将被推送到远程应用和触发重启 (如果要求) . 如果您正在迭代一个使用了本地没有的云服务的功能,这可能会非常有用. 通常远程更新和重启比完全重新构建和部署的周期要快得多.

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

8.5.3. 配置文件系统监视器

FileSystemWatcher 的工作方式是按一定的时间间隔轮询类更改,然后等待预定义的静默期以确保没有更多更改. 然后将更改上传到远程应用程序. 在较慢的开发环境中,可能会发生静默期不够的情况,并且类中的更改可能会分为几批. 第一批类更改上传后,服务器将重新启动. 由于服务器正在重新启动,因此下一批不能发送到应用程序.

这通常通过 RemoteSpringApplication 日志中的警告来证明,即有关上载某些类失败的消息,然后进行重试. 但是,这也可能导致应用程序代码不一致,并且在上传第一批更改后无法重新启动.

如果您经常观察到此类问题,请尝试将 spring.devtools.restart.poll-intervalspring.devtools.restart.quiet-period 参数增加到适合您的开发环境的值:

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

现在每2秒轮询一次受监视的classpath文件夹以进行更改,并保持1秒钟的静默时间以确保没有其他类更改.

9. 打包生产应用

可执行 jar 可用于生产部署,它们是独立 (self-contained,独立、自包含) 的,同样也适合云部署.

针对其他生产就绪功能,比如健康、审计和 REST 或者 JMX 端点指标,可以添加 spring-boot-actuator. 有关这方面的详细信息,请参见 Spring Boot Actuator: 生产就绪功能 .

10. 下一步

您现在应该知道如何使用 Spring Boot 以及应该遵循哪些最佳实践. 接下来您可以深入地了解 Spring Boot 特性,或者您也可以跳过下一部分直接阅读 “生产就绪功能” 方面的内容.