翻译《Spring Boot Reference Guide》-第三单元.使用SpringBoot
第三单元.使用SpringBoot
本节旨在全面介绍SpringBoot的应用与开发流程。涵盖的内容包括构建系统架构、实现自动配置功能以及指导应用程序的部署方法。此外,我们还将分享一些最佳实践指南以助于开发者高效利用该框架。
尽管说SpringBoot并非特别突出(它只是一个功能丰富的库工具),但是一些实用建议值得学习。
遵循这些建议能帮助你提升开发效率和便捷性。
当你首次接触SpringBoot时
13. 构建系统
我们郑重推荐您选择一个构建平台,并提供通过发布至“MavenCentral”仓库下载工程包的能力。
具体来说,请考虑采用 Maven 或 Gradle 这两种工具。
不可忽视的是, Spring Boot 也兼容其他构建工具如 Ant,
但目前并未获得广泛的支持。
13.1 依赖管理
每个正式版本的SpringBoot都会列出其支持的一份精选依赖关系。事实上,在构建配置文档时无需提供任何版本号给依赖项——因为SpringBoot会自动处理这一点。当升级到新的SpringBoot版本时,默认情况下这些被选中的组件也会同步升级。
如果你需要,你可以指定版本来覆盖SpringBoot建议的版本。
精选材料集包含了所有支持Spring Boot集成的官方组件集合,并附带经过筛选的第三方库集合。同时支持Maven和Gradle开发的组件汇总
每个正式版本SpringBoot都与基础版本的SpringFramework相关联。强烈建议您不指定其版本号。
13.2 Maven
Maven用户可继承spring-boot-starter-parent项目从而实现合适的默认设置。该父项目包含以下功能特性:
- 默认采用Java 1.8版本
- 源码编码格式固定为UTF-8
- 提供一个基于Spring Boot的依赖管理模块,用于统一管理和版本控制公共依赖项。当在个人项目POM中集成时,默认会过滤掉这些组件标识符。
- 通过Repackage技术完成可执行目标
- 支持智能资源过滤和插件配置(包括exec插件、Git Commit ID以及共享功能)
- 对application.properties及应用.yml文件中的特定配置文件(如application-dev.properties等)提供智能过滤功能。
请记住自自自自自自自自自自自自自自自自从从从from从fromfromfromfromfromfromfromfromfrom application.properties和application.yml文件开始采用(${})这种格式进行占位符处理之后之后之后之后之后之后之后之后之前之前之前之前之前Maven会过滤后采用(@…@)这种格式来进行占位符替代工作如果你希望对此进行个性化配置可以选择性地修改某些参数以覆盖掉默认设定
13.2.1 继承自Starter Parent
为了使你的项目基于spring-boot-starter-parent进行设置,请具体设置方式如下:
<!-- Inherit defaults from Spring Boot -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.5.RELEASE</version>
</parent>
代码解释
你必须在这个依赖中指定SpringBoot版本。如果导入其他启动器,则无需担心版本问题。
当采用该配置时,您可以通过包裹自身项目的属性来包裹所有相关依赖项。例如,在您的POM文件中添加以下内容即可实现升级操作:
<properties>
<spring-data-releasetrain.version>Fowler-SR2</spring-data-releasetrain.version>
</properties>
代码解释
查看spring-boot-dependencies-pom中所包含的支持信息列表。
13.2.2 在没有Parent Pom下使用SpringBoot
并不是所有人都偏爱继承spring-boot-starter-parent-POM。或许你可以考虑采用你们公司的定制化的Parent POM以满足特定需求;或者你可以明确声明所有的Maven配置参数以避免潜在的问题。
假如你不愿意选择Spring-Boot Starter-Parent组件包,则可以通过dependencyManagement(非插件化管理)来获得相应的便利,并采用scope=import语法结构来配置依赖项,请问是否还有其他问题?
<dependencyManagement>
<dependencies>
<dependency>
<!-- Import dependency management from Spring Boot -->
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.1.5.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
代码解释
如上所述,在之前的示例步骤中并未要求您使用属性来覆盖个别依赖项。为了以相同的效果实现目标,请您在您的项目中添加dependencyManagement依赖项,并确保它位于spring-boot-dependencies依赖之前配置。如需升级springDataReleasetrain,请将以下内容添加到您的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.1.5.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
代码解释
在之前的案例中,我们采用了BOM方案,然而在某些特殊情况下,则可以选择一种统一的方式来覆盖所有类型的依赖项类型
13.2.3 使用SpringBoot Maven插件
SpringBoot拥有一个用于打包项目生成可执行jar包的Maven插件。如果你需要使用这个工具,请将该插件添加到你的工作流程中,并参考以下展示的具体用法:
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
代码解释
当采用spring-boot-starter-parent-pom时,则只需执行插件的添加操作。无需进行任何配置工作,除非你希望更改父配置参数。
13.3 Gradle
建议查阅关于集成使用Spring Boot与Gradle的相关信息,请参考Spring Boot Gradle插件文档。
13.4 Ant
支持使用Apache Ant与Ivy搭建SpringBoot工程。其中spring-boot-antlib组件中的antlib插件能够生成可执行的JAR文件以供Ant工具调用。
为了声明依赖关系,典型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.1.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模块,请参考Section 91.9, "Build an Executable Archive from Ant without Using spring-boot-antlib"
13.5 启动器
启动器可被视为一组便于管理的依赖关系集合,在软件开发中扮演着关键角色。整合这些工具到应用中是一个便捷的选择方式。通过集成一次性获取完整的Spring框架及相关技术方案,则无需手动查找示例代码或复制粘贴相关组件的描述信息。特别地,在涉及数据库访问的应用场景下,默认配置通常已经满足需求:只需将Spring Boot Starter Data JPA插件导入项目中作为基础配置项即可完成所需功能的初始化设置
启动器由多个组件构成,并能同时执行大量项目的初始化操作。该系统具备高度一致的一致性机制,并且能够有效地管理复杂的传递性依赖关系。
名字叫什么
所有官方启动器均遵循相同的命名规律; spring-boot-starter-... ,其中 ... 代表不同类型的程序。这种命名规范能在你需寻找相应启动器时提供便利指导。Maven这一功能广泛应用于各种集成开发环境(IDE),能够让你通过名称快速查找所需依赖项。具体情况下,在安装了合适的Eclipse或其他STS插件后,在项目配置管理工具(POM)界面按下Ctrl+Space键并输入'spring-boot-starter'即可获取完整的启动器列表。
如创建自定义启动器部分所示,在官方提供的 springboot 工具包库中,默认配置可能不会直接使用 spring-boot 作为前缀的第三方启动器存在这一设计限制。相反地,在大多数情况下,默认配置会采用项目名称作为前缀的方式来实现类似的功能。例如,在一个常见的第三方启动器项目中(如 thirdpartyproject),其常见命名方式为 thirdpartyproject-spring-boot-starter
SpringBoot位于该组织的org.springframework.boot组中,并且支持了以下应用程序启动器
| Name | Description | Pom |
|---|---|---|
| spring-boot-starter | 核心启动器,包括支持自动配置,日志记录和YAML | Pom |
| spring-boot-starter-activemq | 使用Apache ActiveMQ的JMS消息通知启动器 | Pom |
| spring-boot-starter-amqp | 使用Spring AMQP和Rabbit MQ的启动器 | Pom |
| spring-boot-starter-aop | 使用Spring AOP和AspectJ进行面向切面编程的启动器 | Pom |
| spring-boot-starter-artemis | 使用Apache Artemis的JMS消息通知启动器 | Pom |
| spring-boot-starter-batch | 使用Spring Batch的启动器 | Pom |
| spring-boot-starter-cache | 使用Spring Framework缓存支持的启动器 | Pom |
| spring-boot-starter-cloud-connectors | 使用Spring Cloud Connectors的启动器,可简化与Cloud Foundry和Heroku等云平台中服务的连接 | Pom |
| spring-boot-starter-data-cassandra | 使用Cassandra分布式数据库和Spring Data Cassandra的启动器 | Pom |
| spring-boot-starter-data-cassandra-reactive | 使用Cassandra分布式数据库和Spring Data Cassandra Reactive的启动器 | Pom |
| spring-boot-starter-data-couchbase | 使用Couchbase面向文档的数据库和Spring Data Couchbase的启动器 | Pom |
| spring-boot-starter-data-couchbase-reactive | 使用Couchbase面向文档的数据库和Spring Data Couchbase Reactive的启动器 | Pom |
| spring-boot-starter-data-elasticsearch | 使用Elasticsearch搜索和分析引擎以及Spring Data Elasticsearch的启动器 | Pom |
| spring-boot-starter-data-jdbc | 使用Spring Data JDBC的启动器 | Pom |
| spring-boot-starter-data-jpa | 将Spring Data JPA与Hibernate结合使用的启动器 | Pom |
| spring-boot-starter-data-ldap | 使用Spring Data LDAP的启动器 | Pom |
| spring-boot-starter-data-mongodb | 使用MongoDB面向文档的数据库和Spring Data MongoDB的启动器 | Pom |
| spring-boot-starter-data-mongodb-reactive | 使用MongoDB面向文档的数据库和Spring Data MongoDB Reactive的启动器 | Pom |
| spring-boot-starter-data-neo4j | 使用Neo4j图形数据库和Spring Data Neo4j的启动器 | Pom |
| spring-boot-starter-data-redis | 使用Redis键值数据存储与Spring Data Redis和Lettuce客户端的启动器 | Pom |
| spring-boot-starter-data-redis-reactive | 将Redis键值数据存储与Spring Data Redis Reacting和Lettuce客户端一起使用的启动器 | Pom |
| spring-boot-starter-data-rest | 使用Spring Data REST通过REST公开Spring数据存储库的启动器 | Pom |
| spring-boot-starter-data-solr | 将Apache Solr搜索平台与Spring Data Solr结合使用的启动器 | Pom |
| spring-boot-starter-freemarker | 使用FreeMarker视图构建MVC Web应用程序的 | Pom |
| spring-boot-starter-groovy-templates | 使用Groovy模板视图构建MVC Web应用程序的启动器 | Pom |
| spring-boot-starter-hateoas | 使用Spring MVC和Spring HATEOAS构建基于超媒体的RESTful Web应用程序的启动器 | Pom |
| spring-boot-starter-integration | 使用Spring Integration的启动器 | Pom |
| spring-boot-starter-jdbc | 结合使用JDBC和HikariCP连接池的启动器 | Pom |
| spring-boot-starter-jersey | 使用JAX-RS和Jersey构建RESTful Web应用程序,代替spring-boot-starter-web的启动器 | Pom |
| spring-boot-starter-jooq | 使用jOOQ访问SQL数据库的启动器。替代spring-boot-starter-data-jpa或spring-boot-starter-jdbc | Pom |
| spring-boot-starter-json | 读写JSON的启动器 | Pom |
| spring-boot-starter-jta-atomikos | 使用Atomikos的JTA交易的启动器 | Pom |
| spring-boot-starter-jta-bitronix | 使用Bitronix的JTA交易的启动器 | Pom |
| spring-boot-starter-mail | 使用Java Mail和Spring Framework的电子邮件发送支持的启动器 | Pom |
| spring-boot-starter-mustache | 使用Mustache视图构建Web应用程序的启动器 | Pom |
| spring-boot-starter-oauth2-client | 使用Spring Security的OAuth2或OpenID Connect客户端功能的启动器 | Pom |
| spring-boot-starter-oauth2-resource-server | 使用Spring Security的OAuth2资源服务器功能的启动器 | Pom |
| spring-boot-starter-quartz | 使用Quartz Scheduler的启动器 | Pom |
| spring-boot-starter-security | 使用Spring Security的启动器 | Pom |
| spring-boot-starter-test | 用于使用包括JUnit,Hamcrest和Mockito在内的库测试Spring Boot应用程序的启动器 | Pom |
| spring-boot-starter-thymeleaf | 使用Thymeleaf视图构建MVC Web应用程序的启动器 | Pom |
| spring-boot-starter-validation | 通过Hibernate Validator使用Java Bean验证的启动器 | Pom |
| spring-boot-starter-web | 使用SpringMVC构建Web(包括RESTful)应用程序的启动器。使用Tomcat作为默认的嵌入式容器 | Pom |
| spring-boot-starter-web-services | 使用Spring Web Services的启动器 | Pom |
| spring-boot-starter-webflux | 使用Spring Framework的Reactive Web支持构建WebFlux应用程序的启动器 | Pom |
| spring-boot-starter-websocket | 使用Spring Framework的WebSocket支持构建WebSocket应用程序的启动器 | Pom |
除了应用程序启动器,以下启动器可用于添加生产就绪功能:
| Name | Description | Pom |
|---|---|---|
| spring-boot-starter-actuator | 使用Spring Boot的Actuator的启动器,它提供了生产就绪功能,可帮助您监视和管理应用程序 | Pom |
Additionally, Spring Boot offers a variety of starters that can be utilized if you wish to exclude or substitute particular technical features.
末尾部分中提到Spring Boot还提供了其他启动器选项。如果你希望排除或替换某些技术细节,请参考这些启动器设置。
| Name | Description | Pom |
|---|---|---|
| spring-boot-starter-jetty | 使用Jetty作为嵌入式servlet容器的启动器。替代spring-boot-starter-tomcat | Pom |
| spring-boot-starter-log4j2 | 使用Log4j2进行日志记录的启动器。替代spring-boot-starter-logging | Pom |
| spring-boot-starter-logging | 使用Logback进行日志记录的启动器。默认记录启动器 | Pom |
| spring-boot-starter-reactor-netty | 使用Reactor Netty作为嵌入式反应式HTTP服务器的启动器 | Pom |
| spring-boot-starter-tomcat | 用于将Tomcat用作嵌入式Servlet容器的启动器。使用spring-boot-starter-web默认使用的servlet容器启动器 | Pom |
| spring-boot-starter-undertow | 使用Undertow作为嵌入式servlet容器的启动器。替代spring-boot-starter-tomcat | Pom |
涉及公共贡献者的一组相关启动器集合,请参阅GitHub上的spring-boot-starters模块中的README文件。
14. 结构化你的代码
Spring Boot不需要任何特定的代码结构也可以正常运行。然而有一套最佳实践可以帮助开发人员提高效率。
14.1 使用“default”包
如果某个类文件未声明包信息时,则默认归于默认包。一般不推荐使用默认包配置,请避免这样做。这可能引发一些问题,在Spring Boot应用中若采用@ComponentScan, @EntityScan,或@SpringBootApplication注解时,则会从每一个JAR文件中读取所有相关的类。
按照我们的建议, 您应该遵从 Java 推荐的命名规范, 并参考反转后的域名示例(如 com.example.project)。
14.2 定位主应用类
一般建议将主应用类放置在根目录上层的包中,并将其作为其他类的基础运行环境配置。JPA相关注解通常会被设置在主类中,并通过这些注解定义一个基础搜索包(Root Package)。这个基础搜索包的作用是帮助JPA应用程序识别并管理相关的 EntityManager 等核心对象及关系。此外,在项目的组织架构中启用组件扫描功能则能帮助快速识别并定位项目中的相关组件及其依赖关系
如果你不打算使用Spring Boot,在其默认配置下系统会自动引入这些注解标记符,并允许你继续配置应用。
以下列表显示了典型的布局:
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);
}
}
代码解释
15. 配置类
Spring Boot 基于 Java 的配置方案。然而它也可以通过 XML 标签实现 Spring Application 的创建。为了提高开发效率 我们推荐优先采用单一 Configuration 类进行配置管理。一般情况下 定义 main 方法的类 会默认携带 @Configuration 标签 从而实现功能上的完整性。
在互联网上发布的Spring配置实例中广泛采用了XML格式,在此情况下,请考虑采用与其功能相匹配的Java配置方案。假如可行的话,请探索带有@enable注解的相关代码可能会是一个不错的切入点。
15.1 入额外的配置类
避免将所有的@Configuration集中在一个类中;可以通过@Import注解导入额外的配置类。通过使用@ComponentScan可以自动获取所有SpringComponents并包含@Configuration类。
15.2 导入XML配置
如果你必须采用基于XML的配置方案, 我们推荐您继续采用Autowired启动方式. 你可以利用@ImportResource注解来导入并加载所需的XML配置文件.
16. 自动配置
Spring Boot会自动生成基于你已包含的JAR文件库以自动生成Spring应用程序。例如,在你的项目classpath中包含HSQLDB,并且未手动设置任何数据库连接时,则一旦运行Spring Boot就会自生成一个基于内存的默认数据库。
建议你将该@Configuration类配置为EnabledAutoConfiguration或SpringBootApplication注解的形式来实现自动配置功能。
你应该始终只在一个地方添加一个 "@SpringBootApplication" 或 "@EnableAutoConfiguration" 注解。我们通常推荐在你的主 @Configuration 类上放置 @SpringBootApplication 或 @EnableAutoConfiguration。
16.1 逐步替换自动配置
非侵入式的自动生成在任何时候都可以启动您自定义配置以取代自动配置的部分设置。例如,在需要增加自定义DataSourceBean时,默认的嵌入式数据库将退出支持
如果你希望确定自动化配置当前应用使用了哪些功能及其原因,请开启你的应用程序调试开关。通过这种方式你可以启用调试日志记录,并设置核心监控器以及相关条件报告到控制台。
16.2 禁止特定的自动配置文件
当您识别到正在部署不需要的特定自动生成配置类时,请您考虑通过设置_EnableAutoConfiguration中的排除属性来阻止该类被启用。例如以下情况中。
import org.springframework.boot.autoconfigure.*;
import org.springframework.boot.autoconfigure.jdbc.*;
import org.springframework.context.annotation.*;
@Configuration
@EnableAutoConfiguration(exclude={DataSourceAutoConfiguration.class})
public class MyConfiguration {
}
代码解释
如果该类不在classpath中,则可以通过设置enableAutoConfiguration 属性的excludeName字段来指定期望替代的完整限定名称。此外,请注意您还可以通过$configureAutoConfigureExcludes 属性来控制需要排除掉的自动生成配置类集合。
- @EnableAutoConfiguration的excludeName属性
import org.springframework.boot.autoconfigure.*;
import org.springframework.boot.autoconfigure.jdbc.*;
import org.springframework.context.annotation.*;
@Configuration
@SpringBootApplication(excludeName = {"org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration"})
public class MyConfiguration {
}
代码解释
- spring.autoconfigure.exclude
# 多值使用,分隔
spring.autoconfigure.exclude=org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration
代码解释
你可以在注释级别和使用属性来定义排除项。
17. Spring Beans和依赖注入
你可以灵活地采用各种传统的Spring框架技术来设置你的Beans及其注入依赖项。为了简化操作过程, 我们通常会推荐采用 beans Sprin_component_scan 和 inject framework_function 的方式来进行操作。
根据上述建议,在不显式配置的情况下,“通过\ComponentScan无需任何配置即可实现”。所有部署的应用组件将被自动注册至SpringBeans。
这个示例展示了如何通过使用 beanshell 的构造函数注入机制来获取所需的 RiskAssessorBean 实例。
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以表明其不可更改。
18. 使用@SpringBootApplication注解
许多springboot开发人员都喜欢他们的应用使用自动化配置设置、组件扫描功能以及在'应用程序类'中支持额外的配置设置等特色功能。通过一个SpringBootApplication注解即可启用这三个功能点:支持自动化配置设置、组件扫描功能以及在'应用程序类'中支持额外的配置设置。
- 通过启动Spring Boot的自动配置机制实现系统自动生成必要的依赖项
- 通过组件扫描功能,在应用程序所在的包中执行(参考最佳实践)
- 该功能提供额外的Bean注册和配置导入接口
在Spring Framework中,默认情况下使用@Configuration注解即可实现与@Autowired类似的组件注入功能。其中,@EnableAutoConfiguration用于启用自动配置功能,在编译时会生成对应的初始化代码。同时,在导入该注解库后,默认会提供一个名为@ComponentScan的方法或变量(具体取决于具体的框架实现),该方法或变量用于对指定组件进行扫描以获取相关的配置项设置。
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
@EnableAutoConfiguration
@Import({ MyConfig.class, MyAnotherConfig.class })
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
代码解释
在这个示例中,
在以下示例中,
Application 和 typical spring-boot applications 相似,
但有一个关键区别:标注有 @Component 的类未被自动识别并展示导入自定义 bean 的内容(请参考 @Import)。
19. 运行你的应用
其主要的优势之一在于能够将您的应用程序打包成一个.jar文件,并内置了完整的HTTP服务模块。类似于运行其他应用程序的方式即可方便地运行该程序。而调试Spring Boot应用同样非常便捷。您无需依赖特定的IDE插件或扩展就能完成开发工作
本节内容仅限于介绍如何打包一个JAR文件。建议将您的应用打包为war文件,并参考服务器和IDE的相关文档。
19.1 从一个IDE运行
类似于通过集成开发环境(IDE)运行简单的Java应用程序的方式,在某些情况下也可以用来运行Spring Boot应用程序。无论怎样做,你必须首先导入你的项目。这些操作会受到所使用的集成开发环境(IDE)以及构建系统的不同影响。多数集成开发环境(IDE)可以直接支持从现有的Maven项目中进行导入操作。例如,在Eclipse中,默认情况下用户可以从菜单栏中选择“文件”选项卡下的“Import…->Existing Maven Projects”。
当无法直接依赖注入到集成开发环境(IDE)时,通常需要配置构建工具以导出该环境的元数据。Maven支持Eclipse和IDEA等主流开发平台的开发工具集。Gradle则提供了针对多个主要编程语言和其对应的开发平台的开发工具集。
如果误操作启动两个Web应用程序,则会显示"端口已被占用"的错误信息。
STS(Spring Tools Suite)的用户可通过ReLaunch按钮而非Run按钮来关闭已经存在的实例。
19.2 运行一个打包的应用程序
当部署基于Spring Boot的项目时,请确保配置依赖项。通过运行指定路径的Java程序即可启动应用。例如:mvn clean install 或 gradle build。
$ 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
代码解释
19.3 使用Maven插件
Spring Boot Maven插件包含Run命令,不仅能够帮助你快速地编译和运行你的应用.应用通常会按照模块化的形式执行,这与你在IDE中使用的做法一致.以下案例展示了如何使用经典的Maven命令来启动Spring Boot应用程序:
$ mvn spring-boot:run
代码解释
你可能也想使用MAVEN_OPTS操作系统环境变量,按以下示例展示:
$ export MAVEN_OPTS=-Xmx1024m
代码解释
19.4 使用Gradle插件
该Gradle插件为Spring Boot提供了分解运行的任务。可通过该任务将应用分解进行运行。当同时配置org.springframework.boot和Java插件时,默认也会引入该分解任务。
$ gradle bootRun
代码解释
你可能也想使用JAVA_OPTS操作系统环境变量,按以下示例展示:
$ export JAVA_OPTS=-Xmx1024m
代码解释
19.5 热交换
由于Spring Boot应用本质上是基于Java开发的简洁应用,因此其JVM热插拔功能通常在部署时即可实现。然而,该功能受限因素主要在于其可替换的字节码部分。如果需要更为全面的解决方案,则建议考虑使用JRebel框架。
该模块提供了快速重启功能。请参考本章后续内容中的Chapter 20以及热交换操作的相关细节。
20. 开发人员工具
Spring Boot集成了一些功能模块以提升应用程序开发体验。其中spring-boot-devtools是一个可集成于任意项目的模块,它提供了丰富的开发时功能支持。为了使devtools生效,请按照以下步骤配置相应的依赖项:首先将该模块作为依赖添加到你的构建.gradle文件中,并根据需求选择合适的版本号。接下来将按照以下指引完成配置:在Maven管理器中执行相关设置操作;或者在 Gradle 章节中找到相应的设置选项完成配置工作。
- 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功能,则需确保excludeDevtoolsbuild属性被禁用以便包含所需功能。这两个插件配置都支持通过设置excludeDevtoolsbuild属性来实现功能。
20.1 属性默认值
Spring Boot依赖于一些第三方库以实现缓存功能,从而提升系统性能。
例如,在构建阶段生成已编译的模版文件,并将其存储起来。
此外,在提供静态资源时(如HTML文件),系统会在响应中添加HTTP缓存标志头。
Spring Boot依赖于一些第三方库以实现缓存功能,从而提升系统性能.
例如,在构建阶段生成已编译的模版文件,并将其存储起来.
此外,当提供静态资源(如HTML文件)时,系统会在响应中添加HTTP缓存标志头.
虽然 cached instances in production contexts offer significant benefits, they may lead to unintended consequences during development, thus making it difficult for developers to observe changes they've made to the application interface. Consequently, by default, tools like spring-boot-devtools disable cache configurations.
缓存设置通常由application.properties文件进行配置。例如,在Thymeleaf中,默认配置了spring.thymeleaf.cache属性。对于spring.boot-devtools模块而言,默认情况下无需手动指定这些缓存相关参数。
由于在开发SpringMVC及SpringWebFlux应用程序过程中,获取关于Web流量的信息至关重要。因此,在开发者工具中启用了DEBUG日志组来记录Web请求。这将提供更多关于接收中的请求数据、当前处理的数据流程及其相关信息。如果需要详细捕获所有请求数据(包括潜在敏感信息),建议打开了pring.http.log-request-details配置设置。
为了避免属性使用默认值,在你的application.properties中,请配置spring.devtools.add-properties为false。
涵盖devtools应用的所有属性的完整列表,请参考DevToolsPropertyDefaultsPostProcessor。
static {
Map<String, Object> properties = new HashMap<>();
properties.put("spring.thymeleaf.cache", "false");
properties.put("spring.freemarker.cache", "false");
properties.put("spring.groovy.template.cache", "false");
properties.put("spring.mustache.cache", "false");
properties.put("server.servlet.session.persistent", "true");
properties.put("spring.h2.console.enabled", "true");
properties.put("spring.resources.cache.period", "0");
properties.put("spring.resources.chain.cache", "false");
properties.put("spring.template.provider.cache", "false");
properties.put("spring.mvc.log-resolved-exception", "true");
properties.put("server.error.include-stacktrace", "ALWAYS");
properties.put("server.servlet.jsp.init-parameters.development", "true");
properties.put("spring.reactor.stacktrace-mode.enabled", "true");
PROPERTIES = Collections.unmodifiableMap(properties);
}
代码解释
20.2 自动重启
每当类路径中的文件发生修改时, spring-boot-devtools会自动重启应用程序.对于那些使用IDE工作的开发者而言,在进行代码修改时会发现这一功能非常实用.因为这使得他们能够迅速获得修改后的反馈.默认情况下,在类路径中跟踪指向文件夹的所有变更.值得注意的是,在这种情况下通常不会影响到应用程序的重启.
触发重启
当DevTools监控类路径资源时,仅需进行类路径重配置即可触发重启。类路径更新的方式会受所使用的开发环境影响。在Eclipse开发环境中编辑修改的项目文件夹将导致类路径重新配置并强制重启服务进程。在IntelliJ IDEA中执行Build -> Build Project操作将实现同样的效果。
如果选择了分叉版本,则还可以配置受支持的构建工具如Maven和Gradle来启动应用程序。由于隔离的应用程序类加载器能够确保应用独立运行而无需外部依赖项的支持,在这种情况下应用能够顺利初始化并开始服务。通常情况下,默认配置下这些工具会在检测到DevTools时自动执行相关操作以保证系统的稳定性和安全性。
自动重启功能表现出色,并且特别适合与LiveReload协同工作。
请注意,在采用JRebel时,自动重启功能将不再起作用。
其他devtools特性(如LiveReload和属性覆盖)仍可正常工作。
在重新启动期间,DevTools依赖于应用程序上下文中被其所依赖的应用程序上下文中的关闭钩子被其所依赖地关闭。如果将关闭钩子设置为不启用(即SpringApplication.setRegisterShutdownHook(false)),则会导致其无法正常工作。
当类路径中的条目发生变化时是否应该触发重新启动时 DevTools 会自动跳过命名的项目 spring-boot spring-boot-devtools spring-boot-autoconfigure spring-bold-actuator 和 spring-bold-starter。
DevTools依赖于一个ApplicationContext来配置ResourceLoader。如果您的应用程序已经实现了自定义的ApplicationContext,则该类将被包装以便与其他组件集成。该工具库不允许直接继承或覆盖ApplicationContext.getResource()方法。
重启 vs 重载
该应用通过两个不同的类加载机制实现了系统的重 boot功能。那些非动态修改的静态资源(如第三方库中的组件)会被预先装载至基础类 loader 中。而动态修改的应用组件则会被分配至专门负责重 boot过程的新 loader 环境中。当执行系统重 boot操作时,会放弃当前的重 boot loader,并建立一个新的独立 loader 机制。这样一来,在大多数情况下实现的应用程序重启速度远超传统 '冷启动'策略。
当遇到应用程序启动缓慢或类加载失败的情况,则可以选择重新加载相关技术。例如ZeroTurnaround的JRebel便是其中一种解决方案。这些操作通常通过在类装载过程中进行修改完成,以方便后续再次装载。
20.2.1 记录条件评估中的更改
通常情况下,在程序重启时都会生成一个报告,并详细记录了相关条件评估的变化量。该报告则详细说明了例如添加或删除bean以及设置配置属性等操作对应用程序自动配置的影响。
要禁用报告的日志记录,请设置以下属性:
spring.devtools.restart.log-condition-evaluation-delta=false
代码解释
20.2.2 排除资源
并非所有资源的更改都会导致重新启动。举个例子来说,在Thymeleaf中是可以实现本地修改的。根据默认设置,在修改以下路径时并不会引发重启操作:/resources、/public、/static以及 templates目录等位置上的变更都会触发表现重装操作。若有特定需求可自行指定排除列表以避免不必要的重启过程,请问您是想实现什么功能呢?
spring.devtools.restart.exclude=static/**,public/**
代码解释
为了保留这些默认值并新增其他排除项,请考虑使用spring.devtools.restart.additional-exclude属性。
20.2.3 监控其它路径
当修改位于类路径之外的文件时,请考虑让应用程序重新启动或者切换到新的版本以确保最新更新的有效性。为此建议使用spring.devtools.restart.additional-paths属性来指定需监控变化的额外路径。你还可以参考前面介绍的spring.devtools.restart.exclude属性来决定那些不在指定排除列表中的更改是导致整个程序重新启动还是立即加载更新内容。
20.2.4 禁用重启
如果你希望避免使用重启特性, 你可以选择配置spring.devtools.restart.enabled属性将其禁用。通常情况下, 你可以将该属性设置在application.properties中(这样操作仍然会导致重新启动类加载器被初始化, 但不会监控文件更改)。
若你希望完全关闭重启功能(比如它不适用于某个特定库),则需在启动应用前配置System属性spring.devtools.restart.enabled=false。
public static void main(String[] args) {
System.setProperty("spring.devtools.restart.enabled", "false");
SpringApplication.run(MyApp.class, args);
}
代码解释
20.2.5 使用触发器文件
如果采用自动更新模式来修改代码编辑器,则可能会偏爱只在特定时间段内强制重置程序。为了达到这一目的,请考虑创建并管理一个'关键脚本'(即一个特殊文件),它会在实际需要执行某些操作时被修改以引发重置过程。修改代码会引发重置过程而非立即重启系统;只有当Devtools检测到需要执行某些操作时才会进行重启操作。您可以通过手动编辑或利用IDE插件来维护这个关键脚本的状态。
为了实现触发功能,请将 spring.devtools.restart.trigger-file 属性指定位置为 驴踢启动文件 的路径。
你可能会建议将该配置项spring.devtools.restart.trigger-file设为全局值,以便所有项目均采用一致的运行模式。
20.2.6 自定义重启类加载器
如相关Restart vs Reload章节所述,在开发中通常会采用基于两个类加载器实现的方法来处理重启功能的问题。这种方法在大多数情况下都能确保良好的运行状态,并且运行速度较快。然而,在某些特殊场景下可能会遇到性能上的挑战
通常情况下,在IDE环境中打开的项目会采用“重新启动”类加载器进行加载;而常规的.jar文件则会采用“基本”类加载器来完成加载过程。如果是在多模块构建时,并非所有模块都被导入到IDE环境中,则可能需要自定义配置以满足需求;为此建议创建一个META-INF/spring-devtools.properties配置文件来实现特定化的开发需求。
该spring-devtools.properties文件能够包含以restart.exclude及restart.include为前缀的属性项。其中涉及include项应被配置为会被提升至"重启"类加载器处理的对象内容;而设置为exclude项目的项,则应被指定为会被推送至"基础类加载器"之外的处理范围之外的内容。这些属性的具体取值形式为一种用于匹配应用在整个类路径上的正则表达式模式(例如以下示例所示):
restart.exclude.companycommonlibs=/mycorp-common-[\ w-]+\.jar
restart.include.projectcommon=/mycorp-myproj-[\ w-]+\.jar
代码解释
每个属性字段都必须满足唯一性要求。
如果一个字段的名称以restart.include.或restart.exclude.开头,则应予以考虑。
所有META-INF/spring-devtools.properties文件均通过类路径加载。建议将META-INF/spring-devtools.properties文件打包至项目内部或项目依赖的公共库中完成部署。
20.2.7 已知限制
此功能不能用于通过标准反序列化的对象ObjectInputStream实现的对象重置。若需反序列化数据,则可能要考虑配合Spring的ConfigurableObjectInputStream并使用Thread.currentThread().getContextClassLoader()。
有遗憾的是,在不考虑上下文类加载器的情况下运行的一些第三方库会进行反序列化。若一旦遇到此类问题,则应寻求原作者的帮助。
20.3 LiveReload
spring-boot-devtools模块包含了一个内置的LiveReload嵌入服务器。该服务器在资源修改时自动触发浏览器刷新功能。此外,用户可通过livereload.com免费下载适用于Chrome、Firefox以及Safari浏览器的LiveReload扩展程序。
在你的应用程序运行时,在不想启动LiveReload服务的情况下,请将spring.devtools.livereload.enabled配置为false。
仅允许同时运行一个该服务。
请确认没有任何其他LiveReload服务正在运行。
在启动您的应用之前,请确保没有其他LiveReload服务在运行。
当您通过IDE多次启动应用时,请注意只有第一个此类操作会被允许。
20.4 全局设定
你建议在你的$HOME目录中创建一个名为spring-boot-devtools.properties的文件(请注意该文件名需以点开头),以便配置全局DevTools设置。任何设置项都会影响所有安装有DevTools的应用程序。例如,在此文档中定义重启时始终基于触发日志,则可实现所需功能。
~/.spring-boot-devtools.properties.
spring.devtools.reload.trigger-file=.reloadtrigger
代码解释
启用配置文件spring-boot-devtools.properties时,并不会干扰与该配置文件相关的其他配置文件的加载过程。
20.5 远程应用
springboot 开发人员工具不仅仅局限于本地开发环境。在远程运行应用程序时(也可以选择启用远程支持),还可以提供多种功能选项。要使其正常运转,请确保已将调试工具包(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属性,如以下示例所示:
spring.devtools.remote.secret=mysecret
代码解释
建议避免在生产环境中开启远程应用的支持功能。
远程devtools分为两个部分:一个是用于接收连接的服务器端端点,另一个是在IDE中运行的客户端应用程序。设置该属性后会自动启用相应的服务器组件。客户端组件必须手动启动相应的服务或功能模块。
20.5.1 运行远程客户端应用程序
该远程客户端应用程序旨在能够在你的IDE环境中运行。为了实现与所连接远程目录上应用的一致性需求,建议您使用org.springframework.boot.devtools.RemoteSpringApplication工具,并确保其运行时使用的类路径与目标目录一致。该应用程序仅需一个必要参数——连接至的目标URL。
比如你采用的是Eclipse或STS,并且你的my-app已部署至Cloud Foundry,则需执行如下操作:
- 在Run菜单中选择Run Configurations…
- 新建一个名为"launch configuration"的Java应用程序。
- 访问该my-app项目以便进行配置。
- 将RemoteSpringApplication设为主类应用以简化配置过程。
- 将远程配置项设置为https://myapp cfapps io
正在运行的远程客户端可能类似于以下清单:
. ____ _ __ _ _
/\ / ___'_ __ _ _(_)_ __ __ _ ___ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | | _ \___ _ __ ___| |_ ___ \ \ \ \
\ / ___)| |_)| | | | | || (_| []::::::[] / -_) ' \/ _ \ _/ -_) ) ) ) )
' |____| .__|_| |_|_| |_\__, | |_|_\___|_|_|_\___/\__\___|/ / / /
=========|_|==============|___/===================================/_/_/_/
:: Spring Boot Remote :: 2.1.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-devtools/target/classes started by pwebb in /Users/pwebb/projects/spring-boot/code/spring-boot-samples/spring-boot-sample-devtools)
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)
代码解释
由于远程客户端采用与真实应用相同的类路径结构,因此能够直接获取应用程序的相关属性信息。这即是Spring DevTools remote secret通过获取相关属性并将这些信息传递至服务器以完成身份验证的技术途径。
通常推荐将https://作为连接协议,并用于实现通信的安全性,并且防止他人获取敏感信息。
如果需要通过代理服务器访问远程应用程序,请确保设置相关的配置参数。
请注意,在Spring框架中,默认不支持代理功能,请确保已经正确配置并启用代理功能。
20.5.2 远程更新
远程客户端采用与本地重新启动相同的监视机制来关注应用程序类路径中的修改情况。所有更新后的资源会被传递至远程应用系统中,并在必要时触发重启过程。如果你能够逐步利用本地尚未提供的云服务功能,则这一做法将非常有益。通常而言,在执行远程更新和重启操作方面相比完整的重建与部署周期而言具有显著优势
当且仅当远程客户端处于运行状态时,系统会对该文件进行监控。若在启动远程客户端之前修改该文件,则该系统将不会将其传输至远程服务器。
21. 打包你的生产申请
可执行jar能够支持生产部署。因为它们各自独立,所以它们非常适合基于云的部署
针对其他"生产准备就绪"功能而言,在涉及运行状况、审核以及基于REST或JMX的标准时域点方面,请建议采用spring-boot-actuator。具体信息,请参考第五部分《Spring Boot执行器:生产就绪功能》。
22. 接下来阅读什么
现在,请掌握如何使用Spring Boot以及应遵循的最佳实践。现在,请选择是否深入学习与Spring Boot相关的详细信息或者跳过本节内容并深入研究Spring Boot的相关内容。

