文章作者:Tyan
博客:noahsnail.com | CSDN | 简书
第一部分:Spring Boot文档
1. 关于文档
Sring参考文档可以通过html,pdf和epub 三种形式得到。最新的文档可以从docs.spring.io/spring-boot/docs/current/reference上得到。
本文档无论是电子版还是打印版,只要你不收取任何费用且在每个副本中包含了版权声明,你就可以自由使用本文档的副本或分发给其它人。
2. 获得帮助
如果在使用Spring Boot中有不会的地方,我们很乐意帮忙!
尝试How-to’s(文档第九部分),里面有最常见问题的解决方案。
学习Spring基础知识——Spring Boot建立在许多其它的Spring工程之上,查看spring.io网站,上面有大量的参考文档。如果你刚开始使用Spring,尝试看这些指南中的一个。
问问题——我们监控着stackoverflow.com中标签为
spring-boot
的问题。报告Spring Boot中的bugs请到github.com/spring-projects/spring-boot/issues。
Spring Boot是开源的,包括文档!如果你在文档中发现了问题;或你想改进它们,请参与进去。
3. 第一步
如果你准备开始学习Spring Boot或通常来说的Spring,从这里开始!
从零开始: 概述 | 要求 | 安装
学习指南: 第一部分 | 第二部分
运行例子: 第一部分 | 第二部分
4. 使用Spring Boot
准备好开始使用Spring Boot了?不用担心。
构建系统:Maven | Gradle | Ant | Starters
最佳实践:Code Structure | @Configuration | @EnableAutoConfiguration | Beans and Dependency Injection
运行代码:IDE | Packaged | Maven | Gradle
打包应用:Production jars
Spring Boot命令行:Using the CLI
5. 了解Spring Boot特性
需要更多关于Spring Boot核心特性的细节?看下面。
核心特性:SpringApplication | External Configuration | Profiles | Logging
Web应用:MVC | Embedded Containers
消息:Overview | JMS
测试:Overview | Boot Applications | Utils
扩展:Auto-configuration | @Conditions
6. 变为产品
当你准备将你的Spring Boot应用变成产品时,给你推荐一些你可能喜欢的小技巧。
管理端点:Overview | Customization
链接选择:HTTP | JMX | SSH
监控:Metrics | Auditing | Tracing | Process
7. 高级课题
最后,我们有一些课题给高级用户。
部署Spring Boot应用:Cloud Deployment | OS Service
构建工具插件:Maven | Gradle
附录:Application Properties | Auto-configuration classes | Executable Jars
Part II 开始
如果你刚开始学习Spring Boot或通常所说的Spring,这部分就是为你准备的!这部分中我们回答了基本的”what?”,”how”,”why?”问题,并在安装说明中介绍Spring Boot。我们将构建第一个Spring Boot应用,讨论一些我们遵循的核心原则。
8. Spring Boot介绍
Spring Boot 使创建独立的、产品级的、基于Spring的应用变得更容易,你只需要运行run
即可。我们采用不变的Spring平台和第三方库,因此你可以几乎无差别的使用Spring Boot。大多数Spring Boot应用只需要很少的Spring配置。
你可以使用Spring Boot创建Java应用,用java-jar
或更传统的war包来部署应用。我们也提供了运行”Spring脚本”的命令行工具。
我们的主要目标是:
为所有Spring开发者提供一个从根本上更迅速可用的入门经验。
坚持开箱即用,当默认设置不满足需求时可以快速避免默认设置。
为具有许多类的工程提供一系列常用的非功能特性(例如嵌入式服务器、安全、度量、健康检查、外部配置)。
绝对没有XML配置代码产生和XML配置需求。
9. 系统需求
By default, Spring Boot 2.0.0.BUILD-SNAPSHOT requires Java 7 and Spring Framework 5.0.0.BUILD-SNAPSHOT or above. You can use Spring Boot with Java 6 with some additional configuration. See Section 80.11, “How to use Java 6” for more details. Explicit build support is provided for Maven (3.2+) and Gradle (1.12 or 2.x). Gradle 3 is not supported.
默认情况下,Spring Boot 2.0.0.BUILD-SNAPSHOT需要Java 7和Spring Framework 5.0.0.BUILD-SNAPSHOT及以上。你可以通过一些额外配置在Java 6下使用Spring Boot。更多细节请看80.11小节,”怎样使用Java 6”。明确的构建支持有Maven (3.2+)和Gradle (1.12 or 2.x),不支持Gradle 3。
Although you can use Spring Boot with Java 6 or 7, we generally recommend Java 8 if at all possible.
虽然你可以在Java 6或Java 7下使用Spring Boot,但我们建议尽可能的使用Java 8。
9.1 Servlet容器
下面的嵌入式servlet
容器支持开箱即用:
Name | Servlet Version | Java Version |
---|---|---|
Tomcat 8 | 3.1 | Java 7+ |
Tomcat 7 | 3.0 | Java 6+ |
Jetty 9.3 | 3.1 | Java 8+ |
Jetty 9.2 | 3.1 | Java 7+ |
Jetty 8 | 3.0 | Java 6+ |
Undertow 1.3 | 3.1 | Java 7+ |
你也可以部署Spring Boot应用到任何兼容Servlet 3.0+的容器。
10. 安装Spring Boot
Spring Boot可以和”经典”的Java开发工具一起使用,也可作为一个命令行工具来进行安装。不管你是需要Java SDK v.16还是更高版本,在开始之前你应该检查你当前安装的Java版本。
1 | $ java -version |
如果你是Java开发的新手,或你只想尝试Spring Boot,你可能首先想试一下Spring Boot CLI,否则,请读”经典”的安装说明。
虽然Spring Boot兼容Java 1.6,但可能的话,你应该考虑使用Java的最新版本。
10.1 Java开发者的安装说明
你可以使用Spring Boot像使用任何标准Java库一样。简单的在你的classpath
中包含恰当spring-boot-*.jar
即可。Spring Boot不需要任何特定的工具集成,因此你可以使用任何IDE或文本编辑器;Spring Boot应用没有什么特别的,你可以像其它的Java程序一样来运行和调试。
尽管你可以只拷贝Spring Boot的jars,但通常我们建议你使用一个支持依赖管理的构建工具(例如Maven或Gradle)。
10.1.1 Maven安装
Spring Boot兼容Apache Maven 3.2或以上。如果你没有安装Maven,你可以根据maven.apache.org的说明来安装。
在许多操作系统上Maven都能通过包管理器来安装。如果你是一个OSX Homebrew用户可以通过
brew install maven
安装。Ubuntu用户可以通过sudo apt-get install maven
安装。
Spring Boot依赖使用org.springframework.boot
groupId
。通常你的Maven POM文件将继承spring-boot-starter-parent
工程并声明一个或多个“Starters”依赖。Spring Boot也提供一个可选的Maven插件来创建可执行的jar包。
下面是一个典型的pom.xml
文件:
1 | <?xml version="1.0" encoding="UTF-8"?> |
spring-boot-starter-parent
是使用Spring Boot的一种极好的方式,但它可能不是一直都合适的。有时你可能需要继承一个不同的父POM,或者你可能不喜欢我们的默认设置。请看13.2.2小节,『没有父POM的情况下使用Spring Boot』是一种可替代的解决方案,它使用了import
作用域。
10.1.2 Gradle安装
Spring Boot兼容Gradle 1.12或2.x。推荐使用2.14.1。不支持Gradle 3。如果你没有安装Gradle,你可以根据www.gradle.org/的介绍来安装。
Spring Boot依赖使用org.springframework.boot
groupId
。通常你的工程会声明一个或多个“Starters”依赖。Spring Boot提供了一个有用的Gradle插件用来简化依赖声明并创建可执行的jar包。
Gradle Wrapper
当你需要构建一个工程时,Gradle Wrapper提供了一种很好的方式来『获得』Gradle。它是一小段脚本和库,并随着你的代码一起提交来引导构建过程。更多细节请看https://docs.gradle.org/2.14.1/userguide/gradle_wrapper.html。
10.2 安装Spring Boot CLI
Spring Boot CLI是一个命令行工具,可以用来快速搭建基于Spring的原型。它允许你运行Groovy脚本,这意味着你有一个熟悉的类Java语法,没有很多的样本代码。
你不需要使用CLI来使用Spring Boot但它是开始得到一个基于Spring应用的最快方式。
10.2.1 手动安装
你可以从Spring软件仓库下载Spring CLI发行版:
最新的snapshot distributions也是可获得的。
一旦下载完成,按照存档INSTALL.txt中的 介绍来安装。总结:bin/
目录的.zip
文件中有一个spring
脚本(Windows中是spring.bat
),或者你可以使用java -jar
运行.jar
文件(这个脚本帮你确保正确设置classpath)。
10.2.2 使用SDKMAN!安装
SDKMAN! (The Software Development Kit Manager)能用来管理各种二进制SDKs的多个版本,包括Groovy和Spring Boot CLI。从sdkman.io中得到SDKMAN!并安装Spring Boot:
1 | $ sdk install springboot |
如果你在为CLI开发功能并向很容易的访问你够简单版本,按照这些额外的介绍去做。
1 | $ sdk install springboot dev /path/to/spring-boot/spring-boot-cli/target/spring-boot-cli-2.0.0.BUILD-SNAPSHOT-bin/spring-2.0.0.BUILD-SNAPSHOT/ |
这将会安装一个名为dev
的本地spring
实例。它指向你的目标构建位置,因此你每次重新构建Spring Boot,spring
将是最新的。
按下面去做你会看到:
1 | $ sdk ls springboot |
10.2.3 OSX Homebrew安装
如果你在Mac上使用Homebrew,安装Spring Boot CLI所有你需要做的是:
1 | $ brew tap pivotal/tap |
Homebrew会在/usr/local/bin
目录安装spring
。
如果你没有看到公式,你安装的brew可能过时了。执行
brew update
并重新再试一次。
10.2.4 MacPorts安装
如果你在Mac上使用MacPorts,安装Spring Boot CLI所有你需要做的是:
1 | $ sudo port install spring-boot-cli |
10.2.5 命令行实现
Spring Boot CLI附带的脚本为BASH和zsh shells提供了命令行实现。你可以在任何shell中source
脚本(也称为spring
),或将它放在用户或系统范围内的bash完成初始化。在Debian系统中系统范围内的脚本是在/shell-completion/bash
目录中,当新shell启动时,目录下的所有脚本都被执行。如果你装了SDKMAN!,为了手动运行脚本,执行下面的命令:
1 | $ . ~/.sdkman/candidates/springboot/current/shell-completion/bash/spring |
如果你想使用Homebrew或MacPorts安装Spring Boot CLI,命令行完成脚本会自动在shell中注册。
10.2.6 快速Spring CLI例子
这儿有一个真实的简单的web应用,你可以用来测试你的安装。创建一个文件叫app.groovy
:
1 | @RestController |
这儿有一个真实的简单的web应用,你可以用来测试你的安装。创建一个文件叫app.groovy
:
1 | @RestController |
当你第一次运行应用时它需要一段时间,因为要下载依赖。接下来运行会更快。
在你最喜欢的浏览器中输入localhost:8080,你应该会看到下面的结果:
1 | Hello World! |
10.3 从早期的Spring Boot升级
如果正在升级你的Spring Boot,检查project wiki中的『发布说明』。你将找到升级说明,说明中有每一次发布的特性列表。
为了升级现有的CLI,要使用合适的包管理命令(例如brew upgrade
),如果你手动安装的CLI,要按照标准的说明去做,为了移除旧的引用要记住更新你的PATH环境变量。
11. 开发你的第一个Spring Boot应用
我们用Java开发一个简单的Web应用“Hello World!”,通过应用来强调Spring Boot的一些关键特性。由于大多数IDE都支持Maven,因此我们用Maven来构建这个项目。
spring.io网站上有许多使用Spring Boot的“Getting Started”指南。如果你要解决一个特定的问题;先去网站上看一下。
你可以通过到start.spring.io上并从依赖搜索器中选择
web
启动器来简化下面的步骤。这会自动的产生一个新的工程结构所以你能以正确的方式开始编码。更多细节请看文档。
1 | $ java -version |
1 | $ mvn -v |
这个例子需要创建它自己的文件夹。接下来的介绍假设你已经创建了合适的文件夹并且文件夹是你的当前目录。
11.1 创建POM文件
我们首先需要创建一个Maven的pom.xml
文件。pom.xml
是用来构建项目的处方。打开你最喜欢的文本编辑器并添加以下内容:
1 | <?xml version="1.0" encoding="UTF-8"?> |
11.2 添加classpath依赖
Spring Boot提供了许多“Starters”,这样可以很容器的在classpath中添加jar包。我们的例子程序已经在POM的parent
部分使用了spring-boot-starter-parent
。spring-boot-starter-parent
是一个特别的启动器,它能提供有用的Maven默认设置。它也提供了依赖管理部分,因此你可以对“blessed”依赖忽略其版本标签。
当开发一个特定的应用时,其它的“Starters”简单的提供了你可能需要的依赖。由于我们正在开发一个web应用,我们将添加spring-boot-starter-web
依赖——但在那之前,让我们先看一下目前有什么。
1 | $ mvn dependency:tree |
11.3 写代码
为了完成我们的应用,我们需要创建一个简单的Java文件。Maven默认的将从src/main/java
编译源码,因此你需要创建文件结构,然后添加名为src/main/java/Example.java
的文件:
1 | import org.springframework.boot.*; |
尽管这儿没有太多代码,许多正在进行中。让我们一步步浏览这些重要的部分。
11.3.1 @RestController和@RequestMapping注解
Example
类中的第一个注解是@RestController
。这是一个模式化的注解。它为阅读代码的人提供了暗示,对于Spring而言,这个类有一个特定的任务。在这个例子中,我们的类是一个web @Controller
,当web请求到来时,Spring会考虑用它来处理。
@RequestMapping
注解提供了『路由』信息。它告诉Spring任何带有路径”/“的HTTP请求应该映射到home
方法上。@RestController
注解告诉Spring将结果渲染成字符串形式并直接返回给调用者。
@RestController
和@RequestMapping
是Spring MVC注解(它们不是Spring Boot特有的)。更多细节请看Spring参考文档中MVC部分。
11.3.2 @EnableAutoConfiguration注解
第二个类级别的注解是@EnableAutoConfiguration
。这个注解告诉Spring Boot基于你添加的jar依赖去”猜”你想怎样配置Spring。由于spring-boot-starter-web
添加了Tomcat和Spring MVC,自动配置会假设你正在开发一个web应用并相应的设置Spring。
启动器和自动化配置
自动配置被设计成跟『启动器』能一起工作的很好,但这两个概念没有直接联系。你可以自由的挑选启动器之外的jar依赖,Spring Boot仍会最大程度地自动配置你的应用。
11.3.3 The “main” method
程序的最后部分是main
方法。这是一个符合Java应用程序入口规范的标准方法。main
方法中委托Spring Boot的SpringApplication
类调用run
方法。SpringApplication
将引导我们的应用启动Spring,Spring将启动自动配置的Tomcat web服务器。我们需要将Example.class
作为参数传给run
方法,告诉SpringApplication
它是主要的Spring组件。args
数组会将所有命令行参数传给run
方法。
11.4 运行这个例子
此时我们的应用应该工作了。既然我们已经使用了spring-boot-starter-parent
POM,那我们有一个有用的run
目标,我们使用它来启动应用。在工程的根目录中输入mvn spring-boot:run
来启动应用。
1 | $ mvn spring-boot:run |
如果你打开一个web浏览器,输入localhost:8080
,你应该会看到下面的输出。
1 | Hello World! |
可以点击ctrl-c
退出应用。
11.5 创建一个可执行的jar
通过创建一个在产品中能运行的完整的自包含可执行jar文件来结束我们的例子。可执行jars(有时称为“fat jars”)是包含编译的类和代码运行需要的所有jar依赖的存档文件。
可执行jars和Java
Java没有提供任何标准方法来加载嵌套的jar文件(例如,jar文件本身包含在一个一个jar中)。如果你想分发一个自包含的应用,这可能是个问题。
为了解决这个问题,许多开发者使用“uber” jars。uber jar简单的将所有jars的所有类打包到一个单独的存档文件中。这个方法的问题是很难看到你的应用正在使用的是哪个库。如果多个jars使用了相同的文件名(不同的内容)也是个问题。
Spring Boot采用了一种不同的方法来处理这个问题,允许你真正的直接内嵌jars。
为了创建可执行jar,我们需要添加spring-boot-maven-plugin
到pom.xml
中。在dependencies
部分下面插入以下内容:
1 | <build> |
spring-boot-starter-parent
POM包含绑定repackage
目标的<executions>
配置。如果你没有使用父POM,那你需要自己声明这个配置。更多细节请看插件文档。
保存你的pom.xml
并从命令行中运行mvn package
:
1 | $ mvn package |
如果你看一下目录target
你应该看到myproject-0.0.1-SNAPSHOT.jar
。这个文件大小应该在10 Mb左右。如果你想看里面的内容,你可以使用:jar tvf
1 | $ jar tvf target/myproject-0.0.1-SNAPSHOT.jar |
你在target
目录中应该也能看到一个更小的名为myproject-0.0.1-SNAPSHOT.jar.original
的文件。这是Spring Boot repackage之前Maven创建的最初的jar文件。
为了运行这个应用,要使用java -jar
命令:
1 | $ java -jar target/myproject-0.0.1-SNAPSHOT.jar |
像前面一样,通过点击ctrl-c
来退出应用。
12. 接下来读什么
希望这部分内容给你提供了一些Spring Boot的基本知识,让你写了你自己的应用。如果你是一个面向任务的开发人员,你可能想跳到spring.io,找出一些getting started指南来解决特定的『用Spring怎样做』的问题;我们也提供了Spring Boot的How-to参考文档。
Spring Boot repository也有一些你可以运行的例子。例子是独立于其它代码的(运行或使用例子时你不需要构建其它的内容)。
此外,按逻辑接下来是读第三部分,『使用Spring Boot』。如果你真的不耐烦,你也跳过这部分,直接阅读Spring Boot的特性。
Part III. 使用Spring Boot
这一节将会讲述关于应该如何使用Spring Boot的更多细节。它包括许多主题例如构建系统,自动配置和怎么运行自己的应用。我们也讲述一些Spring Boot的最佳实践。虽然没有关于Spring Boot非常特别的东西(它只是另一个你可以使用的库),但接下来的一些建议可以让你的开发过程更容易一点。
如果你刚开始学习Spring Boot,在学习这节之前你可能应该先阅读一下『Getting Started』部分。
13. 构建系统
强烈建议你选择一个支持依赖管理的构建系统,构建系统可以使用发布在『Maven Central』仓库中的工件。我们建议你选择Maven或Gradle。Spring Boot可能也可以与其它的构建系统进行协作(例如Ant),但不能特别好的支持其它的构建系统。
13.1 依赖管理
Spring Boot的每一次发布都会提供它支持的依赖列表。实际应用时,在你的构建配置中不需要提供这些依赖的版本,因为Spring Boot会帮你进行管理。当你升级Spring Boot时,这些依赖也会随之进行升级。
如果有必要的话,你仍可以指定版本并覆盖Spring Boot的推荐。
这个列表包含了所有你在Spring Boot中可以使用的Spring模块,也包含了第三方库的精制列表。这个列表可以当做一个标准可用的Bills of Materials (spring-boot-dependencies),也额外的专门支持Maven和Gradle可用。
Spring Boot的每一次发布都是与Spring框架的基本版本相关的,因此我们强烈建议你在自己使用时不要指定它的版本。
13.2 Maven
Maven用户可以继承spring-boot-starter-parent
工程来获得合理的默认配置。父工程提供了下面的特性:
Java 1.6作为默认的编译级别。
UTF-8源码编码。
依赖管理部分,对于常用的依赖允许你忽略
<version>
标签,从spring-boot-dependencies
继承POM。合理的资源过滤。
合理的插件配置(exec plugin, surefire, Git commit ID, shade)。
对包括特定配置文件的
application.properties
和application.yml
的合理资源过滤(例如,application-foo.properties
和application-foo.yml
)。
最后一点:由于默认配置文件采用Spring风格的占位符(${…}
),Maven过滤改成了使用@..@
占位符(你可以使用Maven属性resource.delimiter
来覆盖)。
13.2.1 继承starter parent
为了配置你的工程继承spring-boot-starter-parent
,简单的设置parent
:
1 | <!-- Inherit defaults from Spring Boot --> |
你应该只需要在这个依赖中指定Spring Boot的版本号。如果你导入额外的starters,你可以安全的忽略这个版本号。
有了这个设置,你也可以通过在你的工程中重写一个属性来覆盖单独的依赖。例如,为了升级另一个Spring Data的发布版本,你将需要在你的pom.xml
中添加以下内容:
1 | <properties> |
检查
spring-boot-dependencies
pom支持的属性清单。
13.2.2 没有父POM的情况下使用Spring Boot
不是每个人都喜欢继承spring-boot-starter-parent
POM的。你也可以有需要使用的公司的标准父POM,或者你可能更喜欢显式的声明你所有的Maven配置。
如果你不想使用spring-boot-starter-parent
,但你仍要保留依赖管理的好处(不是插件管理),你可以使用scope=import
依赖:
1 | <dependencyManagement> |
这个设置不允许你使用上面阐述的属性来重写单独的依赖。为了取得同样的效果,你需要在spring-boot-dependencies
入口之前在工程的dependencyManagement
中的添加一个入口。为了升级另一个Spring Data的发布版本,你将需要在你的pom.xml
中添加以下内容:
1 | <dependencyManagement> |
在上面的例子中,我们指定了一个POM但任何依赖类型都可以被重写。
13.2.3 更改Java版本
spring-boot-starter-parent
选择了相当保守的Java兼容性。如果你想听从我们的建议,使用更新的Java版本,你可以添加java.version
属性。
1 | <properties> |
13.2.4 使用Spring Boot Maven插件
Spring Boot包含了一个Maven插件,这个插件可以将工程打包为一个可执行的jar包。如果你向使用它的话,将它添加到你的<plugins>
部分:
1 | <build> |
如果你想使用Spring Boot的starter parent pom,你只需要添加这个插件,不需要配置它,除非你想更改父POM中的定义的设置。
13.3 Gradle
Gradle用户可以直接在它们的dependencies
部分导入starters
。不像Maven,这儿不能导入“super parent”来共享一些配置。
1 | apply plugin: 'java' |
spring-boot-gradle-plugin
也可用,并提供了从源码创建可执行jars和运行项目的功能。它也提供了依赖管理,在其它的兼容性之间,允许你忽略任何Spring Boot管理的依赖的版本号:
1 | buildscript { |
13.4 Ant
使用Apache Ant+Ivy来创建一个Spring Boot项目是可能的。spring-boot-antlib
“AntLib”模块也可以用来帮助Ant创建可执行jars。
为了声明依赖,一个典型的ivy.xml
文件如下所示:
1 | <ivy-module version="2.0"> |
一个典型build.xml
如下所示:
1 | <project |
如果你不想使用
spring-boot-antlib
模块,请看79.10小节,“Build an executable archive from Ant without using spring-boot-antlib” “How-to”。
13.5 Starters
启动器是一系列你可以包含进自己应用中的实用依赖描述符。你可以得到所有Spring和你需要的相关技术的一站式服务,不需要有搜索样例代码和拷贝粘贴依赖描述符的负担。例如,如果你想开始使用Spring和JPA来进行数据库链接,只需要在你的工程中包含spring-boot-starter-data-jpa
依赖,你便可以很好的前行了。
启动器包含许多你需要启动并快速运行一个工程的依赖,并持续支持一系列传递管理的依赖。
What’s in a name
所有的官方启动器都有一个类似的命名模式:spring-boot-starter-*
,*
是应用的特性类型。这个命名结构用来在你需要时帮助你发现一个启动器。Maven在许多IDEs中进行了集成,允许你通过名字来搜索依赖。例如,安装了合适的Eclipse或STS插件,你可以简单的在POM编辑器中点击ctrl-space
并输入“spring-boot-starter”来查找一个完整的列表。
正如在创建你自己的启动器部分讲述的那样,第三方启动器不应该与spring-boot
一起启动,因为它是预留给官方Spring Boot构建的。acme
的第三方启动器通过命名为acme-spring-boot-starter
。
下面的应用启动器由Spring Boot提供,在org.springframework.boot
组下:
表13.1. Spring Boot应用启动器
Name | Description | POM |
---|---|---|
spring-boot-starter-thymeleaf | Starter for building MVC web applications using Thymeleaf views | POM |
spring-boot-starter-data-couchbase | Starter for using Couchbase document-oriented database and Spring Data Couchbase | POM |
spring-boot-starter-artemis | Starter for JMS messaging using Apache Artemis | POM |
spring-boot-starter-web-services | Starter for using Spring Web Services | POM |
spring-boot-starter-mail | Starter for using Java Mail and Spring Framework’s email sending support | POM |
spring-boot-starter-data-redis | Starter for using Redis key-value data store with Spring Data Redis and the Jedis client | 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-data-gemfire | Starter for using GemFire distributed data store and Spring Data GemFire | POM |
spring-boot-starter-activemq | Starter for JMS messaging using Apache ActiveMQ | POM |
spring-boot-starter-data-elasticsearch | Starter for using Elasticsearch search and analytics engine and Spring Data Elasticsearch | POM |
spring-boot-starter-integration | Starter for using Spring Integration | POM |
spring-boot-starter-test | Starter for testing Spring Boot applications with libraries including JUnit, Hamcrest and Mockito | POM |
spring-boot-starter-jdbc | Starter for using JDBC with the Tomcat JDBC connection pool | POM |
spring-boot-starter-mobile | Starter for building web applications using Spring Mobile | POM |
spring-boot-starter-validation | Starter for using Java Bean Validation with Hibernate Validator | POM |
spring-boot-starter-hateoas | Starter for building hypermedia-based RESTful web application with Spring MVC and Spring HATEOAS | 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-data-neo4j | Starter for using Neo4j graph database and Spring Data Neo4j | POM |
spring-boot-starter-websocket | Starter for building WebSocket applications using Spring Framework’s WebSocket support | POM |
spring-boot-starter-aop | Starter for aspect-oriented programming with Spring AOP and AspectJ | POM |
spring-boot-starter-amqp | Starter for using Spring AMQP and Rabbit MQ | POM |
spring-boot-starter-data-cassandra | Starter for using Cassandra distributed database and Spring Data Cassandra | POM |
spring-boot-starter-social-facebook | Starter for using Spring Social Facebook | POM |
spring-boot-starter-jta-atomikos | Starter for JTA transactions using Atomikos | POM |
spring-boot-starter-security | Starter for using Spring Security | POM |
spring-boot-starter-mustache | Starter for building MVC web applications using Mustache views | POM |
spring-boot-starter-data-jpa | Starter for using Spring Data JPA with Hibernate | POM |
spring-boot-starter | Core starter, including auto-configuration support, logging and YAML | POM |
spring-boot-starter-groovy-templates | Starter for building MVC web applications using Groovy Templates views | POM |
spring-boot-starter-freemarker | Starter for building MVC web applications using FreeMarker views | POM |
spring-boot-starter-batch | Starter for using Spring Batch | POM |
spring-boot-starter-social-linkedin | Stater for using Spring Social LinkedIn | POM |
spring-boot-starter-cache | Starter for using Spring Framework’s caching support | POM |
spring-boot-starter-data-solr | Starter for using the Apache Solr search platform with Spring Data Solr | POM |
spring-boot-starter-data-mongodb | Starter for using MongoDB document-oriented database and Spring Data MongoDB | 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-jta-narayana | Spring Boot Narayana JTA Starter | 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 | POM |
spring-boot-starter-jta-bitronix | Starter for JTA transactions using Bitronix | POM |
spring-boot-starter-social-twitter | Starter for using Spring Social Twitter | POM |
spring-boot-starter-data-rest | Starter for exposing Spring Data repositories over REST using Spring Data REST | POM |
除了应用启动器之外,下面的启动器可以用来添加产品准备功能:
Table 13.2. Spring Boot 产品启动器
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也包括一些可以使用的启动器:
Table 13.3. Spring Boot 技术启动器
Name | Description | Pom |
---|---|---|
spring-boot-starter-undertow | Starter for using Undertow as the embedded servlet container. An alternative to spring-boot-starter-tomcat | 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-logging | Starter for logging using Logback. Default logging starter | 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-log4j2 | Starter for using Log4j2 for logging. An alternative to spring-boot-starter-logging |
Pom |
对于额外的社区共享的启动器,请看GitHub上
the spring-boot-starters
模块的README file。
14. 组织你的代码
Spring Boot工作时不要求任何特定的代码布局,但是有一些最佳实践还是很有帮助的。
14.1 使用“default”包
当一个类没有包含一个package
声明时,它当做是在default package
中。通常情况下不建议使用default package
,应该避免使用它。当Spring Boot应用使用@ComponentScan
,@EntityScan
或@SpringBootApplication
它会引起一些特别的问题,因为Spring Boot会读取每个jar中的每个类。
我们建议你遵循Java推荐的包命名规范,使用一个反转的域名(例如,
com.example.project
)。
14.2 定义主应用类
通常我们建议你将你的主应用类放在其它类之上的根包中。@EnableAutoConfiguration
注解经常放在你的主类(main class)中,对于某些像它隐式的定义了一个基search package
,例如,如果你正在写一个JPA应用,@EnableAutoConfiguration
注解的类所在的包将被用来搜索@Entity
项。
根包的应用也允许使用@ComponentScan
注解而不需要指定basePackage
特性。如果你的主类是在根包中,你也可以使用@SpringBootApplication
注解。
下面是一个典型的布局:
1 | com |
Application.java
文件会声明main
方法和基本的@Configuration
。
1 | package com.example.myproject; |
15. 配置类
Spring Boot支持基于Java的注解。尽管可以通过XML源调用SpringApplication.run()
方法,但我们通常建议你主要的源是一个@Configuration
类。
网上已经发布了许多使用XML配置来进行Spring配置的例子。但要尽可能的尝试使用等价的Java注解。搜索
enable*
注解是一个好的开端。
15.1 导入额外的配置类
你不必将所有的@Configuration
放到一个单独的类中。可以使用@Import
注解来导入额外的配置类。或者,你可以使用@ComponentScan
来自动获得所有的Spring组件,包括@Configuration
类。
15.2 导入XML配置
如果你绝对的必须使用基于XML的配置,我们推荐你仍然从@Configuration
类开始。你可以使用额外的@ImportResource
注解来加载XML配置文件。
16. 自动配置
Spring Boot自动配置会基于你添加的jar依赖试图自动配置你的Spring应用。例如,如果HSQLDB
在你的classpath中,并且你没有手动的配置任何数据库连接beans,我们将会在自动配置一个内存中的数据库。
你需要通过添加@EnableAutoConfiguration
或@SpringBootApplication
注解到你的@Configuration
类中的一个来选择性的加入自动配置。
你应该仅添加一个
@EnableAutoConfiguration
注解。我们通常建议你将它添加到你主要的@Configuration
类中。
16.1 逐渐替换自动配置
自动配置是非入侵性的,在任何时候你都可以开始定义你自己的配置来替换自动配置的指定部分。例如,如果你要添加你自己的DataSource
bean,默认嵌入的数据库支持将会退出。
如果你需要找出当前正在应用的自动配置和为什么,你可以用--debug
开关来启动你的应用。这将会使核心日志的输出级别变为debug级别并输出一个自动配置报告到控制台。
16.2 禁用特定的自动配置
如果你发现正在应用特定的你不想使用的自动配置类,你可以使用@EnableAutoConfiguration
注解的exclude
特性来禁用它们。
1 | import org.springframework.boot.autoconfigure.*; |
如果这个类不在classpath中,你可以使用这个注解的excludeName
特性并指定全限定名来代替。最后,你也可以通过spring.autoconfigure.exclude
属性来排除,从而控制自动配置类的列表。
你也可以在注解级别或使用属性来定义排除项。
17. Spring Beans和依赖注入
你可以自由的使用任何标准的Spring框架技术来定义你的beans和它们注入的依赖。为了简便,我们经常使用@ComponentScan
来发现你的beans,结合@Autowired
构造函数注入也工作的很好。
如果你根据上面的建议组织你代码(将你的应用类放在根包中),你可以添加@ComponentScan
注解而不需要任何参数。你所有的应用组件(@Component
,@Service
,@Repository
,@Controller
等等)将会作为Spring bean进行自动注册。
下面是一个@Service
Bean的例子,通过使用构造函数注入来获得RiskAssessor
bean。
1 | package com.example.service; |
注意使用构造函数注入允许
riskAssessor
字段标记为final
,意味着它接下来不能被修改。
18. 使用@SpringBootApplication注解
许多Spring Boot的开发者总是在它们的主类上加上@Configuration
,@EnableAutoConfiguration
和@ComponentScan
注解。由于这些注解频繁的在一起使用(尤其是你遵循上面的最佳实践时),Spring Boot提供了一个方便的@SpringBootApplication
注解来代替它们。
@SpringBootApplication
注解等价于使用@Configuration
,@EnableAutoConfiguration
和@ComponentScan
以及它们的默认特性:
1 | package com.example.myproject; |
@SpringBootApplication
也提供了别名来定制@EnableAutoConfiguration
和@ComponentScan
的特性。
19. 运行你自己的应用
将应用打包成jar并使用内嵌HTTP服务器的一个最大优势是你可以在任何地方运行你的程序。调试Spring Boot应用也很容易;你不必指定任何特定的IDE插件或扩展。
这一节只包含基于jar的打包,如果你想选择将你的应用打包成war文件,你应该参考你的服务器和IDE文档。
19.1 从IDE运行
你可以在你的IDE中运行一个Spring Boot应用将像运行一个简单的Java应用一样,然而,首先你需要导入你的工程。导入步骤根据你的IDE和构建系统会有所变化。大多数IDE可以直接导入Maven工程,例如Eclipse用户可以选择从File
菜单选择Import…
→ Existing Maven Projects
。
如果你不能直接将工程导入你的IDE中,你可以使用构建插件生成一个IDE元数据。Maven中包含Eclipse和IDEA的插件;Gradle有各种IDEs的插件。
如果你偶然的运行一个web应用两次,你会看到一个
Port already in use
错误。为了确保任何现有的实例被关闭,STS用户可以使用Relaunch
按钮而不是Run
按钮。
19.2 运行一个打包的应用
如果你使用Spring Boot的Maven或Gradle插件来创建一个可执行的jar包,你可以通过使用java -jar
来运行你的应用。例如:
1 | $ java -jar target/myproject-0.0.1-SNAPSHOT.jar |
它也支持以远程调试模式运行一个打包的应用。这允许你在打包的应用中添加一个调试器:
1 | $ java -Xdebug -Xrunjdwp:server=y,transport=dt_socket,address=8000,suspend=n -jar target/myproject-0.0.1-SNAPSHOT.jar |
19.3 使用Maven插件
Spring Boot Maven插件包含一个run
目标,可以用来快速编译并运行你的应用。应用以exploded形式运行,就像在IDE中运行一样。
1 | $ mvn spring-boot:run |
你也可以使用有用的操作系统环境变量:
1 | $ export MAVEN_OPTS=-Xmx1024m -XX:MaxPermSize=128M |
19.4 使用Gradle插件
Spring Boot Gradle插件也包含一个bootRun
任务,它可以以exploded方式运行你的应用。当你导入spring-boot-gradle-plugin
时,可以添加bootRun
任务:
1 | $ gradle bootRun |
你也可以使用有用的操作系统环境变量:
1 | $ export JAVA_OPTS=-Xmx1024m -XX:MaxPermSize=128M |
19.5 热交换
由于Spring Boot应用只是普通的Java应用,JVM热交换应该是开箱即用的。JVM热交换可以替换的字节码有限制,一个更全面的解决方案是JRebel或Spring Loaded工程。spring-boot-devtools
模块也支持快速的应用重启。
更多细节请看20章,下面的开发者工具部分和怎样热交换部分。
20. 开发者工具
Spring Boot包含额外的工具集合,可以使应用开发的过程更方便一点。spring-boot-devtools
模块可以包含进任何工程,用来提供额外的程序调试特性。为了添加工具支持,简单的添加模块依赖到你的构建系统中:
Maven.
1 | <dependencies> |
Gradle.
1 | dependencies { |
当运行一个完整的打包应用时,开发者工具会自动失效。如果你的应用是通过
java -jar
启动的,或者是通过一个特定的类加载器启动的,那它会被当做一个『产品级应用』。将依赖标记为optional
是阻止开发工具间接应用到使用你应用的其它模块的最佳实践。Gradle不支持optional
依赖开箱即用,同时你可能想看看propdeps-plugin。再打包文件默认不包含开发者工具。如果你想使用某些远程开发者工具特性,你需要让
excludeDevtools
构建属性包含它。Maven和Gradle插件都支持这个属性。
20.2 自动重启
当classpath
中的文件修改时,使用spring-boot-devtools
的应用会自动重启。当使用IDE开发时,这是一个很有用的功能,因为代码改变时它能快速的进行反馈。默认情况下,会监控classpath
指向的文件夹中任何条目的变化。注意某些资源例如静态资源和视图模板不需要重启应用。
触发重启
作为
DevTools
监视器classpath
中的资源,触发重启的唯一方式是更新classpath
。引起classpath
更新的方式取决于你使用的IDE。在Eclipse中,保存一个修改的文件将引起classpath
更新并触发重启事件。在IntelliJ IDEA中,构建工程(Build → Make Project
)将会有同样的效果。
只要启用了分支,你也可以通过支持的构建系统启动你的应用(例如,Maven和Gradle),因为
DevTools
需要一个独立的应用类加载器来进行正确操作。当Gradle和Maven在classpath
中检测到DevTools
时,它们默认的进行了那个工作。
当使用
LiveReload
,自动重启能很好的工作。更多细节请看下面。如果你使用JRebel
进行自动重启,将不支持动态的类重加载。其它的开发者工具功能(例如LiveReload
和属性覆写)仍能继续使用。
DevTools
依赖应用上下文关闭钩子来进行重启期间的关闭。如果你禁用了关闭钩子它将不能正确工作(SpringApplication.setRegisterShutdownHook(false)
)。
当决定
classpath
中输入引起的改变是否应该触发重启时,DevTools
会自动忽略命名为spring-boot
,spring-boot-devtools
,spring-boot-autoconfigure
,spring-boot-actuator
和spring-boot-starter
的工程。
重启与重载(重新加载)
Spring Boot提供的重启技术是通过两个类加载器进行工作的。加载进基类加载器的类不能改变(例如,那些第三方jar包)。那些你正在开发的类加载进重启类加载器中。当应用重启时,丢弃旧的重启类加载器并创建一个新的。这种方法意味着应用重启时比『冷启动』更快,因为基类加载器已经存在并可用。
如果你发现你的应用重启不够快,或者你碰到了类加载问题,你可以考虑重载技术例如ZeroTurnaround的JRebel。这些工作通过加载时类的重写使它们更适合重载。Spring加载提供了另一种选择,但许多框架都不支持,也不支持商业化。
20.2.1 例外资源
某些资源当它们改变时不一定需要触发重启。例如,Thymeleaf模板可以就地编辑。默认情况下,/META-INF/maven
,/META-INF/resources
,/resources
,/static
,/public
或/templates
中资源的改变不会触发重启,但会触发实时重载。如果你想定制这些例外项,你可以使用spring.devtools.restart.exclude
属性。例如,仅排除/static
和/public
,设置如下:
1 | spring.devtools.restart.exclude=static/**,public/** |
如果你想保持这些默认,添加额外的例外项,可以使用
spring.devtools.restart.additional-exclude
属性。
20.2.2 监控其它路径
当你修改不在classpath
中的文件时,你可能也想重启或重载你的应用。为了这样做,可以使用spring.devtools.restart.additional-paths
属性来监控其它路径上的变化。你可以使用前面描述的spring.devtools.restart.exclude
属性来控制其它路径上的变化是否会触发重启或仅触发实时重载。
20.2.3 禁用重启
如果你想使用重启功能你可以通过spring.devtools.restart.enabled
属性禁用它。大多数情况下你可以在你的application.properties
中设置它(这仍会初始化重启类加载器但它不会监控文件的变化)。
如果你需要完整的禁用重启支持,例如,因为它不能与一个特定的库一起工作,你需要在调用SpringApplication.run(…)
之前设置一个System
属性。例如:
1 | public static void main(String[] args) { |
20.2.4 使用触发器文件
如果你的IDE可以持续编译变化的文件,你可以只在特定的时间触发重启。为了实现这个功能你可以使用『触发器文件』,当你需要真正触发重启检查时,它是一个你必须要修改文件。修改这个文件只触发重启检查,只有Devtools
检测到它必须要做些事情时,重启才会发生。触发器文件应该进行手动更新,或通过IDE插件更新。
为了使用触发器文件需要使用spring.devtools.restart.trigger-file
属性。
为了使你所有的工程都表现一样,你需要将
spring.devtools.restart.trigger-file
设置为全局设置。
20.2.5 定制重启类加载器
像前面的的Restart vs Reload
部分所讲的那样,重启功能是通过两个类加载器实现的。对于大多数应用来说这个方法能很好的工作,但是有时候它也会引起一些类加载问题。
默认情况下,IDE中的任何开放的工程都会使用“restart”类加载器进行加载,任何规范的.jar
文件都会使用“base”类加载器进行加载。如果你在一个多模块工程中工作,不是每一个模块都导入到你的IDE中,你可能需要定制一些东西。为了实现这个功能你可以创建一个META-INF/spring-devtools.properties
文件。
spring-devtools.properties
可以包含restart.exclude.
和restart.include.
前缀属性。include
元素应该拉进“restart”类加载器中,exclude
元素应该推入到“base”类加载器中。属性值是应用到classpath
中的一个正则表达式。
例如:
1 | restart.exclude.companycommonlibs=/mycorp-common-[\\w-]+\.jar |
所有属性的键必须是唯一的。只要
restart.include.
或restart.exclude
作为一个属性启动,它就被应用。
classpath
中的所有META-INF/spring-devtools.properties
都会被加载。你可以将文件打包进你的工程中,或这个工程使用的库中。
20.2.6 已知的限制
当存在使用标准ObjectInputStream
进行反序列化的对象时,重启功能不能很好的工作。如果你需要反序列化数据,你可能需要使用Spring的ConfigurableObjectInputStream
和Thread.currentThread().getContextClassLoader()
。
遗憾的是,一些第三方库反序列化时没有考虑上下文类加载器。如果你发现了这样的问题,你需要请求原作者进行修正。
20.3 实时重载
spring-boot-devtools
模块包含一个内嵌的实时重载服务器,当资源改变时可以用来触发浏览器重新刷新。实时重载浏览器扩展对于livereload.com中的Chrome,Firefox和Safari而言是可用的。
当你的应用运行时,如果你不想启动实时重载服务器,你可以将spring.devtools.livereload.enabled
属性设为false
。
一次你只可以运行一个实时重载服务器。在启动你的应用之前,确保没有其它的实时重载服务器在运行。如果你从你的IDE中启动多个应用,只有第一个应用有实时重载服务器支持。
20.4 全局设置
通过添加一个名为.spring-boot-devtools.properties
的文件到你的$HOME
文件夹中(注意文件名以.
开头),你可以配置全局开发者工具设置。任何添加到这个文件的属性都将应用到你机器上所有使用开发者工具的Spring Boot应用中。例如,为了配置重启时总是使用一个触发器文件,你需要添加如下内容:
~/.spring-boot-devtools.properties.
1 | spring.devtools.reload.trigger-file=.reloadtrigger |
20.5 远程应用
Spring Boot开发者工具是不受本地环境限制的,在运行远程应用时你也可以使用一些功能。远程支持是选择性加入的,为了使它起作用你需要确保devtools
包含在再打包的文件中:
1 | <build> |
然后你需要设置spring.devtools.remote.secret
属性,例如:
1 | spring.devtools.remote.secret=mysecret |
使
spring-boot-devtools
在远程应用上起作用是有安全风险的。在产品部署时,你不应该让它支持spring-boot-devtools
。
远程devtools
需要两部分提供支持:一个接收连接的服务器端,一个运行在IDE中的客户端应用。当设置spring.devtools.remote.secret
属性时,服务器组件会自动起作用。客户端组件必须手动启动。
20.5.1 运行远程客户端应用
远程客户端应用设计要在你的IDE中运行。你需要运行org.springframework.boot.devtools.RemoteSpringApplication
,与要连接的远程工程要使用同样的classpath。传给应用的非可选参数应该是你要连接的远程URL。
例如,如果你在使用Eclipse或STS,你有一个名为my-app
的工程,它已经部署到了云计算中,你需要按照下面的步骤去做:
从
Run
菜单中选择Run Configurations…
。创建一个新的
Java Application
“launch configuration”。浏览
my-app
工程。使用
org.springframework.boot.devtools.RemoteSpringApplication
作为主类。添加
https://myapp.cfapps.io
到Program arguments
(或无论你的远程URL是什么)。
因为远程客户端与真实的应用使用的
classpath
相同,因此它可以直接读取应用属性。这就是spring.devtools.remote.secret
属性是怎样读取并传递给服务器进行授权的。
为了传输可以加密,密码不能被解析,建议总是使用
https://
作为连接协议。
如果你需要使用代理访问远程应用,配置
spring.devtools.remote.proxy.host
和spring.devtools.remote.proxy.port
属性。
20.5.2 远程更新
远程客户端会像本地重启那样监控你应用的classpath
的变化。任何资源的更新都会推送到远程应用并(如果需要的话)触发重启。如果你在迭代一个本地没有的使用云服务的功能,它是非常有帮助的。通常更新和重启比整个重新构建部署更快。
当远程客户端运行时只监控文件。如果在启动远程客户端之前你修改了文件,它将不会推送到远程服务器。
20.5.3 远程调试通道
当在远程应用上分析问题时,Java远程调试是非常有用的。遗憾的是,当你的应用部署离开你的数据中心时,远程调试并不总是能用的。如果你正在使用一个基于容器的技术例如Docker,要设置远程调试也是非常棘手的。
为了帮助解决这些限制,devtools
支持在HTTP协议上的远程调试通道。远程客户端提供一个端口为8000
的本地服务器,你可以在这上面添加一个远程调试器。一旦建立了连接,调试通道将会在HTTP上发送到远程应用上。如果你想使用一个不同的端口,你可以使用spring.devtools.remote.debug.local-port
属性。
你需要确保你的远程应用启动了并且远程调试可用。这经常可以通过配置JAVA_OPTS
来完成。例如,在云计算平台你可以添加下面的内容到你的manifest.yml
中:
1 | --- |
注意你不必向
-Xrunjdwp
传递address=NNNN
选择。如果被忽略Java将会简单的选择一个随机自由的端口。
在网上调试一个远程服务可能是非常慢的,你可能需要在你的IDE中添加
timeouts
。例如,在Eclipse中你可以从Preferences…
选择Java → Debug
,并将Debugger timeout (ms)
改成更合适的值(60000
在大多数情况下都能很好工作)。
21. 将你的应用打包成产品
可执行jars
可以用来进行产品部署。当它们是自包含时,理想情况下它们也是适合云部署的。
对于其它的“production ready”功能,例如健康,审计和度量REST或JMX端点;考虑添加spring-boot-actuator
。更多细节请看第五部分,“Spring Boot Actuator: Production-ready features”。
22. 接下来读什么
现在你应该对怎么使用Spring Boot以及应该循序的一些最佳实践有了很好的理解。你可以继续学习关于Spring Boot的一些深度功能,或者你可以跳过前面,直接阅读Spring Boot “production ready”方面的内容。
Part IV. Spring Boot特性
这一部分进入Spring Boot细节部分。在这部分你会了解到你想使用和定制的一些重要特性。如果你还没准备好,你可以阅读第二部分“Getting started”和第三部分“Using Spring Boot”,可以对基础知识有个较好的认识。
23. SpringApplication
SpringApplication
提供了一种很方便的方式来引导Spring应用,Spring应用可以从main()
方法中启动。许多情况下你可以委托给静态方法SpringApplication.run
:
1 | public static void main(String[] args) { |
当你的应用启动时你应该看到类似于下面的东西:
1 | . ____ _ __ _ _ |
默认情况下会输出INFO
日志信息,包括一些相关的启动细节例如启动应用的用户。
23.1 启动失败
如果你的应用启动失败,注册FailureAnalyzers
有可能会提供专门的错误信息和解决这个问题的具体行动。例如,如果你启动一个8080
端口的web应用并且这个端口已经被占用,你应该会看到类似于下面的内容:
1 | *************************** |
Spring Boot提供了许多
FailureAnalyzer
实现,你可以很容易添加自己的FailureAnalyzer
实现。
如果没有失败分析器能处理这个异常,你仍可以显示完整的自动配置报告,从而更好的理解什么地方出问题了。为了实现这个你需要启用debug
属性或启用org.springframework.boot.autoconfigure.logging.AutoConfigurationReportLoggingInitializer
的DEBUG
日志。
例如,如果你使用java -jar
运行应用,你可以用下面的形式启用debug
属性:
1 | $ java -jar myproject-0.0.1-SNAPSHOT.jar --debug |
23.2 定制Banner
启动时打印的标语可以通过在classpath中添加一个banner.txt
文件或者将banner.location
设置为banner.txt
文件的位置来修改。如果文件是一种不常见的编码方式,你可以设置banner.charset
(默认是UTF-8
)。除了文本文件之外,你也添加一个banner.gif
,banner.jpg
或banner.png
图像文件到classpath中,或者设置一个banner.image.location
属性。图像将被转换成ASCII艺术表示并打印在文本标语之上。
在banner.txt
内部你可以使用下面的任何占位符:
Table 23.1. Banner变量
Variable | Description |
---|---|
${application.version} | 你的应用的版本号在MANIFEST.MF 中声明。 例如Implementation-Version: 1.0 打印成1.0 . |
${application.formatted-version} | 在MANIFEST.MF 中的声明的应用版本号进行格式化显示(加上前缀v 并用括号包裹)。例如(v1.0) 。 |
${spring-boot.version} | 你使用的Spring Boot版本。例如1.4.2.RELEASE . |
${spring-boot.formatted-version} | 你使用的Spring Boot版本进行格式化显示加上前缀v 并用括号包裹)。例如(v1.4.2.RELEASE) 。 |
${Ansi.NAME} (or ${AnsiColor.NAME}, ${AnsiBackground.NAME}, ${AnsiStyle.NAME}) | NAME 是ANSI转义码的名字。更多细节请看AnsiPropertySource 。 |
${application.title} | 在MANIFEST.MF 中声明的应用标题。例如Implementation-Title: MyApp 打印成MyApp . |
如果你想自动生成一个标语你可以使用
SpringApplication.setBanner(…)
方法。使用org.springframework.boot.Banner
接口并实现你自己的printBanner()
方法。
你也可以使用spring.main.banner-mode
属性来决定标语是否必须在System.out
(控制台)上输出,使用配置的日志(log)或一点也不用(off)。
如果你想在你的应用中禁用banner,YAML会将
off
映射为false
,因此要确保添加引用。
1
2
3 spring:
main:
banner-mode: "off"
23.3 定制SpringApplication
如果你不喜欢默认的SpringApplication
,你可以创建一个本地实例并定制它。例如,关闭你写的banner:
1 | public static void main(String[] args) { |
传给
SpringApplication
的构造函数参数是Spring beans配置源。在大多数情况下将会引用@Configuration
类,但它们也可以引用XML配置或应该扫描的包。
也可以使用application.properties
文件配置SpringApplication
。更多细节请看24章,『外部配置』。
完整的配置选项列表,请看SpringApplication
文档。
23.4 流畅的构建器API
如果你需要构建ApplicationContext
分层(多个具有父/子关系的上下文),或者你更喜欢使用fluent
的构建器API,你可以使用SpringApplicationBuilder
。
SpringApplicationBuilder
允许你链接多个方法调用,包括允许你创建分层的parent
和child
方法。
例如:
1 | new SpringApplicationBuilder() |
当创建
ApplicationContext
分层时有一些限制,例如,子上下文必须包含web组件,父子上下文将使用同一个Environment
。更完整的细节请看SpringApplicationBuilder
文档。
23.5 应用事件和监听器
除了平常的Spring框架事件之外,例如ContextRefreshedEvent
,SpringApplication
会发送一些其它的应用事件。
在
ApplicationContext
创建之前实际上会触发一些事件,因此你不能使用@Bean
来注册这些监听器。你可以通过SpringApplication.addListeners(…)
或SpringApplicationBuilder.listeners(…)
方法来注册这些监听器。如果你想自动注册这些监听器,不管上下文的创建方式,你可以在你的工程中添加
META-INF/spring.factories
文件,并通过org.springframework.context.ApplicationListener
作为key来引用你的监听器。
1 org.springframework.context.ApplicationListener=com.example.project.MyListener
当你的应用运行时,应用事件以下面的顺序发送:
- 在运行启动时发送
ApplicationStartedEvent
,除了监听器和初始化器注册之外,在进行任何处理之前发送。 - 当在上下文中使用的
Environment
已知时,发送ApplicationEnvironmentPreparedEvent
,但发送是在上下文创建之前。 - 在再刷新启动之前,但在bean定义加载之后,发送
ApplicationPreparedEvent
。 - 在再刷新之后,发送
ApplicationReadyEvent
,任何相关的回调函数都处理完成之后,意味着应用已经准备处理服务请求了。 - 如果启动时出现异常,发送
ApplicationFailedEvent
.
经常你不需要使用应用事件,但知道它们的存在是便利的。Spring Boot内部使用事件来处理大量的任务。
23.6 Web环境
SpringApplication
会尝试创建代表你的合适的ApplicationContext
类型。默认情况下,会使用AnnotationConfigApplicationContext
或AnnotationConfigEmbeddedWebApplicationContext
,依赖于你是否在开发一个web应用。
使用的决定web environment
的算法是相对简单的(基于现有的一些类)。如果你需要覆写默认值你可以使用setWebEnvironment(boolean webEnvironment)
。
完全控制ApplicationContext
类型也是可能的,通过调用setApplicationContextClass(…)
使用。
当在JUnit测试时使用
SpringApplication
,经常需要调用setWebEnvironment(false)
。
23.7 访问应用参数
如果你需要访问传进SpringApplication.run(…)
中的应用参数,你可以注入org.springframework.boot.ApplicationArguments
bean。ApplicationArguments
接口提供了访问原始String[]
和转换的option
,non-option
参数。
1 | import org.springframework.boot.* |
Spring Boot也在Spring
Environment
中注册CommandLinePropertySource
。这也允许你使用@Value
注解注入单个应对参数。
23.8 使用ApplicationRunner或CommandLineRunner
如果你需要在SpringApplication
启动时运行一些特定的代码,你可以实现ApplicationRunner
或CommandLineRunner
接口。这两个接口以同样方式工作,并有一个单独的run
方法,在SpringApplication.run(…)
之前会调用这个run
方法。
CommandLineRunner
接口提供了对应用参数的访问,应用参数作为一个简单的字符串数组,而ApplicationRunner
使用前面描述的ApplicationArguments
接口。
1 | import org.springframework.boot.* |
另外,如果定义的CommandLineRunner
或ApplicationRunner
beans必须以指定顺序调用,你可以实现org.springframework.core.Ordered
接口或org.springframework.core.annotation.Order
注解。
23.9 应用退出
为了确保ApplicationContext
在关闭时安全退出, 每个SpringApplication
都会在JVM中注册一个关闭钩子。所有的标准Spring生命周期回调函数(例如DisposableBean
接口,或@PreDestroy
注解)都会被使用。
另外,当应用退出时,如果它们想返回一个特定的退出码,beans可以实现org.springframework.boot.ExitCodeGenerator
接口。
23.10 Admin功能
如果应用想启用admin相关的功能,可以指定spring.application.admin.enabled
属性。这会在平台MBeanServer
上暴露SpringApplicationAdminMXBean
。你可以使用这个功能远程的管理你的Spring Boot应用。对于任何服务包裹的实现这是很有用的。
如果你想知道应用运行的HTTP接口,通过关键字
local.server.port
可以得到这个属性。
当启用这个功能时要非常小心,因为MBean会暴露一个关闭应用的方法。
24. 外部配置
Spring Boot允许你进行外部化配置,因此可以将同样的应用代码在不同的环境中运行。你可以使用属性文件,YAML文件,环境变量和命令行参数来进行外部化配置。属性值可以使用@Value
注解直接注入到你的beans中,通过Spring的Environment
抽象或通过@ConfigurationProperties
绑定到结构化对象上来访问。
Spring Boot使用非常特别的PropertySource
顺序,这个顺序的设计是为了允许值的合理重写。属性被认为是按照以下顺序:
- 根目录下的开发工具全局设置属性(当开发工具激活时为
~/.spring-boot-devtools.properties
)。 - 测试中的
@TestPropertySource
注解。 - 测试中的
@SpringBootTest#properties
注解特性。 - 命令行参数。
SPRING_APPLICATION_JSON
中的属性(环境变量或系统属性中的内联JSON嵌入)。ServletConfig
初始化参数。ServletContext
初始化参数。java:comp/env
的JNDI特性。- Java系统属性 (
System.getProperties()
)。 - 操作系统环境变量。
RandomValuePropertySource
只在random.*
中有属性。- jar包之外的指定配置文件的应用属性(
application-{profile}.properties
和YAML变量)。 - jar包之内的指定配置文件的应用属性(
application-{profile}.properties
和YAML变量)。 - jar包之外的应用属性 (
application.properties
和YAML变量)。 - jar包之内的应用属性 (
application.properties
和YAML变量)。 @Configuration
类中的@PropertySource
注解 。- 默认属性(通过
SpringApplication.setDefaultProperties
指定).
为了提供一个具体的例子,假设你开发了一个使用名字属性的@Component
:
1 | import org.springframework.stereotype.* |
在你的应用路径中(例如在你的jar内部),你可以使用application.properties
为name
提供一个合理的默认属性值。当在新环境运行时,application.properties
可以在jar外部提供来重写name
;对于一次性测试,你可以通过指定的命令行切换来启动(例如java -jar app.jar --name="Spring"
)。
SPRING_APPLICATION_JSON
可以在命令行中通过环境变量提供。例如在UNIX shell中:
1 $ SPRING_APPLICATION_JSON='{"foo":{"bar":"spam"}}' java -jar myapp.jar在这个例子中,Spring的
Environment
中会有foo.bar=spam
。你也可以在系统变量中提供JSON作为spring.application.json
。
1 $ java -Dspring.application.json='{"foo":"bar"}' -jar myapp.jar或命令行参数:
1 $ java -jar myapp.jar --spring.application.json='{"foo":"bar"}'或JNDI变量
java:comp/env/spring.application.json
24.1 配置随机值
当注入随机值时,RandomValuePropertySource
是很有用的(例如,注入秘密或测试用例)。它可以产生integers
,longs
,uuids
或strings
,例如:
1 | my.secret=${random.value} |
random.int*
语法OPEN value (,max) CLOSE
,OPEN,CLOSE
可以是任何字符,value,max
是整数。如果提供了max
,则value
是最小值,max
是最大值(不包含)。
24.2 访问命令行属性
默认情况下,SpringApplication
会将任何命令行参数(以--
开头,例如--server.port=9000
)转换成property
并将其添加到Spring的Environment
中。正如前面提到的那样,命令行属性总是优先于其它的配置源。
如果你想命令行属性添加到Environment
中,你可以使用SpringApplication.setAddCommandLineProperties(false)
禁用它。
24.3 应用属性文件
SpringApplication
会从以下位置的application.properties
文件中加载属性并将它们添加到Spring的Environment
中:
当前目录的子目录
/config
当前目录
classpath中的
/config
包classpath的根目录
这个列表是按优先级排序的(在更高位置的属性会重写定义在更低位置的属性)。
你也可以使用YAML(
.yml
)文件来代替.properties
文件。
如果你不喜欢用application.properties
作为配置文件的名字,你可以通过指定spring.config.name
环境属性来来改变配置文件的名字。你也可以使用spring.config.location
环境属性来引用一个显式的位置(目录位置或文件路径以逗号分隔)。
1 | $ java -jar myproject.jar --spring.config.name=myproject |
或
1 | $ java -jar myproject.jar --spring.config.location=classpath:/default.properties,classpath:/override.properties |
spring.config.name
和spring.config.location
可以在早期用来决定加载哪一个文件,因此必须被定义为环境属性(通常是操作系统环境,系统属性或命令行参数)。
如果spring.config.location
包含目录(相对于文件而言),它们应该以/
结尾(在加载之前,在后面添加上从spring.config.name
中产生的名字,包括指定配置文件的名字)。在spring.config.location
中指定的文件按原样使用,不支持指定配置文件变量,将会被任何指定配置文件的属性覆盖。
默认搜索路径一直用classpath:,classpath:/config,file:,file:config/
,不管spring.config.location
中的值。搜索路径按从低到高排序(file:config/
最高)。如果你指定了自己的位置,它们优先于所有的默认位置并使用同样的从低到高的顺序。这样你可以在application.properties
中为你的应用设置默认值(或你可以选择spring.config.name
的其它生成文件基本名),在运行时用其它的文件覆盖它,同时保留默认值。
如果你使用环境变量而不是系统属性,大多数操作系统不允许句号分隔的关键字,但你可以用下划线代替(例如,
SPRING_CONFIG_NAME
代替spring.config.name
)。如果你在容器中运行,那么JNDI属性(在
java:comp/env
中)或servlet上下文初始化参数也可以用来代替环境变量或系统属性。
24.4 特定的profile属性
除了application.properties
文件之外,特定的profile属性也可以使用命名规范application-{profile}.properties
来定义。Environment
有一系列默认配置文件(默认为[default]
),如果没有设置激活的配置文件,会使用默认的配置文件(例如,如果没有激活显式的配置文件,则会加载application-default.properties
中的属性)。
特定的profile属性会从相同位置加载application.properties
,特定的profile文件总是覆盖非特定的配置文件,无论特定profile文件在你打包的jar内部还是外部。
如果指定了几个配置文件,将会应用最后一个。例如,spring.profiles.active
属性指定的配置文件在那些配置的文件之后通过SpringApplication
API添加,因此优先级更高。
如果你在
spring.config.location
中指定了任何文件,那些文件的特定profile版本将不会被考虑。如果你也想使用特定的profile属性,在spring.config.location
中使用目录。
24.5 属性中的占位符
当使用application.properties
中的值时,会通过现有的Environment
进行过滤,因此你可以参考前面定义的值(例如从系统属性中)。
1 | app.name=MyApp |
你也可以使用这个技术来创建现有的Spring Boot属性的
short
版本。怎样使用的更多细节请看70.4小节,“Use ‘short’ command line arguments”。
24.6 使用YAML代替Properties
YAML是JSON的超集,它可以用一种非常方便的形式来指定分层配置数据。当你的类路径有SnakeYAML库时,SpringApplication
类自动支持YAML作为properties的一个替代品。
如果你使用‘Starters’,SnakeYAML将由
spring-boot-starter
自动提供。
24.6.1 加载YAML
Spring框架提供了两个类用来方便的加载YAML文档。YamlPropertiesFactoryBean
将加载YAML作为Properties
,YamlMapFactoryBean
将加载YAML作为Map
。
例如,下面的YAML文档:
1 | environments: |
将被转换成这些属性:
1 | environments.dev.url=http://dev.bar.com |
YAML列表通过[index]
解引用表示为属性的key,例如这个YAML:
1 | my: |
将被转换成这些属性:
1 | my.servers[0]=dev.bar.com |
为了像使用Spring的DataBinder
一样(@ConfigurationProperties
的功能)绑定这些属性,你需要在类型为java.util.List
(或Set
)的目标bean中有属性,你需要提供一个setter
或用一个可变的值来对它初始化,例如,绑定上面的属性值:
1 | @ConfigurationProperties(prefix="my") |
24.6.2 在Spring Environment中公开YAML为属性
YamlPropertySourceLoader
类可以在Spring的Environment
中将YAML作为PropertySource
。这允许你使用熟悉的@Value
注解和占位符语法来访问YAML属性。
24.6.3 多profile的YAML文档
你可以在单个文件中指定多个特定profile的YAML文档,当应用文档时,通过spring.profiles
关键字来表明使用哪个文档。例如:
1 | server: |
在上面的例子中,如果development
profile被激活,server.address
的值为127.0.0.1
。如果development
和production
profile不可用,server.address
的值为192.168.1.100
。
当应用上下文启动时,如果没有显式的激活profile,则激活默认的profile。因此在这个YAML文件中我们仅在”default” profile中设置了security.user.password
。
1 | server: |
在这个例子中,密码总是设置的,因为它没有添加到如何profile中,必要时我们必须在其它的profile中显式的对它重新设置:
1 | server: |
Spring profiles被设计为使用”spring.profiles”元素可以选择性的用!
字符进行否定。如果否定的和非否定的profile指向一个单独的文档,必须至少匹配一个非否定的profile,可能没有否定的profile进行匹配。
24.6.4 YAML缺点
YAML文件不能通过@PropertySource
注解进行加载。因此在这种情况下如果你需要加载值,你需要使用属性文件。
24.6.5 合并YAML列表
正如我们上面看到的,任何YAML内容最终都要转换成属性。当通过profile重写“list“属性时,这个过程可能有违直觉。
例如,假设MyPojo
对象的name
和description
属性默认情况下为空。从FooProperties
使用一个MyPojo
列表:
1 | "foo") ( |
考虑下面的配置:
1 | foo: |
如果dev
profile没有激活,FooProperties.list
将包含一个上面定义的MyPojo
输入。然而如果dev
profile可用,lists
仍只包含一个输入(name为“my another name”,description为空)。这个配置将不能添加第二个MyPojo
到list
中,并且它将不能合并这些项。
当在多个profiles中指定一个集合时,将会使用最高优先级的那个集合(唯一的哪个):
1 | foo: |
在上面的例子中,假设dev
profile被激活,FooProperties.list
将包含一个MyPojo
输入(name为“my another name”,description为空)。
24.7 类型安全的配置属性
Boot提供了一种处理属性的可替代方法,允许强类型的beans管理和验证你的应用的配置。例如:
1 | "connection") (prefix= |
建议添加getters和setters,绑定是通过标准的Java Beans属性描述符,像在Spring MVC中一样。对于不可变类型或那些从
String
中可直接强制转换的类型,它们是强制性的。只要它们被初始化,maps,集合或数组需要getter方法,但不需要setter方法因为通过绑定起它们可以直接变化。如果有setter,可以创建Maps,集合和数组。Maps和集合可以通过getter扩展,数组扩展需要setter。如果它们有默认的构造函数,或构造函数接收可以从String
类型强制转换的值,嵌入的POJO属性也可以创建(因此setter不是强制性的)。一些人使用Lombok项目来自动添加getter和setter。
请看
@Value
和@ConfigurationProperties
之间的不同。
你也需要在@EnableConfigurationProperties
注解中列出要注册的属性类:
1 |
|
当
@ConfigurationProperties
以那种方式注册时,这个bean将有一个常规的名字:<prefix>-<fqn>
,<prefix>
是在@ConfigurationProperties
注解中指定的环境关键字的前缀,<fqn>
是bean的完整合格的名字。如果注解没有提供任何前缀,则只用bean的完整合格的名字。在上面的例子中bean名字是
connection-com.example.ConnectionProperties
,假设ConnectionProperties
在com.example
包中。
即使上面的配置会为ConnectionProperties
创建一个正规的bean,我们建议@ConfigurationProperties
只处理环境,特别是不从上下文中注入其它的beans。已经说过,为了任何带有@ConfigurationProperties
注解的bean可以根据Environment
属性进行配置,@EnableConfigurationProperties
注解也自动应用到你的工程中。确保ConnectionProperties
已经是一个bean,你可以简写上面的MyConfiguration
:
1 |
|
这种风格的配置在SpringApplication
的外部化YAML配置中工作的尤其好:
1 | # application.yml |
为了同@ConfigurationProperties
beans一起工作,你可以像任何其它bean一样以相同的方式注入它们:
1 | @Service |
使用
@ConfigurationProperties
也允许你生成IDEs可以使用的元数据文件。更多细节请看附录B,配置元数据附录。
24.7.1 第三方配置
也可以使用@ConfigurationProperties
来注解一个类,你也可以在公有的@Bean
方法上使用它。当你想绑定属性到你控制之外的第三方组件上时尤其有用。
1 | @ConfigurationProperties(prefix = "foo") |
任何定义的带有foo
前缀的属性都将以类似于上面的ConnectionProperties
例子中的方式映射到FooComponent
bean中。
24.7.2 松散绑定
Spring Boot使用一些松散的规则将Environment
属性绑定到@ConfigurationProperties
beans上,因此不需要在Environment
属性名和bean属性名之间进行确切的匹配。常见的有用例子包括破折号分隔(例如,context-path绑定到contextPath),大小写(例如PORT
绑定到port
,)环境属性。
例如,给定下面的@ConfigurationProperties
类:
1 | @ConfigurationProperties(prefix="person") |
下面的属性名都可以使用:
表24.1. 松散绑定
Property | Note |
---|---|
person.firstName | 标准的驼峰写法 |
person.first-name | 破折号注解,建议在.properties 和.yml 文件中使用 |
person.first_name | 下划线注解,.properties 和.yml 文件中的可替代写法 |
PERSON_FIRST_NAME | 大写形式。当使用系统变量时推荐 |
24.7.3 属性转换
当Spring绑定属性到@ConfigurationProperties
beans时,它将试图将外部的应用属性强制转换成正确的类型。如果你需要定制类型转换你可以提供一个ConversionService
bean(bean id为conversionService
),或定制属性编辑器(通过CustomEditorConfigurer
bean),或定制Converters
(带有@ConfigurationPropertiesBinding
注解的bean定义)。
bean要求在应用生命周期中的早期,要确保限制
ConversionService
使用的依赖。通常,任何你要求的依赖可能在创建时不是完整初始化的。如果你定制的ConversionService
不要求配置关键字强制转换,你可能想重新命名你定制的ConversionService
,并且只依赖满足@ConfigurationPropertiesBindings
的定制转换器。
24.7.4 @ConfigurationProperties验证
Spring Boot会试图验证外部化配置,默认使用JSR-303(如果它在classpath中)。你可以简单的添加JSR-303 javax.validation
约束注解到你的@ConfigurationProperties
类中:
1 | @ConfigurationProperties(prefix="connection") |
为了验证嵌入的属性值,你必须注解相关的字段作为@Valid
来触发它的校验。例如,在上面的ConnectionProperties
例子上构建:
1 | @ConfigurationProperties(prefix="connection") |
通过创建一个称为configurationPropertiesValidator
的bean定义,你也可以添加定制的Spring Validator
。@Bean
方法应该声明静态的。配置属性验证器在应用生命周期的早期创建,声明@Bean
方法为静态方法,允许不必实例化@Configuration
类就创建bean。这避免了任何早期实例化可能引起的问题。这儿有一个属性验证的例子因此你可以看一下怎样设置它
spring-boot-actuator
模块包含一个端点,这个端点将公开所有的@ConfigurationProperties
beans。简单的将你的web浏览器指向/configprops
或用等价的JMX端点。更多细节请看产品级功能
24.7.5 @ConfigurationProperties和@Value
@Value
是一种核心的容器功能,它不能作为类型安全配置属性提供同样的功能。下面的表中总结了@ConfigurationProperties
和@Value
支持的功能:
功能 | @ConfigurationProperties |
@Value |
---|---|---|
松散绑定 | Yes | No |
元数据支持 | Yes | No |
SpEL评估 | No | Yes |
如果你为自己的组件定义了一些配置关键字,我们建议你将它们分组到带有@ConfigurationProperties
注解的POJO中。也请注意@Value
不支持松散绑定,如果你需要用环境变量提供值,它不是一个好的选择。
最后,虽然你可以在@Value
中写表达式,但这种表达式不能从应用属性文件中处理。
25. Profiles
Spring Profiles提供了一种隔离部分应用配置的方式,并让这些配置只在特定的环境生效。任何带有@Profile
标记的@Component
或@Configuration
在加载时都会受限制:
1 | @Configuration |
以正常的Spring方式,你可以使用spring.profiles.active
Environment
属性来指定激活哪一个profiles。你可以在任何常见的方式指定这个属性,例如你可以在你的application.properties
中包含它:
1 | spring.profiles.active=dev,hsqldb |
或在命令行用--spring.profiles.active=dev,hsqldb
指定。
25.1 添加激活的profiles
spring.profiles.active
属性与其它的属性一样遵循同样的排序规则,最高的PropertySource
优先。这意味着你可以在application.properties
指定激活的profiles,然后用命令行转换替代它们。
例如,当一个应用具有以下属性且运行时使用--spring.profiles.active=prod
转换,proddb
和prodmq
profiles也将被激活:
1 | --- |
记住可以在YAML文档中定义
spring.profiles
来决定在配置中包含特定的文档。更多细节请看70.7小节,“根据环境更改配置”。
25.2 以编程方式设置profiles
你可以在你的应用运行之前以编程的方式调用SpringApplication.setAdditionalProfiles(…)
来设置激活的profiles。也可以使用Spring的ConfigurableEnvironment
接口来激活profiles。
25.3 指定profile的配置文件
application.properties
(或application.yml
)和通过@ConfigurationProperties
引用的文件的特定profiles变种都被当做文件进行加载。更多细节请看24.4小节,“Profile-specific properties”。
26. Logging
Spring Boot所有的内部日志都采用Commons Logging,但开放了底层的日志实现。提供了对Java Util Logging,Log4J2和Logback的默认实现。在每个logger中都预先配置使用控制台作为输出,同时也可用可选的文件输出。
默认情况下,如果使用Starters
,Logback将作为日志。也要包含恰当的Logback规则来保证依赖库使用Java Util Logging,Commons Logging,Log4J或SLF4J都能正确工作。
在Java中有许多日志框架可用。不必担心上面的列表看起来有点混乱。通常情况下你不需要改变你的日志依赖,Spring Boot默认情况下能很好的工作。
26.1 Log格式
Spring Boot默认的日志输出看起来如下:
1 | 2014-03-05 10:57:51.112 INFO 45469 --- [ main] org.apache.catalina.core.StandardEngine : Starting Servlet Engine: Apache Tomcat/7.0.52 |
下面的是输出项:
Date and Time — 精确到毫秒且容易排序。
Log级别 — ERROR,WARN,INFO,DEBUG或TRACE。
进程ID。
---
分隔符来区分真正的日志信息的开始。线程名称 — 用方括号包裹(在控制台输出中经常是缩减的)。
Logger名称 — 源类名(经常是简写)。
日志信息。
Logback没有FATAL级别(它映射到ERROR)。
26.2 控制台输出
默认的日志配置会将信息输出到控制台。默认情况下会输出ERROR
,WARN
和INFO
级别的信息。你也可以通过--debug
来启动你的应用,从而启用“debug”模式。
1 | $ java -jar myapp.jar --debug |
你也可以在
application.properties
指定debug=true
。
当启用调试模式时,配置选择的核心logger(嵌入式容器,Hibernate和Spring Boot)来输出更多的信息。启动调试模式不会将你的应用配置成输出所有DEBUG
级别的信息。
或者,你可以用--trace
标记(或在application.properties
中添加trace=true
)启动你的应用,从而启用“trace”模式。这将在选择的核心logger中(嵌入式容器,Hibernate模式生成和整个Spring文件夹)启用trace日志。
26.2.1 颜色编码输出
如果你的终端支持ANSI,颜色输出可以用来辅助阅读。你可以为spring.output.ansi.enabled
设置一个支持值来覆盖自动检测。
颜色编码用%clr
转换词来配置。最简单的形式是根据日志级别进行颜色输出,例如:
1 | %clr(%5p) |
日志级别与颜色的映射如下:
Level | Color |
---|---|
FATAL | Red |
ERROR | Red |
WARN | Yellow |
INFO | Green |
DEBUG | Green |
TRACE | Green |
或者,你可以通过在转换器中提供选项来指定应该试用的颜色或风格。例如,为了使文本显示黄色:
1 | %clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){yellow} |
支持下面的颜色和风格:
- blue
- cyan
- faint
- green
- magenta
- red
- yellow
26.3 文件输出
默认情况下,Spring Boot只能输出日志到控制台,不会写入日志文件。如果你想除了控制台之外还想写日志文件,你需要设置logging.file
或logging.path
属性(例如,在你的application.properties
)。
下表显示了logging.*
属性怎样在一起使用:
表 26.1. Logging属性
logging.file | logging.path | Example | Description |
---|---|---|---|
(none | (none) | 只输出到控制台 | |
指定文件 | (none) | my.log | 写入指定的日志文件。名字可以是一个绝对位置或相对于当前目录。 |
(none) | Specific directory | /var/log | 写spring.log 到一个指定的目录。名字可以是一个绝对位置或相对于当前目录。 |
当日志文件达到10M时日志文件将循环,至于控制台输出,默认情况下只输出ERROR
,WARN
和INFO
级别的信息。
日志系统在应用程序的生命周期早期进行初始化,同样地,通过
@PropertySource
注解加载的属性文件中将不会发现日志属性。
日志属性独立于真正的日志基础架构之外。因此,Spring Boot不管理特定的配置主键(例如Logback的
logback.configurationFile
)。
26.4 日志级别
Spring支持的所有日志系统都可以在Spring的Environment
中设置日志级别(例如在application.properties
设置),使用logging.level.*=LEVEL
进行设置,LEVEL
是TRACE,DEBUG,INFO,WARN,ERROR,FATAL,OFF中的一个。root
日志器可以用logging.level.root
来配置。例如在application.properties
中:
1 | logging.level.root=WARN |
默认情况下Spring Boot重新映射Thymeleaf的
INFO
信息,为了它们能在DEBUG
级别进行输出。这能帮助减少标准日志输出中的噪声。关于怎样在你自己的配置中使用重新映射的更多细节请看LevelRemappingAppender
。
26.5 定制日志配置
在类路径中通过包含恰当的库可以激活各种日志系统,在类路径的根目录中提供一个合适的配置文件可以对日志系统进行更进一步的定制,或者将配置文件放在Spring Environment
的logging.config
属性中指定的位置。
你可以使用系统属性org.springframework.boot.logging.LoggingSystem
来强制Spring Boot使用一个特定的日志系统。它的值应该是全限定类名的LoggingSystem
实现。你也可以通过使用值none
来完全禁用Spring Boot的日志配置。
由于日志是在
ApplicationContext
创建之前初始化,因此不可能从Spring@Configuration
文件中的@PropertySources
来控制日志。系统属性和传统的Spring Boot外部配置文件可以工作的很好。
根据你的日志系统,将会加载下面的文件:
Logging System | Customization |
---|---|
Logback | logback-spring.xml, logback-spring.groovy, logback.xml or logback.groovy |
Log4j2 | log4j2-spring.xml or log4j2.xml |
JDK (Java Util Logging) | logging.properties |
我们建议你尽可能的使用
-spring
变种来进行日志配置(例如,logback-spring.xml
而不是logback.xml
)。如果你在使用标准的配置路径,Spring不能完全控制日志的初始化。
在Java Java Util Logging中存在类加载问题,当从
executable jar
运行时会引起问题。我们建议你尽可能的避免它。
为了帮助定制一些其它属性,从Spring Environment
中转移到系统属性中:
Spring Environment | System Property | Comments |
---|---|---|
logging.exception-conversion-word | LOG_EXCEPTION_CONVERSION_WORD | 当日志出现异常时会用到这个转换词。 |
logging.file | LOG_FILE | 如果定义了,会在默认的日志配置中使用。 |
logging.path | LOG_PATH | 如果定义了,会在默认的日志配置中使用。 |
logging.pattern.console | CONSOLE_LOG_PATTERN | 用在控制台中的日志模式(stdout)。(只支持默认的Logback设置。) |
logging.pattern.file | FILE_LOG_PATTERN | 用在文件中的日志模式 (如果启用LOG_FILE )。(只支持默认的Logback设置。) |
logging.pattern.level | LOG_LEVEL_PATTERN | 这种模式用来实施日志级别(默认%5p )。 (只支持默认的Logback设置。) |
PID | PID | 当前的进程ID |
当转换配置文件时,所有的日志系统都支持查询系统属性。例如spring-boot.jar
的默认配置。
如果你在日志属性中想使用占位符,你应该试用Spring Boot的语法而不是底层框架的语法。尤其是,如果你在使用Logback,你应该使用
:
作为属性名和默认值之间的分隔符,而不是:-
。
你可以通过重写
LOG_LEVEL_PATTERN
(或Logback中的logging.pattern.level
)来添加MDC和其它的专门内容来日志行中。例如,你可以使用logging.pattern.level=user:%X{user} %5p
,默认的日志形式将包含MDC输入,如果它存在的话,例如:
1
2 2015-09-30 12:30:04.031 user:juergen INFO 22174 --- [ nio-8080-exec-0] demo.Controller
Handling authenticated request
26.6 Logback扩展
Spring Boot包含许多Logback的扩展,这有助于进行更高级的配置。你可以在你的logback-spring.xml
配置文件中使用这些扩展。
你不能在标准的
logback.xml
配置文件中使用扩展,因为它加载的太早了。你需要使用logback-spring.xml
或定义logging.config
属性。
26.6.1 特定profile的配置
<springProfile>
标签允许你自由的包含或排除基于激活的Spring profiles的配置的一部分。在<configuration>
元素的任何地方都支持Profile部分。使用name
属性来指定哪一个profile接受配置。多个profiles可以用一个逗号分隔的列表来指定。
1 | <springProfile name="staging"> |
26.6.2 Environment属性
<springProperty>
标签允许你在Logback使用从Spring Environment
获得的属性。如果你想在你的Logback配置中访问application.properties
文件中的属性,这是非常有用的。这个标签与Logback的标准<property>
标签的作用方式类似,但不是为你指定的source
属性(从Environment
中)指定一个直接的value
。如果你需要在某个地方而不是在local
作用域中存储属性,你可以使用scope
属性。如果你需要一个备用值以防属性没有在Environment
中设置,你可以使用defaultValue
属性。
1 | <springProperty scope="context" name="fluentHost" source="myapp.fluentd.host" |
RelaxedPropertyResolver
是用来访问Environment
属性。如果在破折号符号中指定了source
,则会尝试所有的不严格的变种(myPropertyName
,MY_PROPERTY_NAME
等)。