编程开发 --- springboot参考文档之 开发
本节将详细介绍如何使用 Spring Boot。它涵盖了构建系统、自动配置以及如何运行应用程序等主题。我们还将介绍一些 Spring Boot 最佳实践。虽然 Spring Boot 并没有什么特别之处(它只是另一个可以使用的库),但我们还是提出了一些建议,遵循这些建议可以让您的开发过程更轻松一些。
如果您刚开始使用 Spring Boot,在阅读本节内容之前,最好先阅读启动器。
6.1. 构建系统
强烈建议您选择一个支持依赖关系管理的构建系统,该系统可以使用发布到 "Maven Central "资源库的工件。我们建议您选择 Maven 或 Gradle。Spring Boot 也可以与其他构建系统(例如 Ant)配合使用,但它们的支持并不完善。
6.1.1. 依赖性管理
Spring Boot 的每个版本都会提供其支持的依赖项的精选列表。实际上,您无需在构建配置中提供这些依赖项的版本,因为 Spring Boot 会为您管理这些依赖项。当您升级 Spring Boot 本身时,这些依赖项也会以一致的方式升级。
注意
如果需要,您仍然可以指定一个版本并覆盖 Spring Boot 的建议
策划列表包含了可与 Spring Boot 配合使用的所有 Spring 模块,以及第三方库的细化列表。该列表以标准材料清单 (spring-boot- dependencies) 的形式提供,可与 Maven 和 Gradle 一起使用。
警告
Spring Boot 的每个版本都与 Spring Framework 的基础版本相关联。我们强烈建议您不要指定其版本。
6.1.2. Maven
要了解如何将 Spring Boot 与 Maven 结合使用,请参阅 Spring Boot 的 Maven 插件文档:
6.1.3. Gradle
要了解如何将 Spring Boot 与 Gradle 结合使用,请参阅 Spring Boot 的 Gradle 插件文档:
6.1.4. ANT
使用 Apache Ant+Ivy 可以构建 Spring Boot 项目。spring-boot-antlib "AntLib "模块也可帮助 Ant 创建可执行的 jar。(译者注:Ant 主要用于构建项目,而 Ivy 则是用于管理项目依赖的工具。在许多项目中,Ant 和 Ivy 都会一起使用,Ant 负责构建任务,而 Ivy 负责管理项目的依赖。)
要声明依赖关系,典型的 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 文件与下面的示例相似:
<!-- 定义项目名称为 myapp,默认构建目标为 build -->
<project xmlns:ivy="antlib:org.apache.ivy.ant"
xmlns:spring-boot="antlib:org.springframework.boot.ant"
name="myapp" default="build">
<!-- 定义 spring-boot.version 属性,值为 "3.2.2" -->
<property name="spring-boot.version" value="3.2.2" />
<!-- 定义名为 resolve 的目标,用于使用 Ivy 检索依赖项 -->
<target name="resolve" description="Retrieve dependencies with Ivy">
<ivy:retrieve pattern="lib/[conf]/[artifact]-[type]-[revision].[ext]" />
</target>
<!-- 定义名为 classpaths 的目标,依赖于 resolve,用于设置编译库路径 -->
<target name="classpaths" depends="resolve">
<path id="compile.classpath">
<fileset dir="lib/compile" includes="*.jar" />
</path>
</target>
<!-- 定义名为 init 的目标,依赖于 classpaths,用于初始化目录结构,定义编译类路径 -->
<target name="init" depends="classpaths">
<mkdir dir="build/classes" />
</target>
<!-- 定义名为 compile 的目标,依赖于 init,用于编译源代码 -->
<target name="compile" depends="init" description="Compile">
<javac srcdir="src/main/java" destdir="build/classes" classpathref="compile.classpath" />
</target>
<!-- 定义名为 build 的目标,依赖于 compile,用于构建可执行的 Spring Boot JAR 文件 -->
<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 模块,请参阅 "如何不使用 spring-boot-antlib 通过 Ant 构建可执行jar。
6.1.5. Starters
Starters 是一组方便的依赖描述符,你可以将其包含在你的应用程序中。你可以通过一站式服务获得所有你需要的 Spring 和相关技术,而无需查找示例代码并复制粘贴大量依赖描述符。例如,如果你想要开始使用 Spring 和 JPA 进行数据库访问,只需在你的项目中包含 spring-boot-starter-data-jpa 依赖项。
这些 starters 包含了许多你需要快速启动项目并使用一组一致且受springboot官方支持的由maven管理的传递依赖项的依赖关系。
(译者注: 意味着 starters 中包含了一系列依赖项,这些依赖项是被 Spring Boot 团队精心挑选和管理的,并且它们的版本是相互协调和兼容的。这些依赖项通常是其他库和框架的传递依赖,即你的应用程序需要的库可能依赖于其他库,就是依赖的依赖。通过使用 starters,你无需担心这些传递依赖的版本冲突或不一致性,因为它们都是经过仔细选择和管理的,确保了一致性和兼容性。)
名字的含义
所有官方Starter都遵循类似的命名模式:spring-boot-starter-*,其中 * 表示特定类型的应用程序。这种命名结构的目的是在需要查找Starter时提供帮助。许多集成开发环境中的 Maven 集成可让您按名称搜索依赖项。例如,如果安装了相应的 Eclipse 或 Spring Tools 插件,就可以在 POM 编辑器中按下 ctrl-space,然后键入 "spring-boot-starter",查看完整列表。
正如 "创建自己的Starter "部分所述,第三方Starter不应以 spring-boot 开头,因为它是 Spring Boot 官方产品的专用开头。相反,第三方启动器通常以项目名称开头。例如,名为 thirdpartyproject 的第三方Starter项目通常会命名为 thirdpartyproject-spring-boot-starter。
Spring Boot 在 org.springframework.boot组ID 提供了以下应用程序Starter(译者注:这里的组ID是maven的概念,类似java包名)
(译者注:可以还有人不知道 HATEOAS 风格和普通 RESTful 风格的区别,
HATEOAS(Hypermedia as the Engine of Application State)和RESTful是两个相关但不同的概念。
-
RESTful(Representational State Transfer):是一种软件架构风格,旨在通过使用 HTTP 协议的几个核心原则来设计网络应用程序的通信。这些原则包括统一的接口(Uniform Interface)、无状态(Stateless)、资源导向(Resource-Oriented)和客户端-服务器架构(Client-Server Architecture)等。RESTful 风格的 API 遵循这些原则,以提供简单、可伸缩、可扩展和高性能的网络服务。
-
HATEOAS(Hypermedia as the Engine of Application State):是 RESTful 架构中的一个概念,强调超媒体作为应用状态的引擎。它建议将超媒体链接(例如超链接)包含在 API 响应中,以允许客户端动态地发现和导航资源之间的关系和操作。这样,客户端可以根据响应中包含的超链接信息来构建和执行进一步的操作,而不需要事先知道所有的资源路径和操作方式。
区别在于,RESTful 是一种软件架构风格,旨在定义网络应用程序的通信模式和设计原则,而 HATEOAS 是 RESTful 架构中的一个概念,强调在 API 中包含超媒体链接以提供资源之间的关系和操作的导航。
哪一个更好取决于具体的应用场景和需求。RESTful 风格的 API 提供了一种简单、可伸缩和可扩展的网络通信模式,而 HATEOAS 则提供了更丰富和自描述的 API,允许客户端动态地发现和导航资源之间的关系和操作。根据应用的复杂度、团队的技术能力和偏好,以及对 API 自描述性和导航性的需求,选择适合的架构风格。
ATEOAS 的强大功能也带来了一定的复杂性和学习曲线。实现和使用 HATEOAS 风格的 API 需要更多的技术和设计考量,包括资源关系的设计、超链接的构建和管理等。此外,客户端也需要具备一定的能力来理解和处理 API 响应中的超链接信息,以便动态地构建和执行进一步的操作。
相比之下,传统的 RESTful 风格的 API 相对更简单、直观,并且更容易实现和理解。它使用统一的接口和资源导向的设计原则,提供了一种简单而可靠的通信模式,适用于大多数的应用场景。
因此,对于简单的应用场景和团队来说,传统的 RESTful 风格可能更加合适和易于实现。但对于复杂的系统和需要更灵活和自适应的 API 来说,HATEOAS 风格的 API 提供了更强大和更具有未来扩展性的解决方案。
状态是资源的属性值,描述了资源在某一时刻的情况,而会话是一系列相关的请求和响应交互,用于跟踪用户在应用程序中的活动状态。
状态通常是资源级别的,与特定的资源相关,而会话通常是用户级别的,与用户的活动周期相关。
状态通常由服务器维护和管理,而会话通常由服务器和客户端共同维护和管理。
虽然状态和会话是不同的概念,但在某些情况下,会话信息可能会被用来表示某些资源的状态,尤其是在涉及到用户身份认证和权限管理的情况下。
一句话就是
HATEOAS 定义所有的api接口内资源链接是自包含的,restful定义客户端需要事先知道每个资源的地址和操作方法,
再简单说就是一个HATEOAS 接口可以找到所有相关资源,这也被称为超媒体,而restful是有多少资源就要定义多少个接口
比如我们要查找所有的书籍列表,HATEOAS会返回书籍的名称和详细哪本书的url,而restful会返回所有书籍列表。
我们要查找一本书,HATEOAS在上一步已经有了书的url,发出请求即可,而restful需要预先在客户端写死一个url发起请求
好的,让我使用之前提到的图书馆管理系统的例子来演示 HATEOAS 风格和普通 RESTful 风格的 CRUD 操作。
假设我们有以下资源:
书籍(Books)
作者(Authors)
出版商(Publishers)
HATEOAS 风格的 CRUD 操作示例:
获取所有书籍列表(GET /books)
响应:
{ "books": [ { "title": "Clean Code", "links": [ { "rel": "self", "href": "/books/1" } ] }, { "title": "Design Patterns", "links": [ { "rel": "self", "href": "/books/2" } ] } ], "links": [ { "rel": "self", "href": "/books" } ] }
获取单个书籍详情(GET /books/1)
响应:
{ "title": "Clean Code", "author": { "name": "Robert C. Martin", "links": [ { "rel": "self", "href": "/authors/1" } ] }, "publisher": { "name": "Prentice Hall", "links": [ { "rel": "self", "href": "/publishers/1" } ] }, "links": [ { "rel": "self", "href": "/books/1" }, { "rel": "authors", "href": "/books/1/authors" }, { "rel": "publisher", "href": "/books/1/publisher" } ] }
普通 RESTful 风格的 CRUD 操作示例:
获取所有书籍列表(GET /books)
响应:
[ { "title": "Clean Code", "author": "Robert C. Martin", "publisher": "Prentice Hall", "book_id": 1 }, { "title": "Design Patterns", "author": "Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides", "publisher": "Addison-Wesley", "book_id": 2 } ]
获取单个书籍详情(GET /books/1)
{ "title": "Clean Code", "author": "Robert C. Martin", "publisher": "Prentice Hall", "book_id": 1 }
以上就是 HATEOAS 风格和普通 RESTful 风格的 CRUD 操作示例。可以看到,在 HATEOAS 风格中,响应中包含了超链接信息,而在普通 RESTful 风格中,只返回了资源的属性。
)
表 1.Spring Boot 应用程序Starter
(译者注:Starter其实就是一个已经配置好的最佳功能解决方案,比如我要开发web,我只要springboot web启动器就可以将web所需的所有第三方工具加载进来并配置好。)
名称 |
说明 |
spring-boot-starter |
核心启动器,包括自动配置支持、日志和 YAML(译者注:其他启动器直接依赖它,YAML是一种配置文件格式) |
spring-boot-starter-activemq |
使用 Apache ActiveMQ 发送 JMS 消息的启动器(jms是java企业级消息标准,ActiveMQ是实现jms标准的消息代理器) |
spring-boot-starter-amqp |
使用 Spring AMQP 和 Rabbit MQ 的启动器(译者注:Rabbit MQ实现了AMQP协议的代理器。AMQP是通用的,JMS是专用于java的, AMQP:AMQP 提供了丰富的消息传递功能,包括消息队列、交换机、路由、消息确认、持久化、事务等。它支持更复杂的消息传递模型,并且提供了更多的灵活性和可扩展性。 ) |
spring-boot-starter-aop |
使用 Spring AOP 和 AspectJ 进行面向切面编程的启动器(译者注: Spring AOP 和 AspectJ 都是面向切面编程(AOP)的实现框架,它们都旨在帮助开发者将横切关注点从主要业务逻辑中分离出来,以提高代码的模块化性和可维护性。但它们在实现方式、功能和使用场景上有一些不同:
1. **Spring AOP**:
2. **AspectJ**: ) |
spring-boot-starter-artemis |
使用 Apache Artemis 发送 JMS 消息的启动器(与activemq类似,activemq用的人更多) |
spring-boot-starter-batch |
使用 Spring Batch 的启动器(类似windows上的bat批处理程序,会有一个作业概念和调度器的概念) |
spring-boot-starter-cache |
使用 Spring Framework 缓存支持的启动器(主要用于缓存方法的返回值,下次key相同时直接返回结果而不执行函数) |
spring-boot-starter-data-cassandra |
使用 Cassandra 分布式数据库和 Spring Data Cassandra 的启动器(Cassandra 更适合于大规模的分布式数据存储和查询比如日志,多用于后端数据存储,而 Redis 更适合于快速的键值存储和缓存应用比如缓存热门数据,如热门文章、热门商品等,提高访问速度和用户体验。多用于前端数据存储。) |
spring-boot-starter-data-cassandra-reactive |
使用 Cassandra 分布式数据库和 Spring Data Cassandra Reactive 的启动器( 数据适合使用响应式数据库 实时数据流:适合处理实时生成的数据流,如传感器数据、日志数据、网络流量数据等。 总的来说,响应式数据库适合处理各种类型的实时数据和事件流,特别适合需要高并发、高吞吐量、实时处理和流式处理的应用场景。它可以通过异步、非阻塞的方式处理数据流和事件流,提高系统的性能和响应能力。) |
Spring-boot-starter-data-couchbase |
使用面向文档的 Couchbase 数据库和 Spring Data Couchbase 的启动器(Couchbase 数据库是一个面向文档的 NoSQL 数据库,而 Spring Data Couchbase 是 Spring Data 项目提供的用于与 Couchbase 数据库集成的模块。Spring Data Couchbase 提供了对 Couchbase 数据库的对象映射和数据访问支持,简化了在 Spring 应用中使用 Couchbase 数据库的开发工作。Couchbase 是一个面向文档的数据库,注重高性能、高可用和灵活的数据模型;而 MongoDB 也是面向文档的数据库,更注重数据的灵活性和复杂查询的支持。) |
spring-boot-starter-data-couchbase-reactive |
使用面向文档的 Couchbase 数据库和 Spring Data Couchbase Reactive 的启动器(Couchbase 数据库是一个面向文档的 NoSQL 数据库,而 Spring Data Couchbase Reactive 是 Spring Data 项目提供的用于与 Couchbase 数据库集成的响应式模块。与传统的 Spring Data Couchbase 模块不同,Spring Data Couchbase Reactive 支持响应式编程模型,允许开发者使用 Reactor 或 RxJava 等响应式库来处理数据流和异步操作,从而实现更高效的数据访问和处理。) |
spring-boot-starter-data-elasticsearch |
使用 Elasticsearch 搜索和分析引擎以及 Spring Data Elasticsearch 的启动器( Elasticsearch 可以被视为一种数据库,但它与传统的关系型数据库有一些不同之处。
传统的关系型数据库(如 MySQL、PostgreSQL 等)以表的形式组织数据,并使用 SQL 进行数据查询和操作。这些数据库通常用于存储结构化数据,并支持事务和复杂的查询操作。
而 Elasticsearch 是一个分布式搜索和分析引擎,它以文档的形式组织数据,并使用自定义的 JSON 格式进行数据存储和查询。Elasticsearch 主要用于全文搜索、实时数据分析和日志分析等场景,它提供了强大的搜索和聚合功能,可以处理大规模的非结构化和半结构化数据。 ) |
Spring-boot-starter-data-jdbc |
使用 Spring Data JDBC 的启动器( 果你的项目需要复杂的对象关系映射和面向对象的查询语言,可以选择 Spring Data JPA;如果你的项目需要简单的数据模型和直接的 SQL 查询语言,可以选择 Spring Data JDBC。) |
Spring-boot-starter-data-jpa |
将 Spring Data JPA 与 Hibernate 结合使用的启动器( JPA是javaee官方的标准数据库接口,Hibernate 作为 JPA 的实现提供商。) |
spring-boot-starter-data-ldap |
使用 Spring Data LDAP 的启动器( LDAP(轻量目录访问协议)本质上也可以被视为一种数据库,但它与传统的关系型数据库有一些不同之处。 LDAP 主要用于存储和组织目录信息,例如用户、组织、设备等。它具有以下特点:
尽管 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 的启动器(Neo4j 是一个图数据库管理系统,它采用图结构来存储和处理数据。与传统的关系型数据库不同,图数据库使用节点、关系和属性来表示和存储数据,并通过图算法来实现数据的查询和分析。Neo4j 提供了高效的图数据库引擎和丰富的图算法库,可以用于构建和管理复杂的图数据模型,并支持高效的图数据查询、分析和可视化。Neo4j 被广泛应用于社交网络分析、推荐系统、网络安全、知识图谱等领域。) |
spring-boot-starter-data-r2dbc |
使用 Spring Data R2DBC 的启动器( Spring Data R2DBC 是 Spring Data 项目的一部分,用于简化在响应式应用中使用 R2DBC(Reactive Relational Database Connectivity)的开发。R2DBC 是一种响应式的关系型数据库连接规范,旨在提供异步、非阻塞的数据库访问能力,与响应式编程模型相适应。 Spring Data R2DBC 提供了一组 API 和工具,帮助开发者在 Spring 应用中更轻松地进行响应式数据库访问。通过 Spring Data R2DBC,你可以使用响应式编程模型来操作关系型数据库,实现异步和非阻塞的数据访问操作。 Spring Data R2DBC 的主要功能包括:
通过 Spring Data R2DBC,开发者可以利用响应式编程模型来编写异步、非阻塞的数据库访问代码,从而提高应用的性能和可伸缩性,并且能够更好地适应现代的响应式应用开发需求。 ) |
Spring-boot-starter-data-redis |
利用 Spring Data Redis 和 Lettuce 客户端使用 Redis 键值数据存储的启动器 |
spring-boot-starter-data-redis-reactive |
利用 Spring Data Redis reactive 和 Lettuce 客户端使用 Redis 键值数据存储的启动器 |
spring-boot-starter-data-rest |
使用 Spring Data REST 和 Spring MVC 在 RESTful API 中暴露 Spring Data 仓库。(简单来说,这个 Starter 将帮助你快速地创建一个 RESTful API,通过 Spring Data REST 来暴露你的 Spring Data 仓库。Spring Data REST 会自动将你的数据仓库转换为 RESTful 风格的资源,并提供标准的 CRUD (Create, Read, Update, Delete) 操作,使得你可以通过 HTTP 协议对数据进行访问和操作。而 Spring MVC 则用于处理 HTTP 请求和响应,将客户端的请求映射到相应的处理方法,并将处理结果返回给客户端。) |
spring-boot-starter-freemarker |
使用 FreeMarker 视图构建 MVC web应用程序的启动器(类似jsp模板引擎) |
spring-boot-starter-graphql |
使用 Spring GraphQL 构建 GraphQL 应用程序的启动器(GraphQL 是一种接口风格,可以一次查询出所有相关数据,比如一本书包含的作者相关信息。restful而是一个书是一个crud接口,一个作者是另一个crud接口,他们之间使用key进行关联查询。hateoas是每个接口都包含其他接口的请求链接。) |
spring-boot-starter-groovy-templates |
使用 Groovy 模板视图构建 MVC web应用程序的启动器(Groovy语言编写的模板引擎,类似jsp用java编写) |
spring-boot-starter-hateoas |
使用 Spring MVC 和 Spring HATEOAS 构建基于超媒体的 RESTful web应用程序的启动器 |
spring-boot-starter-integration |
使用 Spring Integration 的启动器(提供消息驱动功能的框架) |
spring-boot-starter-jdbc |
与 HikariCP 连接池一起使用 JDBC 的启动器( HikariCP 是一个数据库连接池,它负责管理数据库连接资源,并在需要时分配给应用程序使用。当一个数据库连接被释放(即归还给连接池)时,并不会立即关闭这个连接,而是将其放回连接池中以便重用。这种方式能够提高应用程序的性能和效率,因为避免了频繁地创建和销毁数据库连接,减少了资源消耗和系统开销。
数据库连接池通常会维护一定数量的空闲连接,这些连接处于可重用状态。当应用程序需要获取一个数据库连接时,连接池会优先分配一个空闲连接给应用程序使用,而不是创建一个新的连接。当连接池中没有可用的空闲连接时,连接池会根据配置参数来决定是否创建新的连接。
因此,当一个数据库连接被释放后,它会继续存在于连接池中,供下一次请求使用。这种机制可以有效地减少数据库连接的创建和销毁次数,提高应用程序的性能和资源利用率。 ) |
spring-boot-starter-jersey |
使用 JAX-RS 和 Jersey 构建 RESTful web应用程序的启动器。Spring-boot-starter-web 的替代方案(,JAX-RS 是一套用于构建 RESTful Web 服务的标准 API,而 Jersey 则是 JAX-RS 的一个具体实现,用于实际开发和部署 RESTful Web 服务。Jersey 提供了一套强大而灵活的工具和框架,帮助开发者快速、高效地构建 RESTful Web 服务。) |
Spring-boot-starter-jooq |
使用 jOOQ 通过 JDBC 访问 SQL 数据库的启动器。spring-boot- starter-data-jpa 或 spring-boot-starter-jdbc 的替代选择( jOOQ(Java Object Oriented Querying)是一个用于在 Java 应用程序中进行类型安全的 SQL 查询和操作的库。它与传统的 ORM(对象关系映射)框架有所不同,它不是将数据库表映射为对象,而是将数据库表、字段等对象映射为 Java 中的类、属性等对象,通过生成的 jOOQ 类来进行数据库查询和操作。 ) |
spring-boot-starter-json |
读写 json 的启动器 |
spring-boot-starter-mail |
使用 Java Mail 和 Spring Framework 电子邮件发送支持的启动器 |
spring-boot-starter-mustache |
使用 Mustache 视图构建web应用程序的启动器(Mustache 是无逻辑代码的模板引擎) |
spring-boot-starter-oauth2-authorization- server |
使用 Spring 授权服务器功能的启动器(OAuth 2.0 是一种用于授权的开放标准,允许第三方应用程序通过授权访问用户的受保护资源,而不需要用户提供他们的用户名和密码。OAuth 2.0 授权服务器是实现 OAuth 2.0 协议的一部分,负责颁发访问令牌(Access Token)和刷新令牌(Refresh Token),并对受保护资源的访问进行认证和授权。) |
spring-boot-starter-oauth2-client |
使用 Spring Security 的 OAuth2/OpenID Connect 客户端功能的启动器(
) |
spring-boot-starter-oauth2-resource-server |
使用 Spring Security 的 OAuth2 资源服务器功能的启动器(OAuth 2.0 资源服务器是实现 OAuth 2.0 协议的一部分,负责保护受限资源,并验证来自客户端的访问令牌,以确保只有经过授权的用户可以访问资源。) |
spring-boot-starter-pulsar |
为 Apache Pulsar 使用 Spring 的启动程序(Apache Pulsar 是一个开源的分布式消息系统,具有高可用性、高性能和可扩展性,适用于构建实时数据处理和消息传递应用程序。) |
spring-boot-starter-pulsar-reactive |
将 Spring 用于 Apache Pulsar Reactive 的启动器 |
spring-boot-starter-quartz |
使用quartz调度程序的启动器 |
spring-boot-starter-rsocket |
用于构建 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 服务的启动器(Spring Boot 提供的用于构建基于 SOAP(Simple Object Access Protocol)的 Web 服务的 Starter。SOAP 是一种基于 XML 的协议,用于在网络上交换结构化信息,并支持跨平台和跨语言的通信。) |
Spring-boot-starter-webflux |
使用 Spring Framework 的响应式Web 支持构建 WebFlux 应用程序的启动器 |
spring-boot-starter-websocket |
使用 Spring Framework 的 MVC WebSocket 支持构建 WebSocket 应用程序的启动器(WebSocket 是一种在 Web 应用程序中实现双向通信的协议,它允许客户端和服务器之间建立持久性的连接,并实时地交换数据。) |
除应用启动器外,还可使用以下启动器为生产做好准备
特点
表 2.Spring Boot 生产启动器
名称 |
说明 |
spring-boot-starter-actuator |
使用 Spring Boot Actuator 的启动器,提供生产就绪功能,可帮助您监控和管理应用程序 |
最后,Spring Boot 还包括以下启动器,如果你想排除或切换特定的技术层面,可以使用这些启动器:
名称 |
说明 |
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 容器的启动器。Spring-boot-starter-web 使用的默认服务器容器启动器 |
spring-boot-starter-undertow |
将 Undertow 用作嵌入式 servlet 容器的启动器。spring-boot- starter-tomcat 的替代方案 |
要了解如何交换技术层面,请参阅 如何切换web服务器 和 日志系统 的文档。
TIP
有关其他社区贡献的启动器列表,请参阅 GitHub 上 spring-boot-starters 模块中的 README 文件 https://github.com/spring-projects/spring-boot/tree/main/spring-boot-project/spring-boot-starters/README.adoc
6.2. 构建代码
Spring Boot 的运行不需要任何特定的代码布局。不过,有一些最佳实践会有所帮助。
如果您希望根据领域对项目进行结构化,可以考虑使用 Spring Modulith。
6.2.1. 使用 "默认 "软件包
当一个类没有包含包声明时,它被认为是在 "默认包 "中。一般不鼓励使用 "默认包",应避免使用。它会给使用 @ComponentScan、@ConfigurationPropertiesScan、@EntityScan 或 @SpringBootApplication 注解的 Spring Boot 应用程序带来特别的问题,因为每个 jar 中的每个类都会被读取。
我们建议您遵循 Java 推荐的软件包命名约定,并使用相反的域名(例如 com.example.project)。
6.2.2. 定位主应用程序类
我们通常建议将主应用程序类放置在其他类之上的根包中。@SpringBootApplication注解通常放置在您的主类上,并且它隐式地为某些项定义了一个基本的“搜索包”。例如,如果您正在编写一个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 文件 将 声明 的 方法 方法、 与 声明 的 基本
@SpringBootApplication,如下所示:
Java
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); } }
Kotlin
import org.springframework.boot.autoconfigure.SpringBootApplication import org.springframework.boot.runApplication @SpringBootApplication class MyApplication fun main(args: Array<String>) { runApplication<MyApplication>(*args) }
6.3. 配置类
Spring Boot更倾向于使用基于Java的配置方式。虽然可以使用XML源配置SpringApplication,但通常我们建议您的主要配置源是一个单独的@Configuration类。通常情况下,定义了主方法的类是作为主要的@Configuration的一个很好的选择。
(
在Spring Boot中,通常将包含`main`方法的类作为主要的`@Configuration`类。这是因为这个类除了承担应用程序的启动职责,还可以用于配置应用程序的一些基本设置。以下是一个简单的示例:
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); } // 可以在这里添加其他配置 }
在这个示例中,`MyApplication` 类包含了`main`方法,并使用`@SpringBootApplication`注解标记。这个注解不仅表示这是一个Spring Boot应用程序的入口点,还包含了`@Configuration`、`@EnableAutoConfiguration`和`@ComponentScan`等注解,使得这个类成为主要的配置类。
你可以在`MyApplication`类中添加其他配置,例如数据源配置、Bean的定义等。这样,你可以在一个地方集中管理应用程序的主要配置。
总的来说,将`main`方法的类作为主要的`@Configuration`类是一个常见的做法,有助于保持应用程序的清晰性和一致性。
)
TIP
互联网上发布了许多使用 XML 配置的 Spring 配置示例。如果可能,请尽量使用基于 Java 的等效配置。搜索 Enable* 注解是一个很好的起点。
6.3.1. 导入其他配置类
您不必将所有 @Configuration 都放在一个类中。@Import 注解可用于导入其他配置类。或者,也可以使用 @ComponentScan 自动获取所有 Spring 组件,包括 @Configuration 类。
6.3.2. 导入 XML 配置
如果您绝对必须使用基于 XML 的配置,我们建议您仍从 @Configuration 类开始。然后,您可以使用 @ImportResource 注解来加载 XML 配置文件。
(译者注:
以下是一个示例,演示如何在Spring Boot中使用XML配置文件:
首先,创建一个applicationContext.xml
文件,其中包含您需要的XML配置:
<!-- applicationContext.xml --> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <!-- 定义一个简单的Bean --> <bean id="messageService" class="com.example.services.MessageService"> <property name="message" value="Hello from XML configuration!" /> </bean> </beans>
接下来,创建一个MessageService
类,以便在XML配置中引用:
package com.example.services; public class MessageService { private String message; public void setMessage(String message) { this.message = message; } public String getMessage() { return message; } }
然后,在Spring Boot应用程序中,创建一个Java配置类,并使用@ImportResource
注解来加载XML配置文件:
package com.example.config; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.ImportResource; @Configuration @ImportResource("classpath:applicationContext.xml") public class XmlConfiguration { // 这里可以添加其他的配置 }
在这个示例中,XmlConfiguration
类被标记为@Configuration
,表明它是一个Spring的配置类。然后,使用@ImportResource
注解引入了applicationContext.xml
文件,以加载XML配置。
现在,您可以在Spring Boot应用程序中使用XML配置文件中定义的Bean,例如:
package com.example; import com.example.services.MessageService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.CommandLineRunner; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.annotation.Bean; @SpringBootApplication public class Application { @Autowired private MessageService messageService; public static void main(String[] args) { SpringApplication.run(Application.class, args); } @Bean public CommandLineRunner runner() { return args -> System.out.println(messageService.getMessage()); } }
在这个示例中,我们通过@Autowired
注解注入了MessageService
Bean,并在CommandLineRunner
的实现中使用它来打印消息。
这样,您就可以在Spring Boot应用程序中使用XML配置文件进行配置。
)
6.4. 自动配置
Spring Boot 自动配置会尝试根据您添加的 jar 依赖关系自动配置您的 Spring 应用程序。例如,如果 HSQLDB 位于类路径上,而您没有手动配置任何数据库连接 Bean,那么 Spring Boot 就会自动配置内存数据库。
您需要通过将@EnableAutoConfiguration或@SpringBootApplication注解添加到您的@Configuration类中,以选择自动配置。
TIP
你只能添加一个 @SpringBootApplication 或 @EnableAutoConfiguration 注解。我们通常建议只在主 @Configuration 类中添加其中一个注解。
6.4.1. 逐步取代自动配置
自动配置是非侵入性的。您随时可以开始定义自己的配置来替换自动配置的特定部分。例如,如果您添加自己的DataSource bean,则默认的内嵌数据库支持将会被取消。
如果您需要查看当前应用了哪些自动配置以及原因,请使用 --debug 开关启动您的应用程序。这样做会启用一些核心日志记录器的调试日志,并在控制台上记录条件报告。
6.4.2. 禁用特定自动配置类
如果发现不需要的特定自动配置类被应用,可以使用 @SpringBootApplication 的排除属性来禁用它们,如下例所示:
Java
import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; @SpringBootApplication(exclude = { DataSourceAutoConfiguration.class }) public class MyApplication { }
科特林
import org.springframework.boot.autoconfigure.SpringBootApplication import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration @SpringBootApplication(exclude = [DataSourceAutoConfiguration::class]) class MyApplication
如果类不在类路径上,您可以使用注解的excludeName属性,并指定完全限定的名称。如果您更喜欢使用@EnableAutoConfiguration而不是@SpringBootApplication,exclude和excludeName也是可用的。最后,您还可以通过使用spring.autoconfigure.exclude属性来控制要排除的自动配置类列表。
(译者注:
下面是一个示例,演示如何使用`spring.autoconfigure.exclude`属性来排除自动配置类:
假设您希望排除默认的数据源自动配置,您可以在`application.properties`(或`application.yml`)文件中添加以下配置:
```properties
spring.autoconfigure.exclude=org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration
```
这将排除`DataSourceAutoConfiguration`类,从而禁用默认的数据源自动配置。您可以根据需要添加其他自动配置类的完全限定名称,以排除它们。
)
提示:您可以在注解级别和使用属性两种方式来定义排除项。
注意
尽管自动配置类是公共的,但被视为公共API的部分仅限于类的名称,该名称可用于禁用自动配置。这些类的实际内容,如嵌套配置类或bean方法,仅供内部使用,我们不建议直接使用这些内容。(译者注:其实这里的公共类只是类名称而不是内容,访问权限修饰符不适用)
6.4.3. 自动配置软件包
自动配置包是各种自动配置功能在扫描实体和 Spring Data 资源库时默认查找的包。@EnableAutoConfiguration 注解(可直接使用,也可在 @SpringBootApplication 中使用)决定了默认的自动配置包。可使用 @AutoConfigurationPackage 注解配置其他软件包。
自动配置包是各种自动配置功能在默认情况下进行扫描的包,用于查找诸如实体和Spring Data存储库等内容。@EnableAutoConfiguration注解(可以直接使用@EnableAutoConfiguration注解,也可以通过@SpringBootApplication注解的存在来使用。译者注:在一个类上添加@SpringBootApplication注解时,它实际上包含了@EnableAutoConfiguration注解的功能,因此可以说通过@SpringBootApplication注解的存在,间接地启用了@EnableAutoConfiguration的功能。)确定默认的自动配置包。可以使用@AutoConfigurationPackage注解来配置其他包。
6.5. Spring Beans 和依赖注入
您可以自由使用任何标准的 Spring Framework 技术来定义您的 Bean 及其注入的依赖关系。我们通常建议使用构造器注入来连接依赖关系,并使用 @ComponentScan 来查找 Bean。
如果您按照上述建议(将应用程序类放置在顶层包中)组织代码,您可以在不带任何参数的情况下添加@ComponentScan注解,或者使用@SpringBootApplication注解,后者隐式地包含了它。您的所有应用程序组件(@Component、@Service、@Repository、@Controller等)都会自动注册为Spring Bean。(译者注:这样我们可以在任何地方使用这些bean对象)
下面的示例展示了一个 @Service Bean,该 Bean 使用构造函数注入来获取所需的
RiskAssessor bean:
Java
import org.springframework.stereotype.Service; @Service public class MyAccountService implements AccountService { private final RiskAssessor riskAssessor; public MyAccountService(RiskAssessor riskAssessor) { this.riskAssessor = riskAssessor; } // ... }
科特林
import org.springframework.stereotype.Service @Service class MyAccountService(private val riskAssessor: RiskAssessor) : AccountService
如果一个 Bean 有多个构造函数,则需要用
@Autowired:
import java.io.PrintStream; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @Service public class MyAccountService implements AccountService { private final RiskAssessor riskAssessor; private final PrintStream out; @Autowired public MyAccountService(RiskAssessor riskAssessor) { this.riskAssessor = riskAssessor; this.out = System.out; } public MyAccountService(RiskAssessor riskAssessor, PrintStream out) { this.riskAssessor = riskAssessor; this.out = out; } // ... }
科特林
import org.springframework.beans.factory.annotation.Autowired import org.springframework.stereotype.Service import java.io.PrintStream @Service class MyAccountService : AccountService { private val riskAssessor: RiskAssessor private val out: PrintStream @Autowired constructor(riskAssessor: RiskAssessor) { this.riskAssessor = riskAssessor out = System.out } constructor(riskAssessor: RiskAssessor, out: PrintStream) { this.riskAssessor = riskAssessor this.out = out } // ... }
TIP
请注意,使用构造函数注入可以将 riskAssessor 字段标记为final字段,表示以后不能更改。
当类定义了两个以上的有参构造函数,并且没有明确指定哪一个构造函数用于实例化对象时,Spring会选择一个默认的构造函数进行实例化。通常情况下,它会选择参数列表最短的构造函数。如果多个构造函数的参数数量相同,则选择最早定义的构造函数。
然而,如果这些构造函数中有一个带有@Autowired注解,Spring会优先选择带有@Autowired注解的构造函数进行实例化,而不考虑参数数量。这样做的目的是为了确保通过依赖注入的方式注入依赖项。
如果有多个带有@Autowired注解的构造函数,Spring会选择其中一个。通常情况下,它会选择参数列表最短的带有@Autowired注解的构造函数。如果多个@Autowired注解的构造函数的参数数量相同,则选择最早定义的构造函数。
我在总结一下spring中的组件作用
-
@Component: 是一个泛化的组件注解,用于指示一个类是Spring管理的组件。通常用于表示普通的Spring管理的Bean。
-
@Controller: 用于标记控制器类,通常用于Spring MVC应用程序中。控制器处理HTTP请求,并将响应返回给客户端。
-
@Service: 用于标记服务类,通常用于业务逻辑的实现。服务类通常被用来执行业务逻辑操作,并被其他组件调用。
-
@Repository: 用于标记数据访问对象(DAO)类。@Repository通常用于持久层,用于将数据库访问、数据查询等操作封装到单独的类中。
-
@Configuration: 用于标记配置类,通常用于定义Spring应用程序的配置信息。配置类可以包含@Bean注解的方法,用于定义Spring管理的Bean。
-
@RestController: 是@Controller和@ResponseBody的组合注解,用于标记RESTful风格的控制器类。
-
@ComponentScan: 用于指示Spring框架在指定的包及其子包中搜索组件,并将它们注册为Spring管理的Bean。
-
@Autowired: 用于自动装配依赖项。当一个组件需要使用其他组件时,可以使用@Autowired注解自动将依赖项注入到组件中。
-
@Qualifier: 与@Autowired注解一起使用,用于指定要注入的Bean的限定符。当有多个匹配的Bean时,可以使用@Qualifier注解指定要注入的具体Bean。
-
@Value: 用于注入外部配置属性的值。@Value注解可以用于将配置文件中的属性值注入到组件的字段、方法参数或构造函数参数中。
-
@Aspect: 用于标记切面类,通常与其他切面注解(如@Before、@After、@Around等)一起使用,实现面向切面编程(AOP)。
-
@Transactional: 用于标记事务管理方法,通常用于声明式事务管理。@Transactional注解可以应用于类级别或方法级别,以控制事务的行为。
这些组件和注解是Spring框架中常用的一些组件,用于构建和管理Spring应用程序的不同部分。通过使用这些组件,可以更加方便地实现依赖注入、面向切面编程、声明式事务管理等功能。
使用@Component注解标记一个类,具有以下作用:
自动扫描和注册: Spring会自动扫描应用程序中的组件,并将标记了@Component注解的类注册为Spring上下文中的Bean。这样,这些组件就可以在应用程序的其他地方进行注入和使用。
依赖注入: 标记为组件的类可以通过依赖注入的方式,自动将其他组件注入到其中。例如,使用@Autowired注解可以将依赖注入到组件中。
声明式事务管理: 一些Spring的特性,比如声明式事务管理(如@Transactional注解),只能应用在受Spring管理的Bean上。因此,标记一个类为组件可以让它受到Spring的事务管理。
AOP支持: 使用组件注解标记的类可以被Spring框架用于实现面向切面编程(AOP)。通过在组件类的方法上添加AOP切面,可以实现诸如日志记录、性能监控等功能。
总之一句话就是,spirng框架会自动实例化标记为组件的类,就是所谓的注册,实例化的方法上面已经详细阐述了,在其他的类中就可以使用该实例化的类,也就是所谓的依赖注入。为了便于理解,spirng框架可以理解为一个装有豆子的罐头,里面的豆子就是一个组件,罐子里的豆子可以是我们自己生产的普通豆子,例如注解@Component,也可以是厂家出厂前就已经生产好的特殊的豆子,比如Web服务器和web mvc框架等。这些Bean是“厂家出厂前就已经生产好的”,开发人员只需配置web服务器和webmvc之间的关系即可在web应用程序中使用它们。也就是手动配置。我们想要吃豆子只需要在罐头里取出即可,也就是依赖注入。但是我们每次想吃web豆子前总是要配置一下太繁琐,我们能不能零配置吃豆子呢,答案是肯定的。解决办法就是官方推出一个web罐头即可,也就是springbootweb,他将所有web有关的豆子比如tomcat、spirngmvc等等打包成一个罐头,并配置好他们的关系。我们打开罐头就直接可以吃豆子了。)
6.6. 使用 @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; // Same as @SpringBootConfiguration @EnableAutoConfiguration @ComponentScan @SpringBootApplication public class MyApplication { public static void main(String[] args) { SpringApplication.run(MyApplication.class, args); } }
Kotlin
import org.springframework.boot.autoconfigure.SpringBootApplication import org.springframework.boot.runApplication // same as @SpringBootConfiguration @EnableAutoConfiguration @ComponentScan @SpringBootApplication class MyApplication fun main(args: Array<String>) { runApplication<MyApplication>(*args) }
注意
@SpringBootApplication 还提供了别名来自定义
@EnableAutoConfiguration 和 @ComponentScan.
(译者注:
@SpringBootApplication 提供了一些别名来定制 @EnableAutoConfiguration 和 @ComponentScan 的属性。以下是一些示例:
1. 使用 `exclude` 属性排除特定的自动配置类:
```java
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class, SecurityAutoConfiguration.class}) public class MyApplication { public static void main(String[] args) { SpringApplication.run(MyApplication.class, args); } }
```
在这个示例中,我们使用了 `exclude` 属性来排除了 `DataSourceAutoConfiguration` 和 `SecurityAutoConfiguration` 这两个自动配置类。
2. 使用 `scanBasePackages` 属性指定组件扫描的基础包:
```java
@SpringBootApplication(scanBasePackages = {"com.example.package1", "com.example.package2"}) public class MyApplication { public static void main(String[] args) { SpringApplication.run(MyApplication.class, args); } }
```
在这个示例中,我们使用了 `scanBasePackages` 属性来指定了组件扫描的基础包,Spring Boot 将会在指定的包及其子包下进行组件扫描。
)
注意:
这些功能都不是强制性的,你可以选择用它所启用的任何功能来替代这个单一注解。例如,您可能不想在应用程序中使用组件扫描或配置属性扫描:
Java
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); } }
Kotlin
import org.springframework.boot.SpringBootConfiguration import org.springframework.boot.autoconfigure.EnableAutoConfiguration import org.springframework.boot.docs.using.structuringyourcode.locatingthemainc lass.MyApplication import org.springframework.boot.runApplication import org.springframework.context.annotation.Import @SpringBootConfiguration(proxyBeanMethods = false) @EnableAutoConfiguration @Import(SomeConfiguration::class, AnotherConfiguration::class) class MyApplication fun main(args: Array<String>) { runApplication<MyApplication>(*args) }
在这个例子中,MyApplication 就像任何其他的 Spring Boot 应用程序一样,除了 @Component 注解的类和 @ConfigurationProperties 注解的类不会被自动检测到,并且用户定义的 Bean 被显式地导入(见 @Import)。
6.7. 运行应用程序
将应用程序打包为 jar 并使用嵌入式 HTTP 服务器的最大优势之一是,您可以像运行其他应用程序一样运行应用程序。该示例适用于调试 Spring Boot 应用程序。您不需要任何特殊的集成开发环境插件或扩展。
注意
本节仅涉及基于 jar 的打包。如果您选择将应用程序打包为 war 文件,请参阅服务器和 IDE 文档。
6.7.1. 从集成开发环境运行
您可以将 Spring Boot 应用程序作为 Java 应用程序从集成开发环境中运行。不过,您首先需要导入您的项目。导入步骤因集成开发环境和构建系统而异。大多数 IDE 可以直接导入 Maven 项目。例如,Eclipse 用户可以从 "文件 "菜单中选择 "导入... → 现有 Maven 项目"。
如果无法直接将项目导入集成开发环境,可以使用构建插件生成集成开发环境元数据。Maven 包括用于 Eclipse 和 IDEA 的插件。Gradle 为各种集成开发环境提供了插件。
TIP
如果不小心运行web应用程序两次,就会出现 "端口已在使用中 "的错误。Spring Tools 用户可以使用 "重新启动"(Relaunch)按钮而不是 "运行"(Run)按钮来确保关闭任何现有实例。
6.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
6.7.3. 使用 Maven 插件
Spring Boot Maven 插件包含一个 run 目标,可以用来快速编译和运行你的应用程序。应用程序以展开的形式运行,就像在你的集成开发环境(IDE)中一样。以下示例展示了运行 Spring Boot 应用程序的典型 Maven 命令:
(译者注:
"Exploded" 形式指的是将应用程序以目录结构的形式展开并运行,而不是将应用程序打包成单个的压缩文件(如 JAR 文件)并运行。在这种形式下,应用程序的各个组件(类、资源文件等)被解压到一个目录中,并且可以直接在该目录中运行。这种方式类似于在集成开发环境(IDE)中运行应用程序时的方式,使得开发人员可以更容易地调试和修改应用程序的代码和配置。
)
$ mvn spring-boot:run
(译者注:命令中的spring-boot表示构建插件的名称,这里使用缩写别名,run表示插件提供的一种功能)
您可能还想使用 MAVEN_OPTS 操作系统环境变量,如下例所示:
$ export MAVEN_OPTS=-Xmx1024m6.7.4. 使用 Gradle 插件
Spring Boot Gradle 插件还包含一个 bootRun 任务,可用于以展开形式运行应用程序。只要应用 org.springframework.boot 和 java 插件,就会添加 bootRun 任务,如下示例所示:
$ gradle bootRun
您可能还想使用 JAVA_OPTS 操作系统环境变量,如下例所示:
$ export JAVA_OPTS=-Xmx1024m
6.7.5. 热交换
由于Spring Boot应用程序是普通的Java应用程序,因此JVM热交换应该可以直接使用。 JVM热交换在可以替换的字节码方面存在一定的限制。对于更完整的解决方案,可以使用 JRebel。https://www.jrebel.com/products/jrebel
spring-boot-devtools模块还包括对快速应用程序重启的支持。有关详细信息,请参阅热交换“How-to”。
(译者注:热交换(Hot Swapping)是一种在应用程序运行时无需停止应用程序就可以替换部分代码的能力。在Java中,热交换通常指的是在应用程序运行期间修改和重新加载类文件,以实现代码更新而无需重新启动应用程序。这种能力可以提高开发效率,减少代码修改后重新启动应用程序所需的时间,特别是在开发和调试阶段。然而,热交换的实现存在一定的限制,不是所有的代码修改都能够成功地进行热交换。)
6.8. 开发人员工具
Spring Boot 包含了一组额外的工具,可以让应用程序开发体验更加愉快。spring-boot-devtools 模块可以被包含在任何项目中,以提供额外的开发时功能。要包含 devtools 支持,只需将该模块的依赖添加到你的构建中,如下所示 Maven 和 Gradle 的示例代码:
Maven
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <optional>true</optional> </dependency> </dependencies>
Gradle
dependencies { developmentOnly("org.springframework.boot:spring-boot-devtools") }
注意
Devtools可能会导致类加载问题,特别是在多模块项目中。
《诊断类加载问题》解释了如何诊断和解决这些问题。
注意
当运行一个完全打包的应用程序时,开发工具会自动禁用。如果你的应用程序是从 java -jar 启动的,或者它是从一个特殊的类加载器启动的,那么它被认为是一个“生产应用程序”。你可以通过使用 spring.devtools.restart.enabled 系统属性来控制这种行为。要启用开发工具,无论使用何种类加载器启动你的应用程序,都可以设置 -Dspring.devtools.restart.enabled=true 系统属性。这绝对不能在生产环境中执行,因为运行开发工具会存在安全风险。要禁用开发工具,排除依赖项或设置 -Dspring.devtools.restart.enabled=false 系统属性。
TIP
在 Maven 中将依赖关系标记为可选,或在 Gradle 中使用 developmentOnly 配置(如上图所示),可以防止 devtools 被临时应用到使用项目的其他模块中。
假设你的项目有两个模块:模块A和模块B。在模块A中,你使用了spring-boot-devtools依赖来提供开发时的支持。但是你不想将这个依赖传递给模块B,因为模块B可能是一个独立的应用程序或者不需要开发工具支持。在Maven中,你可以将spring-boot-devtools依赖标记为可选,这样它就不会被传递给其他模块。
)TIP
重新打包的归档文件默认不包含 devtools。如果要使用某种远程 devtools 功能(译者注:远程 devtools 功能指的是 Spring Boot DevTools 提供的一种功能,允许你在开发环境中对远程服务器上运行的应用程序进行调试和修改。通过远程 devtools 功能,你可以在本地进行代码修改,然后将修改的代码实时部署到远程服务器上的应用程序中,而无需手动重启服务器或重新部署应用程序。这样可以提高开发效率,加快开发迭代周期。就好像你亲自在服务器上操作一样。),则需要将其包含在内。使用 Maven 插件时,将 excludeDevtools 属性设置为 false。使用 Gradle 插件时,配置任务的类路径以包含 developmentOnly 配置。
6.8.1. 诊断类加载问题
正如 "重启与重载 "部分所述,重启功能是通过使用两个类加载器来实现的。对于大多数应用程序来说,这种方法效果很好。但有时也会造成类加载问题,特别是在多模块项目中。
要诊断类加载问题是否确实由 devtools 及其两个类加载器引起,请尝试禁用重启。如果问题得到解决,请自定义重启类加载器,使其包含整个项目。
6.8.2. 属性默认值
Spring Boot 支持的一些库使用缓存来提高性能。例如,模板引擎会缓存已编译的模板,以避免重复解析模板文件。此外,Spring MVC 还能在提供静态资源时为响应添加 HTTP 缓存标头。
虽然缓存在生产中非常有用,但在开发过程中可能会适得其反,使您无法看到刚刚在应用程序中做出的更改。因此,spring- boot-devtools 默认禁用缓存选项。
缓存选项通常由application.properties文件中的设置来配置。例如,Thymeleaf 提供了 spring.thymeleaf.cache 属性。spring-boot-devtools 模块会自动应用合理的开发时配置,而无需手动设置这些属性。
下表列出了应用的所有属性:
名称 |
默认值 |
server.error.include-binding-errors(指示是否在错误响应中包含绑定错误信息。例如,在用户注册表单提交时,如果用户名长度不符合要求,错误响应中将包含有关绑定错误的详细信息,如错误码、错误消息、字段名等。) |
always |
server.error.include-message( 指示是否在错误响应中包含错误消息。例如,当用户访问一个不存在的页面时,错误响应中可能包含有关页面未找到的消息。) |
always |
server.error.include-stacktrace(指示是否在错误响应中包含堆栈跟踪信息。例如,在开发阶段,如果应用程序出现未捕获的异常,则错误响应中可能包含有关异常发生位置的堆栈跟踪信息。) |
always |
server.servlet.jsp.init-parameters.development(初始化参数,用于指示是否处于开发模式。例如,可以将其设置为true,以在开发环境中启用JSP的某些特定功能或调试选项。例如,可能会打开 JSP 编译器的调试信息,以便在浏览器中查看更详细的错误信息或源代码映射。) |
true |
server.servlet.session.persistent(指示会话是否应该持久化。例如,在某些情况下,您可能希望会话持久化,以确保即使服务器重启,会话数据仍然保留。) |
true |
spring.docker.compose.readiness.wait(Docker Compose 准备就绪的等待时间。例如,您可能希望在启动应用程序之前等待一段时间,以确保所有必要的服务已经准备就绪。) |
only-if-started |
spring.freemarker.cache(指示是否启用 FreeMarker 模板缓存。例如,在使用FreeMarker作为模板引擎的应用程序中,启用缓存可以提高模板渲染的性能和效率。) |
false |
spring.graphql.graphiql.enabled( 指示是否启用 GraphQL 的 GraphiQL 工具。例如,在开发阶段,您可以启用GraphiQL来测试和调试GraphQL查询。GraphiQL 是一个基于浏览器的交互式 GraphQL 查询界面,能够帮助开发人员在浏览器中方便地构建和测试 GraphQL 查询。) |
true |
spring.groovy.template.cache(指示是否启用 Groovy 模板缓存。例如,在使用Groovy模板引擎的应用程序中,启用缓存可以提高模板的渲染性能。) |
false |
spring.h2.console.enabled(指示是否启用 H2 控制台。例如,当开发人员需要查看和管理应用程序中的H2数据库时,可以通过访问/h2-console路径来打开H2控制台) |
true |
spring.mustache.servlet.cache( 指示是否启用 Mustache 模板缓存。例如,在使用Mustache作为模板引擎的应用程序中,启用缓存可以提高模板渲染的性能和效率。) |
false |
spring.mvc.log-resolved-exception( 指示是否记录已解析的异常。例如,您可能希望在日志中记录已解析的异常,以便更好地了解应用程序的运行状况和错误处理情况。,Spring MVC 框架能够捕获并处理的异常。这些异常可能是由应用程序代码中的错误、请求参数验证失败、请求的资源不存在等引起的。 启用 spring.mvc.log-resolved-exception 可以让 Spring MVC 框架在处理完异常后将异常信息记录到日志中,这样可以更好地了解应用程序的运行状况和错误处理情况。记录已解析的异常有助于开发人员进行故障排除、监控应用程序的健康状况以及改进错误处理机制。 通常,开启这个选项是一个良好的实践,特别是在开发和测试阶段。但在生产环境中,可能需要根据实际情况进行评估,以确保日志记录的信息量不会过于庞大,以免影响性能或增加维护成本。 ) |
true |
spring.reactor.netty.shutdown-quiet-period( Reactor Netty 关闭时的安静期。例如,您可以设置一个安静期,在此期间允许正在处理的请求完成,然后再关闭Netty服) |
0s |
spring.template.provider.cache(指示是否启用模板提供程序缓存。例如,在应用程序中使用多个模板引擎时,启用缓存可以提高模板的渲染性能。) |
false |
spring.thymeleaf.cache( 指示是否启用 Thymeleaf 模板缓存。例如,在使用Thymeleaf作为模板引擎的应用程序中,启用缓存可以提高模板的渲染性能。) |
false |
spring.web.resources.cache.period( 静态资源缓存周期。例如,您可以设置静态资源的缓存周期,以控制浏览器何时重新请求资源。) |
0 |
spring.web.resources.chain.cache(静态资源链缓存。例如,您可以配置静态资源链缓存以提高静态资源的访问性能和效率。 静态资源链(Static Resource Chain)通常是指在 Web 应用程序中对静态资源(如样式表、JavaScript 文件、图像等)进行版本控制和管理的一种机制。其主要目的是确保在资源更新时,浏览器可以及时获取最新版本的资源,同时通过缓存等机制减少对服务器的请求,提高页面加载性能。 举例来说,假设我们有一个名为 例如,原始的样式表文件名为 另一种常见的做法是使用文件内容的哈希值作为版本标识。例如,原始样式表文件名仍然为 静态资源链的实现方式可以根据具体情况和需求进行调整,但总的来说,其目标都是确保静态资源在更新时能够及时地被浏览器获取,同时利用缓存等机制提高性能。 ) |
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 配置属性。
(
`logging.level.web=DEBUG` 和 `spring.mvc.log-request-details`、`spring.codec.log-request-details` 之间有一些区别,主要体现在以下几个方面:
1. **作用对象**:
- `logging.level.web=DEBUG`:指定了整个 `web` 日志组的日志级别为 DEBUG。这会影响所有 Web 相关的日志记录,包括框架和应用程序本身。
- `spring.mvc.log-request-details`、`spring.codec.log-request-details`:分别指定了 Spring MVC 和 Spring WebFlux 的特定功能的日志记录配置。
2. **详细程度**:
- `logging.level.web=DEBUG`:控制整个 `web` 日志组的日志级别,会影响到所有与 Web 相关的日志记录,包括请求处理、响应处理、过滤器、拦截器等。它的作用范围更广,而且更一般化。
- `spring.mvc.log-request-details`、`spring.codec.log-request-details`:针对特定功能或模块的日志记录详细级别进行配置。例如,`spring.mvc.log-request-details` 仅控制 Spring MVC 框架记录请求详情的功能。
3. **灵活性**:
- `logging.level.web=DEBUG`:是一种更为全局的设置,影响整个 `web` 日志组的行为。虽然它更为便捷,但可能不够灵活,无法针对特定的功能进行细粒度的配置。
- `spring.mvc.log-request-details`、`spring.codec.log-request-details`:提供了更为细粒度的配置选项,允许针对特定功能进行个性化设置。这使得可以更精确地控制日志记录的详细级别,以满足具体的需求。
综上所述,`logging.level.web=DEBUG` 是一个更为全局的设置,适用于整个 Web 日志组的调试配置;而 `spring.mvc.log-request-details`、`spring.codec.log-request-details` 则提供了更为特定功能的配置选项,可以对请求详情记录的粒度进行更细致的控制。
)
6.8.3. 自动重启
只要类路径上的文件发生变化,使用 spring-boot-devtools 的应用程序就会自动重新启动。在集成开发环境中工作时,这是一项非常有用的功能,因为它能为代码更改提供非常快速的反馈回路。默认情况下,classpath 上指向目录的任何条目都会受到监控,以防发生变化。请注意,某些资源(如静态资产和视图模板)不需要重新启动应用程序。
触发重启
由于 DevTools 会监控类路径资源,因此触发重启的唯一方法就是更新类路径。无论您使用的是集成开发环境还是构建插件,都必须重新编译修改后的文件才能触发重启。更新类路径的方式取决于你使用的工具:(实际上,当您在IDE中修改源代码并保存后,DevTools会监控到这些修改并触发重新编译,而不需要您手动运行编译命令。这意味着只要您保存了修改,DevTools会自动将这些变更重新编译到应用程序中,并且通常会触发应用程序的重启,以便应用程序能够加载最新的代码。)
• 在 Eclipse 中,保存修改后的文件将更新类路径并触发重启。
• 在 IntelliJ IDEA 中,构建项目(选择 Build → Build Project)具有相同的效果。
• 如果使用构建插件,对于 Maven 运行 mvn compile 或对于 Gradle 运行 gradle build 将触发重启。
实际上,当您在IDE中修改源代码并保存后,DevTools会监控到这些修改并触发重新编译,而不需要您手动运行编译命令。这意味着只要您保存了修改,DevTools会自动将这些变更重新编译到应用程序中,并且通常会触发应用程序的重启,以便应用程序能够加载最新的代码。
(
类路径(Classpath)是指 Java 虚拟机(JVM)在执行 Java 程序时搜索类和资源文件的位置。在编译和运行 Java 程序时,类路径是 JVM 用来查找类文件、库文件和其他资源文件的一个重要设置。
类路径可以包括以下几种内容:
1. 目录:指向包含编译后的 `.class` 文件的目录。
2. JAR 文件:Java 归档文件,其中包含了一组类文件和资源文件。
3. ZIP 文件:与 JAR 文件类似,也可以包含一组类文件和资源文件。
在开发 Java 应用程序时,你可以通过指定类路径来告诉 JVM 在哪里查找类和资源文件。通常情况下,类路径可以通过以下几种方式指定:
1. 使用命令行参数 `-classpath` 或 `-cp`:通过在命令行中使用 `-classpath` 或 `-cp` 参数来指定类路径。
2. 使用环境变量 CLASSPATH:你可以设置一个名为 CLASSPATH 的环境变量来指定类路径。不过,这种方式不太常见,因为它会影响所有的 Java 程序,容易引起混乱。
3. 在 Java 应用程序的 MANIFEST.MF 文件中指定 Class-Path 属性:对于可执行的 JAR 文件,你可以在其 MANIFEST.MF 文件中指定 Class-Path 属性来设置类路径。
例如,如果你有一个名为 `MyApp.java` 的 Java 源文件,编译后生成了 `MyApp.class` 文件,而该文件又依赖于一个名为 `MyLibrary.jar` 的 JAR 文件,你可以通过以下方式指定类路径来运行该程序:
```
java -cp .:MyLibrary.jar MyApp
```
这个命令告诉 JVM 在当前目录和 `MyLibrary.jar` 文件中查找类文件。
)
注意
如果使用构建插件通过 Maven 或 Gradle 重新启动,则必须将分叉设置为启用。如果禁用分叉,devtools 使用的隔离应用程序类加载器将无法创建,重启将无法正常运行。(这里的分叉可以理解为重新创建一个类加载器用于加载类和资源)
隔离应用程序类加载器(Isolated Application Classloader)是 Spring Boot DevTools 中的一个关键概念,用于在应用程序重启时加载应用程序的类和资源。它的作用是确保在重启过程中应用程序的类和资源能够被正确地重新加载,同时避免与开发工具自身的类和资源产生冲突。
具体来说,隔离应用程序类加载器会在应用程序启动时创建一个独立的类加载器实例,用于加载应用程序的类和资源。这个类加载器与开发工具使用的类加载器是相互隔离的,因此在重启过程中不会相互干扰。
使用隔离应用程序类加载器有助于解决以下问题:
1. **类加载器冲突**:如果应用程序与开发工具使用的类加载器相同,可能会导致类加载器冲突,造成类版本不一致或类重复加载等问题。
2. **资源泄露**:开发工具可能会在运行时修改应用程序的类和资源文件,如果不进行隔离,可能会导致资源泄露或资源文件被覆盖的问题。
通过使用隔离应用程序类加载器,Spring Boot DevTools 确保了应用程序在重启过程中能够正确加载最新的类和资源,同时保持与开发工具的独立性。
请注意,对于某些开发工具或特定的应用程序配置,可能需要手动配置隔离应用程序类加载器以确保正确的工作。
在 Spring Boot 项目中,您可以使用 Maven Surefire 插件来执行单元测试,并通过配置来启用分叉功能。
要在 Spring Boot 项目中启用 Maven Surefire 插件的分叉功能,您可以在 Maven 项目的 `pom.xml` 文件中添加如下配置:
```xml
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version><!-- Surefire 插件的版本号 --></version>
<configuration>
<forkCount>1</forkCount>
</configuration>
</plugin>
</plugins>
</build>
```
在这个配置中,`<forkCount>` 元素指定了分叉的数量。将其设置为 `1` 表示启用分叉功能,每个测试类将在独立的 JVM 进程中执行。这有助于确保测试之间的隔离,以避免测试之间的相互影响导致的问题。
请注意,这个配置是在 Maven 项目的 `pom.xml` 文件中进行的,确保您将正确的插件版本号和其他相关配置替换到上述示例中。
)TIP
自动重启与 LiveReload 配合使用时效果非常好。详情请参阅 LiveReload 部分。如果使用 JRebel,自动重启将被禁用,转而使用动态的类重载。但仍可使用其他 devtools 功能(如 LiveReload 和属性重载)。
LiveReload 的工作流程通常是这样的:
在你的开发环境中启动 LiveReload 服务器。
在你的浏览器中安装 LiveReload 插件或使用浏览器内置的 LiveReload 功能。
在你进行代码编辑时,LiveReload 服务器会监视你的项目文件。
当你保存文件时,LiveReload 服务器会检测到文件的变化,并向浏览器发送消息。
浏览器收到消息后,会自动刷新页面,以加载最新的代码更改。
使用 LiveReload 可以提高前端开发的效率,因为它减少了手动刷新浏览器的频率,让开发者能够更专注于代码的编写和调试。
动态的类重载(Dynamic Class Reloading)是指在应用程序运行时,无需停止应用程序,通过替换已加载的类的字节码来更新应用程序的功能。这意味着你可以在不重启应用程序的情况下,对代码进行修改,并立即看到这些修改的效果。
具体来说,动态类重新加载通常包括以下几个步骤:
1. **监视类文件的修改**:开发工具或框架会监视项目中的类文件的变化。
2. **重新编译修改的类**:当检测到类文件的修改时,开发工具会重新编译这些类,生成新的字节码。
3. **替换已加载的类**:重新编译后的类字节码会被动态地加载到 JVM 中,取代原先已加载的类。
4. **应用程序状态维持**:动态类重新加载尽可能地保持应用程序的当前状态,例如保留已创建的对象和已经建立的连接。
动态类重新加载的优点是可以极大地提升开发效率,因为它减少了重新启动应用程序所需的时间,而且不会丢失应用程序的当前状态。这对于大型应用程序和长时间运行的服务特别有用,因为它允许开发者在进行代码修改时保持应用程序的运行状态。
JRebel 是一个流行的动态类重新加载工具,它允许开发者在开发过程中对 Java 类进行修改,并立即看到这些修改的效果,而无需重新启动应用程序。
)注意
DevTools 依靠应用程序上下文的关闭钩子在重启时关闭应用程序。如果禁用了关闭钩子(SpringApplication.setRegisterShutdownHook(false)),它就无法正常工作。
"重新启动期间关闭它" 指的是在使用 Spring Boot DevTools 进行应用程序重新启动时,DevTools 会在重新启动过程中关闭当前应用程序实例。这样做的目的是在重新启动之前清理应用程序的资源和状态,以确保重新启动后应用程序的行为是一致的。
当你对应用程序进行更改并触发重新启动时,DevTools 会关闭当前的应用程序实例,然后启动一个新的实例来应用你的更改。这个过程中,DevTools 需要确保当前的应用程序实例被正确地关闭,以避免可能导致的资源泄露或不一致状态。
在这段文本中,它提到如果你禁用了关闭钩子(shutdown hook),也就是通过 `SpringApplication.setRegisterShutdownHook(false)` 方法来禁用,那么 DevTools 将无法在重新启动过程中正确地关闭当前应用程序实例,可能导致不可预期的问题。因此,建议不要禁用关闭钩子,以确保 DevTools 能够正常工作。
)注意
DevTools 需要定制 ApplicationContext 使用的 ResourceLoader。如果您的应用程序已经提供了资源加载器,它将被封装。不支持直接覆盖 ApplicationContext 上的 getResource 方法。
(举例来说,假设你的应用程序定义了一个自定义的 ApplicationContext,并在其中提供了自定义的资源加载器。如果你启用了 Spring Boot DevTools,它将会在你的应用程序上下文中注入一个自定义的资源加载器,以确保 DevTools 能够正确地处理资源加载过程。这样,即使你已经提供了自己的资源加载器,DevTools 仍然会对其进行包装和定制,以适应其特定的需求和功能。)
注意 使用 AspectJ 编织时不支持自动重启。
记录状态评估中的变化
默认情况下,每次重新启动应用程序时,都会记录一份显示条件评估 delta 的报告。在您进行添加或删除 Bean 以及设置配置属性等更改时,该报告会显示应用程序自动配置的更改情况。
要禁用报告记录,请设置以下属性:
Properties
spring.devtools.restart.log-condition-evaluation-delta=false
Yaml
spring:
devtools:
restart:
log-condition-evaluation-delta: false
(
条件评估(Condition Evaluation)是指在 Spring 应用程序中,根据一系列条件来决定是否应该启用或禁用特定的功能或组件的过程。这些条件可以基于环境、配置、类路径等多种因素。
在 Spring 中,条件评估通常与自动配置(Auto-configuration)密切相关。自动配置是 Spring Boot 的一个重要特性,它根据应用程序的类路径和配置来自动配置应用程序的各种功能。而条件评估则用于决定哪些自动配置应该生效,哪些应该被禁用。
条件评估是通过实现 `Condition` 接口来定义的。当 Spring Boot 启动时,会对所有的自动配置类进行条件评估,根据条件的结果来决定是否应该应用该自动配置。如果条件评估为真,则相应的自动配置会被启用;如果条件评估为假,则相应的自动配置会被禁用。
条件评估可以根据多种条件来进行,例如:
- 环境属性(Environment Properties):根据应用程序当前运行的环境来决定是否启用自动配置。
- 类路径上的资源是否存在:根据类路径上的某些资源是否存在来决定是否启用自动配置。
- Bean 是否存在:根据 Spring 容器中是否存在某个特定的 Bean 来决定是否启用自动配置等。
通过条件评估,Spring Boot 能够根据不同的条件来动态地调整应用程序的行为,从而实现更灵活和可配置的应用程序。
报告会显示在应用程序的日志文件中。具体来说,它通常会显示在控制台或日志文件中,取决于您的应用程序是如何配置日志记录的。
如果您在控制台运行应用程序,您可以在控制台输出中查看这些报告。如果您配置了日志记录到文件中,您可以在相应的日志文件中查看这些报告。
报告的内容会记录有关条件评估的变化,例如哪些自动配置被启用或禁用,哪些 bean 被添加或删除,以及配置属性的变化情况等。通过查看这些报告,您可以了解在应用程序重新启动时发生了什么变化。
)
不包括资源
某些资源在更改时并不一定需要触发重启。例如,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/**"
TIP
如果您想保留这些默认设置并添加额外的排除项,请改用 spring.devtools.restart.additional-exclude 属性。
(换句话说,如果您想要在默认排除的基础上额外排除某些路径,可以使用这个属性。例如,如果您想保留默认排除 /META-INF/maven, /META-INF/resources, /resources, /templates,并且额外排除 /static 和 /public,您可以设置这个属性来实现。)
观察附加路径
您可能希望在更改不在类路径上的文件时重启或重新加载应用程序。为此,可使用 spring.devtools.restart.additional-paths 属性配置额外路径,以更改监控。你可以使用前面介绍的 spring.devtools.restart.exclude 属性来控制附加路径下的更改是触发完全重启还是实时重载。
禁用重启
如果不想使用重启功能,可以使用 spring.devtools.restart.enabled 属性将其禁用。在大多数情况下,你可以在 application.properties 中设置该属性(这样做仍会初始化 重启类加载器,但不会监控文件更改)。
如果您需要完全禁用重启支持(例如,因为它与特定库不兼容),您需要在调用 SpringApplication.run(...) 之前将 spring.devtools.restart.enabled 系统属性设置为 false,如下例所示:
Java
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); } }
科特林
import org.springframework.boot.SpringApplication import org.springframework.boot.autoconfigure.SpringBootApplication @SpringBootApplication object MyApplication { @JvmStatic fun main(args: Array<String>) { System.setProperty("spring.devtools.restart.enabled", "false") SpringApplication.run(MyApplication::class.java, *args) } }
使用触发器文件
如果您使用的集成开发环境会持续编译已更改的文件,那么您可能更希望只在特定时间触发重启。(换句话说,开发者可能更愿意在特定时刻手动触发应用程序的重新启动,而不是在每次文件修改后都自动触发重新启动。)要做到这一点,可以使用 "触发文件",这是一个特殊的文件,必须在实际触发重启检查时进行修改。
注意
文件的任何更新都会触发检查,但只有在 Devtools 检测到它有事情要做时,才会实际重启。
要使用触发器文件,请将 spring.devtools.restart.trigger-file 属性设置为触发器文件的名称(不包括任何路径)。触发器文件必须出现在类路径上的某个位置。
例如,如果您有一个结构如下的项目:
src +- main +- resources +- .reloadtrigger
那么您的触发器文件属性就是
Properties
spring.devtools.restart.trigger-file=.reloadtriggerYaml
spring: devtools: restart: trigger-file: ".reloadtrigger"
现在只有在更新 src/main/resources/.reloadtrigger 时才会重启。(具体来说,当您对项目中的 .reloadtrigger 文件进行了更新或修改时,Spring Boot Devtools 会检测到这个变化,并认为有必要重新加载或重新启动应用程序以应用新的更改。这种机制允许您在需要时手动控制应用程序的重新加载或重新启动,而不是依赖于自动检测文件更改的机制。这在某些开发和调试场景下非常有用,例如在特定代码或资源更改后手动触发重新启动以验证修改。)
TIP
您可能希望将 spring.devtools.restart.trigger-file 设置为全局设置,这样所有项目都能以相同方式运行。
一些集成开发环境(IDE)具有功能,可以帮助您避免手动更新触发器文件的需要。Spring Tools for Eclipse (https://spring.io/tools)和 IntelliJ IDEA(Ultimate 版)https://www.jetbrains.com/idea/ 都支持这样的支持。对于 Spring Tools,只要您的触发器文件命名为 `.reloadtrigger`,您就可以从控制台视图中使用“重新加载”按钮。至于 IntelliJ IDEA,您可以按照他们文档中的说明进行操作。(https://www.jetbrains.com/help/idea/spring-boot.html#application-update-policies)
(
Spring Tools for Eclipse 中的 "重新加载" 按钮用于手动触发应用程序的重新加载或重新启动。以下是使用步骤:
-
确保触发器文件命名为
.reloadtrigger
:首先,您需要确保在您的项目中存在一个名为.reloadtrigger
的文件,这是 Devtools 所需的触发器文件。 -
打开控制台视图:在 Eclipse 的窗口菜单中,选择“窗口(Window)” > “显示视图(Show View)” > “其他(Other)”,然后在弹出的窗口中找到并选择“控制台(Console)”视图。
-
点击重新加载按钮:在控制台视图中,应该会有一个名为“重新加载”的按钮。点击这个按钮,它会触发 Spring Tools for Eclipse 检测触发器文件的更新,并相应地重新加载或重新启动应用程序。
通过这个按钮,您可以方便地手动控制应用程序的重新加载,而无需手动编辑触发器文件。
)
自定义重启类加载器
如前面在“重启 vs 重新加载”一节中描述的那样,重启功能是通过使用两个类加载器来实现的。如果这导致问题,您可能需要自定义哪些内容由哪个类加载器加载。
默认情况下,您的 IDE 中打开的任何项目都将使用“重启”类加载器加载,而任何常规的 .jar 文件都将使用“基础”类加载器加载。如果您使用 `mvn spring-boot:run` 或 `gradle bootRun`,同样的规则也适用:包含 `@SpringBootApplication` 的项目将使用“重启”类加载器加载,而其他所有内容都使用“基础”类加载器加载。
您可以通过创建一个 `META-INF/spring-devtools.properties` 文件来指示 Spring Boot 使用不同的类加载器加载项目的部分内容。`spring-devtools.properties` 文件可以包含以 `restart.exclude` 和 `restart.include` 前缀开头的属性。`include` 元素是应该被提升到“重启”类加载器中的项目,而 `exclude` 元素是应该被推送到“基础”类加载器中的项目。属性的值是应用于类路径的正则表达式模式,如以下示例所示:
Properties
restart.exclude.companycommonlibs=/mycorp-common-[\\w\\d-\\.]+\\.jar
restart.include.projectcommon=/mycorp-myproj-[\\w\\d-\\.]+\\.jar
Yaml
restart: exclude: companycommonlibs: "/mycorp-common-[\\w\\d-\\.]+\\.jar" include: projectcommon: "/mycorp-myproj-[\\w\\d-\\.]+\\.jar"
注意
所有属性键必须是唯一的。只要属性以 restart.include. 或 restart.exclude. 开头,它就会被考虑。
TIP
所有类路径下的 META-INF/spring-devtools.properties 都会被加载。您可以将文件打包到您的项目内部,或者在项目使用的库中。
已知限制
重启功能与使用标准的 `ObjectInputStream` 进行反序列化的对象不兼容。如果您需要对数据进行反序列化,可能需要使用 Spring 的 `ConfigurableObjectInputStream` 结合 `Thread.currentThread().getContextClassLoader()`。
不幸的是,一些第三方库在反序列化时没有考虑上下文类加载器。如果您发现了这样的问题,您需要向原始作者请求修复。
6.8.4. LiveReload
spring-boot-devtools 模块包含了一个内置的 LiveReload 服务器,可以在资源发生更改时触发浏览器刷新。LiveReload 浏览器扩展可以在 Chrome、Firefox 和 Safari 中免费获取。您可以通过在您选择的浏览器的市场或商店中搜索“LiveReload”来找到这些扩展。
如果您不希望在应用程序运行时启动 LiveReload 服务器,可以将 spring.devtools.livereload.enabled 属性设置为 false。
注意
一次只能运行一个 LiveReload 服务器。启动应用程序前,请确保没有其他 LiveReload 服务器在运行。如果从集成开发环境启动多个应用程序,只有第一个支持 LiveReload。
警告
要在文件更改时触发 LiveReload,必须启用自动重启。
6.8.5. 全局设置
您可以将以下任意文件添加到 $HOME/.config/spring-boot 目录:
- spring-boot-devtools.properties
- spring-boot-devtools.yaml
- spring-boot-devtools.yml
添加到这些文件中的任何属性都适用于机器上使用 devtools 的所有 Spring Boot 应用程序。例如,要配置重启始终使用触发器文件,可以在 spring-boot-devtools 文件中添加以下属性:
属性
spring.devtools.restart.trigger-file=.reloadtrigger
Yaml
spring: devtools: restart: trigger-file: ".reloadtrigger"
默认情况下,$HOME 是用户的主目录。要自定义此位置,请设置 SPRING_DEVTOOLS_HOME 环境变量或 spring.devtools.home 系统属性。
注意
如果在 $HOME/.config/spring-boot 中找不到 devtools 配置文件,则会搜索 $HOME 目录根目录中是否存在 .spring-boot- devtools.properties 文件。这样,您就可以与使用不支持 $HOME/.config/spring-boot 位置的旧版 Spring Boot 的应用程序共享 devtools 全局配置。(话句话说,新版兼容旧版配置文档)
注意
devtools properties/yaml 配置文件不支持特定的 Spring Profile(例如 dev、test、prod)下激活的配置文件
任何在 .spring-boot-devtools.properties 中激活的配置文件都不会影响特定配置文件的加载。不支持 YAML 文件和属性文件中的配置文件特定文件名(格式为 spring-boot-devtools-<profile>.properties)也不支持 YAML 和属性文件中的 spring.config.activate.on-profile 文档。
(
假设您有一个 Spring Boot 应用程序,并且希望根据不同的环境加载不同的配置文件,比如开发环境、测试环境和生产环境。通常情况下,您可以通过在 application.properties 或 application.yml 文件中设置 spring.profiles.active 属性来实现这一点,例如:
yaml
# application.yml spring: profiles: active: dev
这样会告诉 Spring 加载名为 application-dev.yml 的配置文件。
但是,在使用 Spring Boot 的开发工具(devtools)时,您可能希望根据不同的环境加载不同的配置文件,但是不能通过上述方式实现。这意味着,您无法在 devtools 的配置文件中指定要激活的配置文件。例如,在名为 .spring-boot-devtools.properties 的文件中设置 spring.profiles.active=dev 是不起作用的。
因此,您需要通过其他方式来激活或加载特定的配置文件,而不是依赖于在 devtools 配置文件中设置。
当您使用 spring.config.activate.on-profile 时,您可以在 .properties 文件中列出多个要激活的配置文件,如下所示:
properties
spring.config.activate.on-profile=dev,production
这将激活名为 spring-boot-devtools-dev.properties 和 spring-boot-devtools-production.properties 的两个配置文件。
而当您使用 spring.profiles.active 时,您可以在 application.yml 文件中指定要激活的单个配置文件,如下所示:
yaml
spring: profiles: active: dev
这将激活名为 application-dev.yml 的配置文件。
)
配置文件系统监视器
FileSystemWatcher(https://github.com/spring-projects/spring-boot/tree/v3.2.2/spring-boot-project/spring-boot-devtools/src/main/java/org/springframework/boot/devtools/filewatch/FileSystemWatcher.java) 的工作原理是以一定的时间间隔轮询类的更改,然后等待预定义的静默期,以确保不再有更改。由于 Spring Boot 完全依赖集成开发环境来编译文件并将其复制到 Spring Boot 可以读取的位置,因此您可能会发现,当 devtools 重新启动应用程序时,某些更改有时无法反映出来。如果您经常发现此类问题,请尝试将 spring.devtools.restart.poll-interval 和 spring.devtools.restart.quiet-period 参数设置为适合您开发环境的值
(具体来说,当IDE执行编译操作时,它可能会锁定某些文件或目录,以防止其他进程(例如DevTools)对它们进行访问。在这种情况下,如果DevTools正在尝试监视这些文件以检测变化,它可能会受到IDE操作的限制而无法及时检测到文件的变化,导致重新启动延迟。
因此,为了确保DevTools能够可靠地检测到文件系统的变化并触发重新启动,建议在IDE执行编译或文件复制操作时,尽可能减少对文件系统的锁定,并尽量避免长时间持有文件的锁定。此外,可以通过调整DevTools的配置参数来增加轮询间隔和安静期的时长,以适应可能存在的延迟。)
属性
spring.devtools.restart.poll-interval=2s
spring.devtools.restart.quiet-period=1s
Yaml
spring: devtools: restart: poll-interval: "2s" quiet-period: "1s"
现在,每 2 秒钟就会轮询一次受监控的类路径目录是否有变化,并保持 1 秒钟的静默期,以确保没有其他类变化。
6.8.6.远程应用
Spring Boot 开发人员工具不仅限于本地开发。您还可以在远程运行应用程序时使用多项功能。远程支持是选择性的,因为启用它可能存在安全风险。只有在受信任的网络上运行或使用 SSL 确保安全时,才能启用远程支持。如果这两个选项都不可用,则不应使用 DevTools 的远程支持。绝不应在生产部署中启用支持。
要启用它,需要确保重新打包的归档文件中包含 devtools,如下表所示:
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludeDevtools>false</excludeDevtools>
</configuration>
</plugin>
</plugins>
</build>
然后需要设置 spring.devtools.remote.secret 属性。就像任何重要的密码或秘密一样,该值应是唯一且强大的,以防被猜测或暴力破解。
远程 devtools 支持由两部分组成:接受连接的服务器端端点(译者注:端点就是web接口本身)和在集成开发环境中运行的客户端程序。当设置了 spring.devtools.remote.secret 属性后,服务器组件将自动启用。客户端组件必须手动启动。
注意
Spring WebFlux 应用程序不支持远程 devtools。
运行远程客户端应用程序
远程客户端应用程序设计为从您的集成开发环境(IDE)中运行。您需要以与您连接到的远程项目相同的类路径运行 org.springframework.boot.devtools.RemoteSpringApplication。该应用程序的单个必需参数是它连接的远程URL。
例如,如果您使用Eclipse或Spring Tools,并且您有一个名为my-app的项目,并将其部署到Cloud Foundry,您应该执行以下操作:
从“运行”菜单中选择“运行配置”。
创建一个新的Java应用程序“启动配置”。
浏览my-app项目。
将 org.springframework.boot.devtools.RemoteSpringApplication 用作主类。
将 https://myapp.cfapps.io 添加到程序参数(或您的远程URL)。
运行中的远程客户端可能类似于以下清单:
. ____ _ __ _ _ /\\ / ___'_ __ _ _(_)_ __ __ _ ___ _ \ \ \ \ ( ( )\___ | '_ | '_| | '_ \/ _` | | _ \___ _ __ ___| |_ ___ \ \ \ \ \\/ ___)| |_)| | | | | || (_| []::::::[] / -_) ' \/ _ \ _/ -_) ) ) ) ) ' |____| .__|_| |_|_| |_\__, | |_|_\___|_|_|_\___/\__\___|/ / / / =========|_|==============|___/===================================/_/_/_/ :: Spring Boot Remote :: (v3.2.3) 2024-02-22T18:33:07.762Z INFO 34942 --- [ main] o.s.b.devtools.RemoteSpringApplication : Starting RemoteSpringApplication v3.2.3 using Java 17.0.10 with PID 34942 (/Users/myuser/.m2/repository/org/springframework/boot/spring-boot-devtools/3.2.3/spring-boot-devtools-3.2.3.jar started by myuser in /opt/apps/) 2024-02-22T18:33:07.766Z INFO 34942 --- [ main] o.s.b.devtools.RemoteSpringApplication : No active profile set, falling back to 1 default profile: "default" 2024-02-22T18:33:08.081Z INFO 34942 --- [ main] o.s.b.d.a.OptionalLiveReloadServer : LiveReload server is running on port 35729 2024-02-22T18:33:08.116Z INFO 34942 --- [ main] o.s.b.devtools.RemoteSpringApplication : Started RemoteSpringApplication in 0.786 seconds (process running for 1.137)
注意
因为远程客户端使用与真实应用程序相同的类路径,它可以直接读取应用程序属性。这就是 spring.devtools.remote.secret 属性如何被读取并传递给服务器进行身份验证的方式。
TIP
建议始终使用 https:// 作为连接协议,这样流量就会被加密,密码就无法被拦截。
TIP
如果需要使用代理访问远程应用程序,请配置
spring.devtools.remote.proxy.host 和 spring.devtools.remote.proxy.port 属性。
远程更新
远程客户端以与本地重启相同的方式监控应用程序类路径的变化。任何更新的资源都会推送到远程应用程序,并(在需要时)触发重启。如果您迭代的功能使用的是本地没有的云服务,这将很有帮助。一般来说,远程更新和重启比完整的重建和部署周期要快得多。
在开发速度较慢的环境中,可能会出现静默期不够的情况,类的更改可能会分成几批进行。第一批类更改上传后,服务器会重新启动。由于服务器正在重启,下一批更改无法发送到应用程序。
这种情况通常会在 RemoteSpringApplication 日志中出现警告,提示无法上传某些类,并随之重试。但它也可能导致应用程序代码不一致,以及在上传第一批更改后无法重新启动。如果您经常发现此类问题、尝试增加的spring.devtools.restart.poll-interval和 spring.devtools.restart.quiet-period 参数,使其达到适合你的开发环境的值。有关配置这些属性的信息,请参阅 "配置文件系统监视器 "部分。
注意
只有在远程客户端运行时,文件才会受到监控。如果在启动远程客户端之前更改文件,则不会将其推送到远程服务器。
6.9. 为生产包装您的应用程序
可执行 jar 可用于生产部署。由于它们是独立的,因此也非常适合基于云的部署。
如需额外的 "生产就绪 "功能,如健康、审计和度量 REST 或 JMX 端点,请考虑添加 spring-boot-actuator。有关详细信息,请参阅生产就绪功能。
6.10. 下一步读什么
现在,您应该了解了如何使用 Spring Boot 以及应该遵循的一些最佳实践。现在,您可以继续深入了解 Spring Boot 的具体功能,也可以跳到前面阅读 Spring Boot 的 "生产就绪 "方面。
一些集成开发环境(IDE)具有功能,可以帮助您避免手动更新触发器文件的需要。Spring Tools for Eclipse 和 IntelliJ IDEA(Ultimate 版)都支持这样的支持。对于 Spring Tools,只要您的触发器文件命名为 `.reloadtrigger`,您就可以从控制台视图中使用“重新加载”按钮。至于 IntelliJ IDEA,您可以按照他们文档中的说明进行操作。