Spring Boot参考指南 Boot Reference Guide Zh
spring-boot-reference-guide-zh
spring-boot-reference-guide-zh
spring-boot-reference-guide-zh
spring-boot-reference-guide-zh
spring-boot-reference-guide-zh
User Manual: Pdf
Open the PDF directly: View PDF
.
Page Count: 714 [warning: Documents this large are best viewed by clicking the View PDF Link!]
- Introduction
- I. Spring Boot文档
- II. 开始
- III. 使用Spring Boot
- IV. Spring Boot特性
- V. Spring Boot执行器: Production-ready特性
- VII. Spring Boot CLI
- VIII. 构建工具插件
- IX. How-to指南
- 68. Spring Boot应用
- 70. 内嵌servlet容器
- 70.1 为应用添加Servlet,Filter或Listener
- 70.2 改变HTTP端口
- 70.3 使用随机未分配的HTTP端口
- 70.4 发现运行时的HTTP端口
- 70.5 配置SSL
- 70.6 配置访问日志
- 70.7 在前端代理服务器后使用
- 70.8 配置Tomcat
- 70.9 启用Tomcat的多连接器
- 70.10 使用Tomcat的LegacyCookieProcessor
- 70.11 使用Jetty替代Tomcat
- 70.12 配置Jetty
- 70.13 使用Undertow替代Tomcat
- 70.14 配置Undertow
- 70.15 启用Undertow的多监听器
- 70.16 使用Tomcat 7.x或8.0
- 70.17 使用Jetty9.2
- 70.18 使用Jetty 8
- 70.19 使用@ServerEndpoint创建WebSocket端点
- 71. Spring MVC
- 73. 日志
- 74. 数据访问
- 75. 数据库初始化
- 76. 批处理应用
- 77. 执行器
- 78. 安全
- 79. 热交换
- 80. 构建
- 81. 传统部署
- X.附录

1.1
1.2
1.2.1
1.2.2
1.2.3
1.2.4
1.2.5
1.2.6
1.2.7
1.3
1.3.1
1.3.2
1.3.2.1
1.3.3
1.3.3.1
1.3.3.1.1
1.3.3.1.2
1.3.3.2
1.3.3.2.1
1.3.3.2.2
1.3.3.2.3
1.3.3.2.4
1.3.3.2.5
1.3.3.2.6
1.3.3.3
1.3.3.4
1.3.3.5
目錄
Introduction
I.SpringBoot文档
1.关于本文档
2.获取帮助
3.第一步
4.使用SpringBoot
5.了解SpringBoot特性
6.迁移到生产环境
7.高级主题
II.开始
8.SpringBoot介绍
9.系统要求
9.1.Servlet容器
10.SpringBoot安装
10.1.为Java开发者准备的安装指南
10.1.1.Maven安装
10.1.2.Gradle安装
10.2.SpringBootCLI安装
10.2.1.手动安装
10.2.2.使用SDKMAN进行安装
10.2.3.使用OSXHomebrew进行安装
10.2.4.使用MacPorts进行安装
10.2.5.命令行实现
10.2.6.SpringCLI示例快速入门
10.3.从SpringBoot早期版本升级
11.开发你的第一个SpringBoot应用
11.1.创建POM
1

1.3.3.6
1.3.3.7
1.3.3.7.1
1.3.3.7.2
1.3.3.7.3
1.3.3.8
1.3.3.9
1.3.3.10
1.4
1.4.1
1.4.1.1
1.4.1.2
1.4.1.2.1
1.4.1.2.3
1.4.1.2.4
1.4.1.2.2
1.4.1.3
1.4.1.4
1.4.1.5
1.4.2
1.4.2.1
1.4.2.2
1.4.3
1.4.3.1
1.4.3.2
1.4.4
1.4.4.1
1.4.4.2
1.4.5
1.4.6
11.2.添加classpath依赖
11.3.编写代码
11.3.1.@RestController和@RequestMapping注解
11.3.2.@EnableAutoConfiguration注解
11.3.3.main方法
11.4.运行示例
11.5.创建一个可执行jar
12.接下来阅读什么
III.使用SpringBoot
13.构建系统
13.1.依赖管理
13.2.Maven
13.2.1.继承starterparent
13.2.2.在不使用parentPOM的情况下玩转SpringBoot
13.2.3.改变Java版本
13.2.4.使用SpringBootMaven插件
13.3.Gradle
13.4.Ant
13.5.Starters
14.组织你的代码
14.1.使用"default"包
14.2.放置应用的main类
15.配置类
15.1.导入其他配置类
15.2.导入XML配置
16.自动配置
16.1.逐步替换自动配置
16.2.禁用特定的自动配置
17.SpringBeans和依赖注入
18.使用@SpringBootApplication注解
2

1.4.7
1.4.7.1
1.4.7.2
1.4.7.3
1.4.7.4
1.4.7.5
1.4.8
1.4.8.1
1.4.8.2
1.4.8.2.1
1.4.8.2.2
1.4.8.2.3
1.4.8.2.4
1.4.8.2.5
1.4.8.2.6
1.4.8.3
1.4.8.4
1.4.8.5
1.4.8.5.1
1.4.8.5.2
1.4.8.5.3
1.4.8.5.3.1
1.4.8.5.3.2
1.5
1.5.1
1.5.1.1
1.5.1.2
1.5.1.3
1.5.1.4
1.5.1.5
19.运行应用程序
19.1.从IDE中运行
19.2.作为一个打包后的应用运行
19.3.使用Maven插件运行
19.4.使用Gradle插件运行
19.5.热交换
20.开发者工具
20.1默认属性
20.2自动重启
20.2.1排除资源
20.2.2查看其他路径
20.2.3禁用重启
20.2.4使用触发器文件
20.2.5自定义restart类加载器
20.2.6已知限制
20.3LiveReload
20.4全局设置
20.5远程应用
20.5.1运行远程客户端应用
20.5.2远程更新
20.5.3远程调试通道
21.打包用于生产的应用
22.接下来阅读什么
IV.SpringBoot特性
23.SpringApplication
23.1启动失败
23.2.自定义Banner
23.3.自定义SpringApplication
23.4.流式构建API
23.5.Application事件和监听器
3

1.5.1.6
1.5.1.7
1.5.1.8
1.5.1.9
1.5.2
1.5.2.1
1.5.2.2
1.5.2.3
1.5.2.4
1.5.2.5
1.5.2.6
1.5.2.6.1
1.5.2.6.2
1.5.2.6.3
1.5.2.6.4
1.5.2.6.5
1.5.2.7
1.5.2.7.1
1.5.2.7.2
1.5.2.7.3
1.5.2.7.4
1.5.2.7.5
1.5.3
1.5.3.1
1.5.3.2
1.5.3.3
1.5.4
1.5.4.1
1.5.4.2
1.5.4.2.1
23.6.Web环境
23.7访问应用参数
23.8.使用ApplicationRunner或CommandLineRunner
23.9Application退出
24.外化配置
24.1.配置随机值
24.2.访问命令行属性
24.3.Application属性文件
24.4.Profile-specific属性
24.5.属性占位符
24.6.使用YAML代替Properties
24.6.1.加载YAML
24.6.2.在Spring环境中使用YAML暴露属性
24.6.3.Multi-profileYAML文档
24.6.4.YAML缺点
24.6.5合并YAML列表
24.7.类型安全的配置属性
24.7.1.第三方配置
24.7.2.Relaxed绑定
24.7.3属性转换
24.7.4.@ConfigurationProperties校验
24.7.5@ConfigurationPropertiesvs@Value
25.Profiles
25.1.添加激活的profiles
25.2.以编程方式设置profiles
25.3.Profile-specific配置文件
26.日志
26.1.日志格式
26.2.控制台输出
26.2.1Color-coded输出
4

1.5.4.3
1.5.4.4
1.5.4.5
1.5.4.6
1.5.4.6.1
1.5.4.6.2
1.5.5
1.5.5.1
1.5.5.1.1
1.5.5.1.2
1.5.5.1.3
1.5.5.1.4
1.5.5.1.5
1.5.5.1.6
1.5.5.1.7
1.5.5.1.8
1.5.5.1.9
1.5.5.1.10
1.5.5.2
1.5.5.3
1.5.5.3.1
1.5.5.3.2
1.5.5.3.3
1.5.5.3.4
1.5.5.3.5
1.5.6
1.5.6.1
1.5.6.1.1
1.5.6.1.2
1.5.6.2
26.3.文件输出
26.4.日志级别
26.5.自定义日志配置
26.6Logback扩展
26.6.1Profile-specific配置
26.6.2Environment属性
27.开发Web应用
27.1.SpringWebMVC框架
27.1.1.SpringMVC自动配置
27.1.2.HttpMessageConverters
27.1.3自定义JSON序列化器和反序列化器
27.1.4MessageCodesResolver
27.1.5静态内容
27.1.6ConfigurableWebBindingInitializer
27.1.7模板引擎
27.1.8错误处理
27.1.9SpringHATEOAS
27.1.10CORS支持
27.2JAX-RS和Jersey
27.3内嵌servlet容器支持
27.3.1Servlets,Filters和listeners
27.3.2Servlet上下文初始化
27.3.3EmbeddedWebApplicationContext
27.3.4自定义内嵌servlet容器
27.3.5JSP的限制
28.安全
28.1OAuth2
28.1.1授权服务器
28.1.2资源服务器
28.2UserInfo中的Token类型
5

1.5.6.3
1.5.6.3.1
1.5.6.3.2
1.5.6.4
1.5.7
1.5.7.1
1.5.7.1.1
1.5.7.1.2
1.5.7.1.3
1.5.7.2
1.5.7.3
1.5.7.3.1
1.5.7.3.2
1.5.7.3.3
1.5.7.4
1.5.7.4.1
1.5.7.4.2
1.5.7.5
1.5.7.5.1
1.5.7.5.2
1.5.7.5.3
1.5.8
1.5.8.1
1.5.8.1.1
1.5.8.2
1.5.8.2.1
1.5.8.2.2
1.5.8.2.3
1.5.8.2.4
1.5.8.3
28.3自定义UserInfoRestTemplate
28.3.1客户端
28.3.2单点登陆
28.4Actuator安全
29.使用SQL数据库
29.1.配置DataSource
29.1.1.对内嵌数据库的支持
29.1.2.连接生产环境数据库
29.1.3.连接JNDI数据库
29.2.使用JdbcTemplate
29.3.JPA和SpringData
29.3.1.实体类
29.3.2.SpringDataJPA仓库
29.3.3.创建和删除JPA数据库
29.4使用H2的web控制台
29.4.1改变H2控制台路径
29.4.2保护H2控制台
29.5使用jOOQ
29.5.1代码生成
29.5.2使用DSLContext
29.5.3自定义jOOQ
30.使用NoSQL技术
30.1.Redis
30.1.1.连接Redis
30.2.MongoDB
30.2.1.连接MongoDB数据库
30.2.2.MongoDBTemplate
30.2.3.SpringDataMongoDB仓库
30.2.4内嵌的Mongo
30.3Neo4j
6

1.5.8.3.1
1.5.8.3.2
1.5.8.3.3
1.5.8.3.4
1.5.8.3.5
1.5.8.4
1.5.8.5
1.5.8.5.1
1.5.8.5.2
1.5.8.6
1.5.8.6.1
1.5.8.6.2
1.5.8.6.3
1.5.8.7
1.5.8.7.1
1.5.8.7.2
1.5.8.8
1.5.8.8.1
1.5.8.8.2
1.5.9
1.5.9.1
1.5.9.1.1
1.5.9.1.2
1.5.9.1.3
1.5.9.1.4
1.5.9.1.5
1.5.9.1.6
1.5.9.1.7
1.5.9.1.8
1.5.9.1.9
30.3.1连接Neo4j数据库
30.3.2使用内嵌模式
30.3.3Neo4jSession
30.3.4SpringDataNeo4j仓库
30.3.5仓库示例
30.4Gemfire
30.5Solr
30.5.1连接Solr
30.5.2SpringDataSolr仓库
30.6Elasticsearch
30.6.1使用Jest连接Elasticsearch
30.6.2使用SpringData连接Elasticsearch
30.6.3SpringDataElasticseach仓库
30.7Cassandra
30.7.1连接Cassandra
30.7.2SpringDataCassandra仓库
30.8Couchbase
30.8.1连接Couchbase
30.8.2SpringDataCouchbase仓库
31.缓存
31.1支持的缓存提供商
31.1.1Generic
31.1.2JCache(JSR-107)
31.1.3EhCache2.x
31.1.4Hazelcast
31.1.5Infinispan
31.1.6Couchbase
31.1.7Redis
31.1.8Caffeine
31.1.9Guava
7

1.5.9.1.10
1.5.9.1.11
1.5.10
1.5.10.1
1.5.10.1.1
1.5.10.1.2
1.5.10.1.3
1.5.10.1.4
1.5.10.1.5
1.5.10.1.6
1.5.10.2
1.5.10.2.1
1.5.10.2.2
1.5.10.2.3
1.5.10.3
1.5.10.3.1
1.5.11
1.5.12
1.5.12.1
1.5.12.2
1.5.12.3
1.5.12.4
1.5.12.5
1.5.12.6
1.5.13
1.5.14
1.5.15
1.5.16
1.5.17
1.5.17.1
31.1.10Simple
31.1.11None
32.消息
32.1.JMS
32.1.1ActiveQ支持
32.1.2Artemis支持
32.1.3HornetQ支持
32.1.4使用JNDIConnectionFactory
32.1.5发送消息
32.1.6接收消息
32.2AMQP
32.2.1RabbitMQ支持
32.2.2发送消息
32.2.3接收消息
33.调用REST服务
33.1自定义RestTemplate
34.发送邮件
35.使用JTA处理分布式事务
35.1使用Atomikos事务管理器
35.2使用Bitronix事务管理器
35.3使用Narayana事务管理器
35.4使用J2EE管理的事务管理器
35.5混合XA和non-XA的JMS连接
35.6支持可替代的内嵌事务管理器
36.Hazelcast
37.Spring集成
38.SpringSession
39.基于JMX的监控和管理
40.测试
40.1测试作用域依赖
8

1.5.17.2
1.5.17.3
1.5.17.3.1
1.5.17.3.2
1.5.17.3.3
1.5.17.3.4
1.5.17.3.5
1.5.17.3.6
1.5.17.3.7
1.5.17.3.8
1.5.17.3.9
1.5.17.3.10
1.5.17.3.11
1.5.17.4
1.5.17.4.1
1.5.17.4.2
1.5.17.4.3
1.5.17.4.4
1.5.18
1.5.19
1.5.20
1.5.20.1
1.5.20.2
1.5.20.3
1.5.20.3.1
1.5.20.3.2
1.5.20.3.3
1.5.20.3.4
1.5.20.3.5
1.5.20.3.6
40.2测试Spring应用
40.3测试SpringBoot应用
40.3.1发现测试配置
40.3.2排除测试配置
40.3.3使用随机端口
40.3.4模拟和监视beans
40.3.5自动配置测试
40.3.6自动配置的JSON测试
40.3.7自动配置的SpringMVC测试
40.3.8自动配置的DataJPA测试
40.3.9自动配置的REST客户端
40.3.10自动配置的SpringRESTDocs测试
40.3.11使用Spock测试SpringBoot应用
40.4测试工具类
40.4.1ConfigFileApplicationContextInitializer
40.4.2EnvironmentTestUtils
40.4.3OutputCapture
40.4.4TestRestTemplate
41.WebSockets
42.WebServices
43.创建自己的auto-configuration
43.1理解自动配置的beans
43.2定位自动配置候选者
43.3条件注解
43.3.1Class条件
43.3.2Bean条件
43.3.3Property条件
43.3.4Resource条件
43.3.5WebApplication条件
43.3.6SpEL表达式条件
9

1.5.20.4
1.5.20.4.1
1.5.20.4.2
1.5.20.4.3
1.5.21
1.6
1.6.1
1.6.2
1.6.2.1
1.6.2.2
1.6.2.3
1.6.2.4
1.6.2.5
1.6.2.6
1.6.2.6.1
1.6.2.6.2
1.6.2.7
1.6.2.7.1
1.6.2.7.2
1.6.2.7.3
1.6.2.7.4
1.6.2.7.5
1.6.3
1.6.3.1
1.6.3.2
1.6.3.3
1.6.3.4
1.6.3.5
1.6.3.6
1.6.3.7
43.4创建自己的starter
43.4.1命名
43.4.2自动配置模块
43.4.3Starter模块
44.接下来阅读什么
V.SpringBoot执行器:Production-ready特性
45.开启production-ready特性
46.端点
46.1自定义端点
46.2执行器MVC端点的超媒体支持
46.3CORS支持
46.4添加自定义端点
46.5健康信息
46.6安全与HealthIndicators
46.6.1自动配置的HealthIndicators
46.6.2编写自定义HealthIndicators
46.7应用信息
46.7.1自动配置的InfoContributors
46.7.2自定义应用info信息
46.7.3Git提交信息
46.7.4构建信息
46.7.5编写自定义的InfoContributors
47.基于HTTP的监控和管理
47.1保护敏感端点
47.2自定义管理端点路径
47.3自定义管理服务器端口
47.4配置管理相关的SSL
47.5自定义管理服务器地址
47.6禁用HTTP端点
47.7HTTPhealth端点访问限制
10

1.6.4
1.6.4.1
1.6.4.2
1.6.4.3
1.6.4.3.1
1.6.4.3.2
1.6.5
1.6.5.1
1.6.5.1.1
1.6.5.2
1.6.5.2.1
1.6.5.2.2
1.6.6
1.6.6.1
1.6.6.2
1.6.6.3
1.6.6.4
1.6.6.5
1.6.6.6
1.6.6.7
1.6.6.8
1.6.6.8.1
1.6.6.8.2
1.6.6.8.3
1.6.6.8.4
1.6.6.9
1.6.6.10
1.6.6.11
1.6.7
1.6.8
48.基于JMX的监控和管理
48.1自定义MBean名称
48.2禁用JMX端点
48.3使用Jolokia通过HTTP实现JMX远程管理
48.3.1自定义Jolokia
48.3.2禁用Jolokia
49.使用远程shell进行监控和管理
49.1连接远程shell
49.1.1远程shell证书
49.2扩展远程shell
49.2.1远程shell命令
49.2.2远程shell插件
50.度量指标
50.1系统指标
50.2数据源指标
50.3缓存指标
50.4Tomcatsession指标
50.5记录自己的指标
50.6添加自己的公共指标
50.7使用Java8的特性
50.8指标写入,导出和聚合
50.8.1示例:导出到Redis
50.8.2示例:导出到OpenTSDB
50.8.3示例:导出到Statsd
50.8.4示例:导出到JMX
50.9聚合多个来源的指标
50.10Dropwizard指标
50.11消息渠道集成
51.审计
52.追踪
11

1.6.8.1
1.6.9
1.6.9.1
1.6.9.2
1.6.10
1.7
1.7.1
1.7.1.1
1.7.1.1.1
1.7.1.2
1.7.1.3
1.7.1.4
1.7.1.5
1.7.2
1.7.2.1
1.7.2.1.1
1.7.2.1.2
1.7.2.1.3
1.7.2.2
1.7.3
1.8
1.8.1
1.8.2
1.8.2.1
1.8.2.1.1
1.8.2.1.2
1.8.2.1.3
1.8.2.1.4
1.8.2.1.5
1.8.2.2
52.1自定义追踪
53.进程监控
53.1扩展配置
53.2以编程方式
54.接下来阅读什么
VI.部署到云端
55.部署到云端
55.1CloudFoundry
55.1.1绑定服务
55.2Heroku
55.3Openshift
55.4Boxfuse和AmazonWebServices
55.5GoogleAppEngine
56.安装SpringBoot应用
56.1Unix/Linux服务
56.1.1安装为init.d服务(SystemV)
56.1.2安装为Systemd服务
56.1.3自定义启动脚本
56.2MicrosoftWindows服务
57.接下来阅读什么
VII.SpringBootCLI
58.安装CLI
59.使用CLI
59.1使用CLI运行应用
59.1.1推断"grab"依赖
59.1.2推断"grab"坐标
59.1.3默认import语句
59.1.4自动创建main方法
59.1.5自定义依赖管理
59.2测试你的代码
12

1.8.2.3
1.8.2.4
1.8.2.5
1.8.2.6
1.8.2.7
1.8.3
1.8.4
1.8.5
1.9
1.9.1
1.9.1.1
1.9.1.2
1.9.2
1.9.2.1
1.9.2.2
1.9.2.3
1.9.2.4
1.9.2.5
1.9.2.6
1.9.2.7
1.9.2.7.1
1.9.2.7.2
1.9.2.8
1.9.2.9
1.9.2.9.2
1.9.2.9.1
1.9.2.10
1.9.2.10.1
1.9.2.10.1.1
1.9.2.10.1.2
59.3多源文件应用
59.4应用打包
59.5初始化新工程
59.6使用内嵌shell
59.7为CLI添加扩展
60.使用GroovybeansDSL开发应用
61.使用settings.xml配置CLI
62.接下来阅读什么
VIII.构建工具插件
63.SpringBootMaven插件
63.1包含该插件
63.2打包可执行jar和war文件
64.SpringBootGradle插件
64.1包含该插件
64.2Gradle依赖管理
64.3打包可执行jar和war文件
64.4就地(in-place)运行项目
64.5SpringBoot插件配置
64.6Repackage配置
64.7使用Gradle自定义配置进行Repackage
64.7.1配置选项
64.7.2可用的layouts
64.8理解Gradle插件是如何工作的
64.9使用Gradle将artifacts发布到Maven仓库
64.9.1自定义Gradle,用于产生一个继承依赖管理的pom
64.9.2自定义Gradle,用于产生一个导入依赖管理的
pom
65.SpringBootAntLib模块
65.1.SpringBootAnt任务
65.1.1.spring-boot:exejar
65.1.2.示例
13

1.9.2.10.2
1.9.2.10.2.1
1.9.3
1.9.3.1
1.9.3.2
1.9.3.3
1.9.3.4
1.9.4
1.10
1.10.1
1.10.1.1
1.10.1.2
1.10.1.3
1.10.1.4
1.10.1.5
1.10.1.5.1
1.10.1.6
1.10.1.6.1
1.10.1.6.2
1.10.1.7
1.10.1.8
1.10.1.9
1.10.1.10
1.10.1.11
1.10.1.12
1.10.1.13
1.10.2
1.10.2.1
1.10.2.1.1
1.10.2.1.2
65.2.spring-boot:findmainclass
65.2.1.示例
66.对其他构建系统的支持
66.1.重新打包存档
66.2.内嵌库
66.3.查找main类
66.4.repackage实现示例
67.接下来阅读什么
IX.How-to指南
68.SpringBoot应用
68.1创建自己的FailureAnalyzer
68.2解决自动配置问题
68.3启动前自定义Environment或ApplicationContext
68.4构建ApplicationContext层次结构
68.5创建no-web应用
69.属性&配置
69.1.运行时暴露属性
69.1.1.使用Maven自动暴露属性
69.1.2.使用Gradle自动暴露属性
69.2.外部化SpringApplication配置
69.3改变应用程序外部配置文件的位置
69.4使用'short'命令行参数
69.5使用YAML配置外部属性
69.6设置生效的Springprofiles
69.7根据环境改变配置
69.8发现外部属性的内置选项
70.内嵌servlet容器
70.1为应用添加Servlet,Filter或Listener
70.1.1使用Springbean添加Servlet,Filter或Listener
70.1.2使用classpath扫描添加Servlets,Filters和Listeners
14

1.10.2.2
1.10.2.3
1.10.2.4
1.10.2.5
1.10.2.6
1.10.2.7
1.10.2.7.1
1.10.2.8
1.10.2.9
1.10.2.10
1.10.2.11
1.10.2.12
1.10.2.13
1.10.2.14
1.10.2.15
1.10.2.16
1.10.2.16.1
1.10.2.16.2
1.10.2.17
1.10.2.17.1
1.10.2.17.2
1.10.2.18
1.10.2.18.1
1.10.2.18.2
1.10.2.19
1.10.3
1.10.3.1
1.10.3.2
1.10.3.3
1.10.3.4
70.2改变HTTP端口
70.3使用随机未分配的HTTP端口
70.4发现运行时的HTTP端口
70.5配置SSL
70.6配置访问日志
70.7在前端代理服务器后使用
70.7.1自定义Tomcat代理配置
70.8配置Tomcat
70.9启用Tomcat的多连接器
70.10使用Tomcat的LegacyCookieProcessor
70.11使用Jetty替代Tomcat
70.12配置Jetty
70.13使用Undertow替代Tomcat
70.14配置Undertow
70.15启用Undertow的多监听器
70.16使用Tomcat7.x或8.0
70.16.1通过Maven使用Tomcat7.x或8.0
70.16.2通过Gradle使用Tomcat7.x或8.0
70.17使用Jetty9.2
70.17.1通过Maven使用Jetty9.2
70.17.2通过Gradle使用Jetty9.2
70.18使用Jetty8
70.18.1通过Maven使用Jetty8
70.18.2通过Gradle使用Jetty8
70.19使用@ServerEndpoint创建WebSocket端点
71.SpringMVC
71.1编写JSONREST服务
71.2编写XMLREST服务
71.3自定义JacksonObjectMapper
71.4自定义@ResponseBody渲染
15

1.10.3.5
1.10.3.6
1.10.3.7
1.10.3.8
1.10.3.9
1.10.3.10
1.10.4
1.10.4.1
1.10.4.1.1
1.10.4.2
1.10.4.2.1
1.10.5
1.10.5.1
1.10.5.2
1.10.5.3
1.10.5.4
1.10.5.5
1.10.5.6
1.10.5.7
1.10.5.8
1.10.5.9
1.10.5.10
1.10.5.11
1.10.6
1.10.6.1
1.10.6.2
1.10.6.3
1.10.6.4
1.10.6.5
1.10.6.5.1
71.5处理Multipart文件上传
71.6关闭SpringMVCDispatcherServlet
71.7关闭默认的MVC配置
71.8自定义ViewResolvers
71.9Velocity
71.10使用Thymeleaf3
73.日志
73.1配置Logback
73.1.1配置logback只输出到文件
73.2配置Log4j
73.2.1使用YAML或JSON配置Log4j2
74.数据访问
74.1配置数据源
74.2配置两个数据源
74.3使用SpringData仓库
74.4从Spring配置分离@Entity定义
74.5配置JPA属性
74.6使用自定义EntityManagerFactory
74.7使用两个EntityManagers
74.8使用普通的persistence.xml
74.9使用SpringDataJPA和Mongo仓库
74.10将SpringData仓库暴露为REST端点
74.11配置JPA使用的组件
75.数据库初始化
75.1使用JPA初始化数据库
75.2使用Hibernate初始化数据库
75.3使用SpringJDBC初始化数据库
75.4初始化SpringBatch数据库
75.5使用高级数据迁移工具
75.5.1启动时执行Flyway数据库迁移
16

1.10.6.5.2
1.10.7
1.10.7.1
1.10.8
1.10.8.1
1.10.8.2
1.10.8.3
1.10.9
1.10.9.1
1.10.9.2
1.10.9.3
1.10.10
1.10.10.1
1.10.10.2
1.10.10.2.1
1.10.10.2.2
1.10.10.2.3
1.10.10.2.4
1.10.10.3
1.10.10.4
1.10.10.4.1
1.10.11
1.10.11.1
1.10.11.2
1.10.11.3
1.10.11.4
1.10.11.5
1.10.11.6
1.10.11.7
1.10.10.4.2
75.5.2启动时执行Liquibase数据库迁移
76.批处理应用
76.1在启动时执行SpringBatch作业
77.执行器
77.1改变HTTP端口或执行器端点的地址
77.2自定义WhiteLabel错误页面
77.3Actuator和Jersey
78.安全
78.1关闭SpringBoot安全配置
78.2改变AuthenticationManager并添加用户账号
78.3当前端使用代理服务器时启用HTTPS
79.热交换
79.1重新加载静态内容
79.2.在不重启容器的情况下重新加载模板
79.2.1Thymeleaf模板
79.2.2FreeMarker模板
79.2.3Groovy模板
79.2.4Velocity模板
79.3应用快速重启
79.4在不重启容器的情况下重新加载Java类
79.4.1使用Maven配置SpringLoaded
79.4.2使用Gradle和IntelliJIDEA配置SpringLoaded
80.构建
80.1生成构建信息
80.2生成Git信息
80.3自定义依赖版本
80.4使用Maven创建可执行JAR
80.5将SpringBoot应用作为依赖
80.6在可执行jar运行时提取特定的版本
80.7使用排除创建不可执行的JAR
17

1.10.11.8
1.10.11.9
1.10.11.10
1.10.11.11
1.10.11.11.1
1.10.11.11.2
1.10.11.11.3
1.10.12
1.10.12.1
1.10.12.2
1.10.12.3
1.10.12.4
1.10.12.5
1.11
1.11.1
1.11.2
1.11.2.1
1.11.2.1.1
1.11.2.1.2
1.11.2.1.3
1.11.2.2
1.11.2.2.1
1.11.2.2.2
1.11.3
1.11.3.1
1.11.3.2
1.11.4
1.11.4.1
1.11.4.1.1
1.11.4.1.2
80.8远程调试使用Maven启动的SpringBoot项目
80.9远程调试使用Gradle启动的SpringBoot项目
80.10使用Ant构建可执行存档
80.11如何使用Java6
80.11.1内嵌Servlet容器兼容性
80.11.2Jackson
80.11.3JTAAPI兼容性
81.传统部署
81.1创建可部署的war文件
81.2为老的servlet容器创建可部署的war文件
81.3将现有的应用转换为SpringBoot
81.4部署WAR到Weblogic
81.5部署WAR到老的(Servlet2.5)容器
X.附录
附录A.常见应用属性
附录B.配置元数据
附录B.1.元数据格式
附录B.1.1.Group属性
附录B.1.2.Property属性
附录B.1.3.可重复的元数据节点
附录B.2.使用注解处理器产生自己的元数据
附录B.2.1.内嵌属性
附录B.2.2.添加其他的元数据
附录C.自动配置类
附录C.1.来自spring-boot-autoconfigure模块
附录C.2.来自spring-boot-actuator模块
附录D.可执行jar格式
附录D.1.内嵌JARs
附录D.1.1.可执行jar文件结构
附录D.1.2.可执行war文件结构
18

1.11.4.2
1.11.4.2.1
1.11.4.3
1.11.4.3.1
1.11.4.3.2
1.11.4.4
1.11.4.5
1.11.4.5.1
1.11.4.5.2
1.11.4.6
1.11.5
附录D.2.SpringBoot的"JarFile"类
附录D.2.1.对标准Java"JarFile"的兼容性
附录D.3.启动可执行jars
附录D.3.1Launchermanifest
附录D.3.2.暴露的存档
附录D.4.PropertiesLauncher特性
附录D.5.可执行jar的限制
附录D.5.1.Zip实体压缩
附录D.5.2.系统ClassLoader
附录D.6.可替代的单一jar解决方案
附录E.依赖版本
19

Spring-Boot-Reference-Guide
SpringBootReferenceGuide中文翻译-《SpringBoot参考指南》
说明:本文档翻译的版本:1.4.1.RELEASE。
如感兴趣,可以star或fork该仓库!
Github:https://github.com/qibaoguang/
GitBook:SpringBoot参考指南
整合示例:程序猿DD-SpringBoot教程
Email:qibaoguang@gmail.com
从这里开始
交流群:
SpringForAll社区:470962790
springboot最佳实践2(已满):460560346
springboot最佳实践(已满):445015546
注1.3版本查看本仓库的release。
Introduction
20

SpringBoot文档
本节对SpringBoot参考文档做了一个简单概述。你可以参考本节,从头到尾依次阅
读该文档,也可以跳过不感兴趣的章节。
I.SpringBoot文档
21

2.获取帮助
使用SpringBoot遇到麻烦,我们很乐意帮忙!
尝试How-to’s-它们为多数常见问题提供解决方案。
学习Spring基础知识-SpringBoot是在很多其他Spring项目上构建的,查
看spring.io站点可以获取丰富的参考文档。如果你刚开始使用Spring,可以尝
试这些指导中的一个。
提问题-我们时刻监控着stackoverflow.com上标记为spring-boot的问题。
在github.com/spring-projects/spring-boot/issues上报告SpringBoot的bug。
注:SpringBoot的一切都是开源的,包括文档!如果你发现文档有问题,或只是想
提高它们的质量,请参与进来!
2.获取帮助
23

3.第一步
如果你想对SpringBoot或Spring有个整体认识,可以从这里开始!
从零开始:概述|要求|安装
教程:第一部分|第二部分
运行示例:第一部分|第二部分
3.第一步
24

4.使用SpringBoot
准备好使用SpringBoot了?我们已经为你铺好道路.
构建系统:Maven|Gradle|Ant|Starters
最佳实践:代码结构|@Configuration|@EnableAutoConfiguration|Beans
和依赖注入
运行代码:IDE|Packaged|Maven|Gradle
应用打包:产品级jars
SpringBoot命令行:使用CLI
4.使用SpringBoot
25

5.了解SpringBoot特性
想要了解更多SpringBoot核心特性的详情?这就是为你准备的!
核心特性:SpringApplication|外部化配置|Profiles|日志
Web应用:MVC|内嵌容器
使用数据:SQL|NO-SQL
消息:概述|JMS
测试:概述|Boot应用|工具
扩展:Auto-configuration|@Conditions
5.了解SpringBoot特性
26

6.迁移到生产环境
当你准备将SpringBoot应用发布到生产环境时,我们提供了一些你可能喜欢的技
巧!
管理端点:概述|自定义
连接选项:HTTP|JMX|SSH
监控:指标|审计|追踪|进程
6.迁移到生产环境
27

入门指南
如果你想从大体上了解SpringBoot或Spring,本章节正是你所需要的!本节中,我
们会回答基本的"what?","how?"和"why?"等问题,并通过一些安装指南简单介绍
下SpringBoot。然后我们会构建第一个SpringBoot应用,并讨论一些需要遵循的
核心原则。
II.开始
29

8.SpringBoot介绍
SpringBoot简化了基于Spring的应用开发,你只需要"run"就能创建一个独立的,产
品级别的Spring应用。我们为Spring平台及第三方库提供开箱即用的设置,这样你
就可以有条不紊地开始。多数SpringBoot应用只需要很少的Spring配置。
你可以使用SpringBoot创建Java应用,并使用 java-jar启动它或采用传统的
war部署方式。我们也提供了一个运行"spring脚本"的命令行工具。
我们主要的目标是:
为所有Spring开发提供一个从根本上更快,且随处可得的入门体验。
开箱即用,但通过不采用默认设置可以快速摆脱这种方式。
提供一系列大型项目常用的非功能性特征,比如:内嵌服务器,安全,指标,
健康检测,外部化配置。
绝对没有代码生成,也不需要XML配置。
8.SpringBoot介绍
30

9.1.Servlet容器
下列内嵌容器支持开箱即用(outofthebox):
名称 Servlet版本 Java版本
Tomcat8 3.1 Java7+
Tomcat7 3.0 Java6+
Jetty9.3 3.1 Java8+
Jetty9.2 3.1 Java7+
Jetty8 3.0 Java6+
Undertow1.3 3.1 Java7+
你也可以将SpringBoot应用部署到任何兼容Servlet3.0+的容器。
9.1.Servlet容器
32

10.1.为Java开发者准备的安装指南
对于java开发者来说,使用SpringBoot就跟使用其他Java库一样,只需要在你的
classpath下引入适当的 spring-boot-*.jar文件。SpringBoot不需要集成任何
特殊的工具,所以你可以使用任何IDE或文本编辑器;同时,SpringBoot应用也没
有什么特殊之处,你可以像对待其他Java程序那样运行,调试它。
尽管可以拷贝SpringBootjars,但我们还是建议你使用支持依赖管理的构建工具,
比如Maven或Gradle。
10.1.为Java开发者准备的安装指南
34

10.1.1.Maven安装
SpringBoot兼容ApacheMaven3.2或更高版本。如果本地没有安装Maven,你可
以参考maven.apache.org上的指南。
注:在很多操作系统上,可以通过包管理器来安装Maven。OSXHomebrew用户可
以尝试 brewinstallmaven,Ubuntu用户可以运行 sudoapt-getinstall
maven。
SpringBoot依赖使用的groupId为org.springframework.boot。通常,你的
MavenPOM文件会继承 spring-boot-starter-parent工程,并声明一个或多
个“StarterPOMs”依赖。此外,SpringBoot提供了一个可选的Maven插件,用于创
建可执行jars。
下面是一个典型的pom.xml文件:
<?xmlversion="1.0"encoding="UTF-8"?>
<projectxmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="ht
tp://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0http:/
/maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>myproject</artifactId>
<version>0.0.1-SNAPSHOT</version>
<!--InheritdefaultsfromSpringBoot-->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.4.0.BUILD-SNAPSHOT</version>
</parent>
<!--Addtypicaldependenciesforawebapplication-->
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
10.1.为Java开发者准备的安装指南
35

</dependency>
</dependencies>
<!--Packageasanexecutablejar-->
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
<!--AddSpringrepositories-->
<!--(youdon'tneedthisifyouareusinga.RELEASEversio
n)-->
<repositories>
<repository>
<id>spring-snapshots</id>
<url>http://repo.spring.io/snapshot</url>
<snapshots><enabled>true</enabled></snapshots>
</repository>
<repository>
<id>spring-milestones</id>
<url>http://repo.spring.io/milestone</url>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>spring-snapshots</id>
<url>http://repo.spring.io/snapshot</url>
</pluginRepository>
<pluginRepository>
<id>spring-milestones</id>
<url>http://repo.spring.io/milestone</url>
</pluginRepository>
</pluginRepositories>
</project>
10.1.为Java开发者准备的安装指南
36

注: spring-boot-starter-parent是使用SpringBoot的一种不错的方式,但它
并不总是最合适的。有时你可能需要继承一个不同的父POM,或只是不喜欢我们
的默认配置,那你可以使用import作用域这种替代方案,具体查看Section13.2.2,
“UsingSpringBootwithouttheparentPOM”。
10.1.为Java开发者准备的安装指南
37

10.1.2.Gradle安装
SpringBoot兼容Gradle1.12或更高版本。如果本地没有安装Gradle,你可以参
考www.gradle.org上的指南。
SpringBoot的依赖可通过groupId org.springframework.boot来声明。通常,
你的项目将声明一个或多个“StarterPOMs”依赖。SpringBoot提供了一个很有用的
Gradle插件,可以用来简化依赖声明,创建可执行jars。
注:当你需要构建项目时,GradleWrapper提供一种给力的获取Gradle的方式。它
是一小段脚本和库,跟你的代码一块提交,用于启动构建进程,具体参考Gradle
Wrapper。
下面是一个典型的 build.gradle文件:
10.1.为Java开发者准备的安装指南
38

buildscript{
repositories{
jcenter()
maven{url"http://repo.spring.io/snapshot"}
maven{url"http://repo.spring.io/milestone"}
}
dependencies{
classpath("org.springframework.boot:spring-boot-gradle-p
lugin:1.4.0.BUILD-SNAPSHOT")
}
}
applyplugin:'java'
applyplugin:'spring-boot'
jar{
baseName='myproject'
version='0.0.1-SNAPSHOT'
}
repositories{
jcenter()
maven{url"http://repo.spring.io/snapshot"}
maven{url"http://repo.spring.io/milestone"}
}
dependencies{
compile("org.springframework.boot:spring-boot-starter-web")
testCompile("org.springframework.boot:spring-boot-starter-te
st")
}
10.1.为Java开发者准备的安装指南
39

10.2.1.手动安装
SpringCLI分发包可以从Spring软件仓库下载:
1. spring-boot-cli-1.4.0.BUILD-SNAPSHOT-bin.zip
2. spring-boot-cli-1.4.0.BUILD-SNAPSHOT-bin.tar.gz
不稳定的snapshot分发包也可以获取到。
下载完成后,解压分发包,根据存档里的INSTALL.txt操作指南进行安装。总的来
说,在 .zip文件的 bin/目录下会有一个spring脚本(Windows下
是spring.bat),或使用 java-jar运行 lib/目录下的 .jar文件(该脚
本会帮你确保classpath被正确设置)。
10.2.SpringBootCLI安装
41

10.2.2.使用SDKMAN安装
SDKMAN(软件开发包管理器)可以对各种各样的二进制SDK包进行版本管理,包
括Groovy和SpringBootCLI。可以从sdkman.io下载SDKMAN,并使用以下命令安
装SpringBoot:
$sdkinstallspringboot
$spring--version
SpringBootv1.4.0.BUILD-SNAPSHOT
如果你正在为CLI开发新的特性,并想轻松获取刚构建的版本,可以使用以下命
令:
$sdkinstallspringbootdev/path/to/spring-boot/spring-boot-cl
i/target/spring-boot-cli-1.4.0.BUILD-SNAPSHOT-bin/spring-1.4.0.B
UILD-SNAPSHOT/
$sdkdefaultspringbootdev
$spring--version
SpringCLIv1.4.0.BUILD-SNAPSHOT
这将会安装一个名叫dev的本地spring实例,它指向你的目标构建位置,所以每次你
重新构建SpringBoot,spring都会更新为最新的。
你可以通过以下命令来验证:
10.2.SpringBootCLI安装
42

$sdklsspringboot
================================================================
================
AvailableSpringbootVersions
================================================================
================
>+dev
*1.4.0.BUILD-SNAPSHOT
================================================================
================
+-localversion
*-installed
>-currentlyinuse
================================================================
================
10.2.SpringBootCLI安装
43

10.2.5.命令行实现
SpringBootCLI启动脚本为BASH和zshshells提供完整的命令行实现。你可以在任
何shell中source脚本(名称也是spring),或将它放到用户或系统范围内的bash初
始化脚本里。在Debian系统中,系统级的脚本位于 /shell-
completion/bash下,当新的shell启动时该目录下的所有脚本都会被执行。如果
想要手动运行脚本,假如你已经安装了SDKMAN,可以使用以下命令:
$.~/.sdkman/candidates/springboot/current/shell-completion/bas
h/spring
$spring<HITTABHERE>
grabhelpjarruntestversion
注:如果你使用Homebrew或MacPorts安装SpringBootCLI,命令行实现脚本会自
动注册到你的shell。
10.2.SpringBootCLI安装
46

10.2.6.SpringCLI示例快速入门
下面是一个相当简单的web应用,你可以用它测试SpringCLI安装是否成功。创建
一个名叫 app.groovy的文件:
@RestController
classThisWillActuallyRun{
@RequestMapping("/")
Stringhome(){
"HelloWorld!"
}
}
然后只需在shell中运行以下命令:
$springrunapp.groovy
注:首次运行该应用将会花费一些时间,因为需要下载依赖,后续运行将会快很
多。
使用你最喜欢的浏览器打开localhost:8080,然后就可以看到如下输出:
HelloWorld!
10.2.SpringBootCLI安装
47

11.开发你的第一个SpringBoot应用
我们将使用Java开发一个简单的"HelloWorld"web应用,以此强调下SpringBoot的
一些关键特性。项目采用Maven进行构建,因为大多数IDEs都支持它。
注:spring.io网站包含很多SpringBoot"入门"指南,如果你正在找特定问题的解决
方案,可以先去那瞅瞅。你也可以简化下面的步骤,直接从start.spring.io的依赖搜
索器选中 webstarter,这会自动生成一个新的项目结构,然后你就可以happy的
敲代码了。具体详情参考文档。
在开始前,你需要打开终端检查下安装的Java和Maven版本是否可用:
$java-version
javaversion"1.7.0_51"
Java(TM)SERuntimeEnvironment(build1.7.0_51-b13)
JavaHotSpot(TM)64-BitServerVM(build24.51-b03,mixedmode)
$mvn-v
ApacheMaven3.2.3(33f8c3e1027c3ddde99d3cdebad2656a31e8fdf4;20
14-08-11T13:58:10-07:00)
Mavenhome:/Users/user/tools/apache-maven-3.1.1
Javaversion:1.7.0_51,vendor:OracleCorporation
注:该示例需要创建单独的文件夹,后续的操作建立在你已创建一个合适的文件
夹,并且它是你的“当前目录”。
11.开发你的第一个SpringBoot应用
49

11.1.创建POM
让我们以创建一个Maven pom.xml文件作为开始吧,因为 pom.xml是构建项目
的处方!打开你最喜欢的文本编辑器,并添加以下内容:
<?xmlversion="1.0"encoding="UTF-8"?>
<projectxmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="ht
tp://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0http:/
/maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>myproject</artifactId>
<version>0.0.1-SNAPSHOT</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.4.1.BUILD-SNAPSHOT</version>
</parent>
<!--Additionallinestobeaddedhere...-->
<!--(youdon'tneedthisifyouareusinga.RELEASEversio
n)-->
<repositories>
<repository>
<id>spring-snapshots</id>
<url>http://repo.spring.io/snapshot</url>
<snapshots><enabled>true</enabled></snapshots>
</repository>
<repository>
<id>spring-milestones</id>
<url>http://repo.spring.io/milestone</url>
</repository>
</repositories>
<pluginRepositories>
11.1.创建POM
50

<pluginRepository>
<id>spring-snapshots</id>
<url>http://repo.spring.io/snapshot</url>
</pluginRepository>
<pluginRepository>
<id>spring-milestones</id>
<url>http://repo.spring.io/milestone</url>
</pluginRepository>
</pluginRepositories>
</project>
这样一个可工作的构建就完成了,你可以通过运行 mvnpackage测试它(暂时忽
略"jar将是空的-没有包含任何内容!"的警告)。
注:此刻,你可以将该项目导入到IDE中(大多数现代的JavaIDE都包含对Maven
的内建支持)。简单起见,我们将继续使用普通的文本编辑器完成该示例。
11.1.创建POM
51

11.2.添加classpath依赖
SpringBoot提供很多"Starters",用来简化添加jars到classpath的操作。示例程序中
已经在POM的parent节点使用了 spring-boot-starter-parent,它是一个
特殊的starter,提供了有用的Maven默认设置。同时,它也提供一个 dependency-
management节点,这样对于期望(”blessed“)的依赖就可以省略version标记了。
其他”Starters“只简单提供开发特定类型应用所需的依赖。由于正在开发web应用,
我们将添加 spring-boot-starter-web依赖-但在此之前,让我们先看下目前的
依赖:
$mvndependency:tree
[INFO]com.example:myproject:jar:0.0.1-SNAPSHOT
mvndependency:tree命令可以将项目依赖以树形方式展现出来,你可以看
到spring-boot-starter-parent本身并没有提供依赖。编辑 pom.xml,并
在parent节点下添加 spring-boot-starter-web依赖:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
如果再次运行 mvndependency:tree,你将看到现在多了一些其他依赖,包括
Tomcatweb服务器和SpringBoot自身。
11.2.添加classpath依赖
52

11.3.编写代码
为了完成应用程序,我们需要创建一个单独的Java文件。Maven默认会编
译src/main/java下的源码,所以你需要创建那样的文件结构,并添加一个名
为src/main/java/Example.java的文件:
importorg.springframework.boot.*;
importorg.springframework.boot.autoconfigure.*;
importorg.springframework.stereotype.*;
importorg.springframework.web.bind.annotation.*;
@RestController
@EnableAutoConfiguration
publicclassExample{
@RequestMapping("/")
Stringhome(){
return"HelloWorld!";
}
publicstaticvoidmain(String[]args)throwsException{
SpringApplication.run(Example.class,args);
}
}
尽管代码不多,但已经发生了很多事情,让我们分步探讨重要的部分吧!
11.3.编写代码
53

11.3.1.@RestController和@RequestMapping注解
Example类上使用的第一个注解是 @RestController,这被称为构造型
(stereotype)注解。它为阅读代码的人提供暗示(这是一个支持REST的控制
器),对于Spring,该类扮演了一个特殊角色。在本示例中,我们的类是一个web
@Controller,所以当web请求进来时,Spring会考虑是否使用它来处理。
@RequestMapping注解提供路由信息,它告诉Spring任何来自"/"路径的HTTP请
求都应该被映射到 home方法。 @RestController注解告诉Spring以字符串的形
式渲染结果,并直接返回给调用者。
注: @RestController和@RequestMapping是SpringMVC中的注解(它们不
是SpringBoot的特定部分),具体参考Spring文档的MVC章节。
11.3.编写代码
54

11.3.2.@EnableAutoConfiguration注解
第二个类级别的注解是 @EnableAutoConfiguration,这个注解告诉SpringBoot
根据添加的jar依赖猜测你想如何配置Spring。由于 spring-boot-starter-web添
加了Tomcat和SpringMVC,所以auto-configuration将假定你正在开发一个web应
用,并对Spring进行相应地设置。
Starters和Auto-Configuration:Auto-configuration设计成可以跟"Starters"一起很
好的使用,但这两个概念没有直接的联系。你可以自由地挑选starters以外的jar依
赖,SpringBoot仍会尽最大努力去自动配置你的应用。
11.3.编写代码
55

11.3.3.main方法
应用程序的最后部分是main方法,这是一个标准的方法,它遵循Java对于一个应用
程序入口点的约定。我们的main方法通过调用 run,将业务委托给了SpringBoot
的SpringApplication类。SpringApplication将引导我们的应用,启动Spring,相应
地启动被自动配置的Tomcatweb服务器。我们需要将 Example.class作为参数传
递给 run方法,以此告诉SpringApplication谁是主要的Spring组件,并传递args数
组以暴露所有的命令行参数。
11.3.编写代码
56

11.4.运行示例
到此,示例应用可以工作了。由于使用了 spring-boot-starter-parent
POM,这样我们就有了一个非常有用的run目标来启动程序。在项目根目录下输
入mvnspring-boot:run启动应用:
$mvnspring-boot:run
._________
/\\/___'_____(_)______\\\\
(()\___|'_|'_||'_\/_`|\\\\
\\/___)||_)|||||||(_||))))
'|____|.__|_||_|_||_\__,|////
=========|_|==============|___/=/_/_/_/
::SpringBoot::(v1.4.1.BUILD-SNAPSHOT)
..........
..........(logoutputhere)
..........
........StartedExamplein2.222seconds(JVMrunningfor6.514
)
如果使用浏览器打开localhost:8080,你应该可以看到如下输出:
HelloWorld!
点击 ctrl-c温雅地关闭应用程序。
11.4.运行示例
57

11.5.创建可执行jar
让我们通过创建一个完全自包含,并可以在生产环境运行的可执行jar来结束示例
吧!可执行jars(有时被称为胖jars"fatjars")是包含编译后的类及代码运行所需依
赖jar的存档。
可执行jars和Java:Java没有提供任何标准方式,用于加载内嵌jar文件(即jar文件
中还包含jar文件),这对分发自包含应用来说是个问题。为了解决该问题,很多开
发者采用"共享的"jars。共享的jar只是简单地将所有jars的类打包进一个单独的存
档,这种方式存在的问题是,很难区分应用程序中使用了哪些库。在多个jars中如
果存在相同的文件名(但内容不一样)也会是一个问题。SpringBoot采取一个不同
的方式,允许你真正的直接内嵌jars。
为了创建可执行的jar,我们需要将 spring-boot-maven-plugin添加
到pom.xml中,在dependencies节点后面插入以下内容:
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
注: spring-boot-starter-parentPOM包含绑定到repackage目标
的<executions>配置。如果不使用parentPOM,你需要自己声明该配置,具体
参考插件文档。
保存 pom.xml,并从命令行运行 mvnpackage:
11.5.创建一个可执行jar
58

$mvnpackage
[INFO]Scanningforprojects...
[INFO]
[INFO]---------------------------------------------------------
---------------
[INFO]Buildingmyproject0.0.1-SNAPSHOT
[INFO]---------------------------------------------------------
---------------
[INFO]......
[INFO]---maven-jar-plugin:2.4:jar(default-jar)@myproject--
-
[INFO]Buildingjar:/Users/developer/example/spring-boot-exampl
e/target/myproject-0.0.1-SNAPSHOT.jar
[INFO]
[INFO]---spring-boot-maven-plugin:1.4.1.BUILD-SNAPSHOT:repacka
ge(default)@myproject---
[INFO]---------------------------------------------------------
---------------
[INFO]BUILDSUCCESS
[INFO]---------------------------------------------------------
---------------
如果查看target目录,你应该可以看到 myproject-0.0.1-SNAPSHOT.jar,该文
件大概有10Mb。想查看内部结构,可以运行 jartvf:
$jartvftarget/myproject-0.0.1-SNAPSHOT.jar
在该目录下,你应该还能看到一个很小的名为 myproject-0.0.1-
SNAPSHOT.jar.original的文件,这是在SpringBoot重新打包前,Maven创建的
原始jar文件。
可以使用 java-jar命令运行该应用程序:
11.5.创建一个可执行jar
59

$java-jartarget/myproject-0.0.1-SNAPSHOT.jar
._________
/\\/___'_____(_)______\\\\
(()\___|'_|'_||'_\/_`|\\\\
\\/___)||_)|||||||(_||))))
'|____|.__|_||_|_||_\__,|////
=========|_|==============|___/=/_/_/_/
::SpringBoot::(v1.3.0.BUILD-SNAPSHOT)
..........
..........(logoutputhere)
..........
........StartedExamplein2.536seconds(JVMrunningfor2.864
)
如上所述,点击 ctrl-c可以温雅地退出应用。
11.5.创建一个可执行jar
60

使用SpringBoot
本章节将详细介绍如何使用SpringBoot,不仅覆盖构建系统,自动配置,如何运行
应用等主题,还包括一些SpringBoot的最佳实践。尽管SpringBoot本身没有什么
特别的(跟其他一样,它只是另一个你可以使用的库),但仍有一些建议,如果遵
循的话将会事半功倍。
如果你刚接触SpringBoot,那最好先阅读上一章节的GettingStarted指南。
III.使用SpringBoot
62

13.构建系统
强烈建议你选择一个支持依赖管理,能消费发布到"Maven中央仓库"的artifacts的构
建系统,比如Maven或Gradle。使用其他构建系统也是可以的,比如Ant,但它们
可能得不到很好的支持。
13.构建系统
63

13.1.依赖管理
SpringBoot每次发布时都会提供一个它所支持的精选依赖列表。实际上,在构建配
置里你不需要提供任何依赖的版本,因为SpringBoot已经替你管理好了。当更新
SpringBoot时,那些依赖也会一起更新。
注如果有必要,你可以指定依赖的版本来覆盖SpringBoot默认版本。
精选列表包括所有能够跟SpringBoot一起使用的Spring模块及第三方库,该列表可
以在材料清单(spring-boot-dependencies)获取到,也可以找到一些支持Maven和
Gradle的资料。
注SpringBoot每次发布都关联一个Spring框架的基础版本,所以强烈建议你不要自
己指定Spring版本。
13.1.依赖管理
64

13.2.Maven
Maven用户可以继承 spring-boot-starter-parent项目来获取合适的默认设
置。该parent项目提供以下特性:
默认编译级别为Java1.6
源码编码为UTF-8
一个Dependencymanagement节点,允许你省略常见依赖的 <version>标
签,继承自 spring-boot-dependenciesPOM。
恰到好处的资源过滤
恰到好处的插件配置(exec插件,surefire,GitcommitID,shade)
恰到好处的对 application.properties和application.yml进行筛选,
包括特定profile(profile-specific)的文件,比如 application-
foo.properties和application-foo.yml
最后一点:由于配置文件默认接收Spring风格的占位符( ${...}),所以Maven
filtering需改用 @..@占位符(你可以使用Maven属性 resource.delimiter来覆
盖它)。
13.2.Maven
65

13.2.1.继承starterparent
如果你想配置项目,让其继承自 spring-boot-starter-parent,只需
将parent按如下设置:
<!--InheritdefaultsfromSpringBoot-->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.4.1.BUILD-SNAPSHOT</version>
</parent>
注:你应该只需在该依赖上指定SpringBoot版本,如果导入其他的starters,放心
的省略版本号好了。
按照以上设置,你可以在自己的项目中通过覆盖属性来覆盖个别的依赖。例如,你
可以将以下设置添加到 pom.xml中来升级SpringData到另一个发布版本。
<properties>
<spring-data-releasetrain.version>Fowler-SR2</spring-data-re
leasetrain.version>
</properties>
注查看spring-boot-dependenciespom获取支持的属性列表。
13.2.Maven
66

13.2.2.在不使用parentPOM的情况下玩转Spring
Boot
不是每个人都喜欢继承 spring-boot-starter-parentPOM,比如你可能需要
使用公司的标准parent,或只是倾向于显式声明所有的Maven配置。
如果你不想使用 spring-boot-starter-parent,通过设置 scope=import的依
赖,你仍能获取到依赖管理的好处:
<dependencyManagement>
<dependencies>
<dependency>
<!--ImportdependencymanagementfromSpringBoot-
->
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>1.4.1.BUILD-SNAPSHOT</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
以上设置不允许你使用属性覆盖个别依赖,为了达到这个目的,你需要在项目
的dependencyManagement节点中,在 spring-boot-dependencies实体前插
入一个节点。例如,为了将SpringData升级到另一个发布版本,你需要将以下配置
添加到 pom.xml中:
13.2.Maven
67

<dependencyManagement>
<dependencies>
<!--OverrideSpringDatareleasetrainprovidedbySpri
ngBoot-->
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-releasetrain</artifactId>
<version>Fowler-SR2</version>
<scope>import</scope>
<type>pom</type>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>1.4.1.BUILD-SNAPSHOT</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
注示例中,我们指定了一个BOM,但任何的依赖类型都可以通过这种方式覆盖。
13.2.Maven
68

13.2.3.改变Java版本
spring-boot-starter-parent选择了相当保守的Java兼容策略,如果你遵循我
们的建议,使用最新的Java版本,可以添加一个 java.version属性:
<properties>
<java.version>1.8</java.version>
</properties>
13.2.Maven
69

13.2.4.使用SpringBootMaven插件
SpringBoot包含一个Maven插件,它可以将项目打包成一个可执行jar。如果想使用
它,你可以将该插件添加到 <plugins>节点处:
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
注:如果使用SpringBootstarterparentpom,你只需添加该插件而无需配置它,
除非你想改变定义在partent中的设置。
13.2.Maven
70

13.3.Gradle
Gradle用户可以直接在它们的 dependencies节点处导入”starters“。跟Maven不
同的是,这里不用导入"superparent",也就不能共享配置。
applyplugin:'java'
repositories{
maven{url"http://repo.spring.io/snapshot"}
maven{url"http://repo.spring.io/milestone"}
}
dependencies{
compile("org.springframework.boot:spring-boot-starter-web:1.
4.1.BUILD-SNAPSHOT")
}
跟maven类似,springboot也有gradle插件spring-boot-gradle-plugin,它能够提供
任务用于创建可执行jar,或从源码(source)运行项目。它也提供依赖管理的能
力,该功能允许你省略SpringBoot管理的任何依赖的version版本号:
13.3.Gradle
71

buildscript{
repositories{
maven{url"http://repo.spring.io/snapshot"}
maven{url"http://repo.spring.io/milestone"}
}
dependencies{
classpath("org.springframework.boot:spring-boot-gradle-p
lugin:1.4.1.BUILD-SNAPSHOT")
}
}
applyplugin:'java'
applyplugin:'spring-boot'
repositories{
maven{url"http://repo.spring.io/snapshot"}
maven{url"http://repo.spring.io/milestone"}
}
dependencies{
compile("org.springframework.boot:spring-boot-starter-web")
testCompile("org.springframework.boot:spring-boot-starter-te
st")
}
13.3.Gradle
72

13.4.Ant
使用ApacheAnt+Ivy构建SpringBoot项目是完全可能的。 spring-boot-antlib
AntLib模块能够帮助Ant创建可执行jars,一个传统的用于声明依赖的 ivy.xml文
件可能如下所示:
<ivy-moduleversion="2.0">
<infoorganisation="org.springframework.boot"module="spring
-boot-sample-ant"/>
<configurations>
<confname="compile"description="everythingneededtoc
ompilethismodule"/>
<confname="runtime"extends="compile"description="ever
ythingneededtorunthismodule"/>
</configurations>
<dependencies>
<dependencyorg="org.springframework.boot"name="spring-
boot-starter"
rev="${spring-boot.version}"conf="compile"/>
</dependencies>
</ivy-module>
同样,一个传统的 build.xml可能是这样的:
13.4.Ant
73

<project
xmlns:ivy="antlib:org.apache.ivy.ant"
xmlns:spring-boot="antlib:org.springframework.boot.ant"
name="myapp"default="build">
<propertyname="spring-boot.version"value="1.3.0.BUILD-SNAP
SHOT"/>
<targetname="resolve"description="-->retrievedependencie
swithivy">
<ivy:retrievepattern="lib/[conf]/[artifact]-[type]-[rev
ision].[ext]"/>
</target>
<targetname="classpaths"depends="resolve">
<pathid="compile.classpath">
<filesetdir="lib/compile"includes="*.jar"/>
</path>
</target>
<targetname="init"depends="classpaths">
<mkdirdir="build/classes"/>
</target>
<targetname="compile"depends="init"description="compile">
<javacsrcdir="src/main/java"destdir="build/classes"cl
asspathref="compile.classpath"/>
</target>
<targetname="build"depends="compile">
<spring-boot:exejardestfile="build/myapp.jar"classes="
build/classes">
<spring-boot:lib>
<filesetdir="lib/runtime"/>
</spring-boot:lib>
</spring-boot:exejar>
</target>
</project>
13.4.Ant
74

注如果你不想使用 spring-boot-antlib模块,那查看Section81.10,“Buildan
executablearchivefromAntwithoutusingspring-boot-antlib”获取更多指导。
13.4.Ant
75

13.5.Starters
Starters是一个依赖描述符的集合,你可以将它包含进项目中,这样添加依赖就非
常方便。你可以获取所有Spring及相关技术的一站式服务,而不需要翻阅示例代
码,拷贝粘贴大量的依赖描述符。例如,如果你想使用Spring和JPA进行数据库访
问,只需要在项目中包含 spring-boot-starter-data-jpa依赖,然后你就可以
开始了。
该starters包含很多搭建,快速运行项目所需的依赖,并提供一致的,可管理传递性
的依赖集。
名字有什么含义:所有官方starters遵循相似的命名模式: spring-boot-
starter-*,在这里 *是一种特殊的应用程序类型。该命名结构旨在帮你找到需
要的starter。很多集成于IDEs中的Maven插件允许你通过名称name搜索依赖。例
如,使用相应的Eclipse或STS插件,你可以简单地在POM编辑器中点击 ctrl-
space,然后输入"spring-boot-starter"就可以获取一个完整列表。正如Creating
yourownstarter章节中讨论的,第三方starters不应该以 spring-boot开头,因
为它跟SpringBoot官方artifacts冲突。一个acme的第三方starter通常命名为 acme-
spring-boot-starter。
以下应用程序starters是SpringBoot在org.springframework.bootgroup下提供
的:
表13.1.SpringBootapplicationstarters
名称 描述 Pom
spring-boot-
starter-test
用于测试SpringBoot应用,支持常用测试类库,包
括JUnit,Hamcrest和Mockito Pom
spring-boot-
starter-mobile 用于使用SpringMobile开发web应用 Pom
spring-boot-
starter-social-
twitter
对使用SpringSocialTwitter的支持 Pom
spring-boot-
starter-cache 用于使用Spring框架的缓存支持 Pom
spring-boot-
starter-activemq 用于使用ApacheActiveMQ实现JMS消息 Pom
13.5.Starters
76

spring-boot-
starter-jta-
atomikos
用于使用Atomikos实现JTA事务 Pom
spring-boot-
starter-aop 用于使用SpringAOP和AspectJ实现面向切面编程 Pom
spring-boot-
starter-web
用于使用SpringMVC构建web应用,包括
RESTful。Tomcat是默认的内嵌容器 Pom
spring-boot-
starter-data-
elasticsearch
用于使用Elasticsearch搜索,分析引擎和Spring
DataElasticsearch Pom
spring-boot-
starter-jdbc 对JDBC的支持(使用TomcatJDBC连接池) Pom
spring-boot-
starter-batch 对SpringBatch的支持 Pom
spring-boot-
starter-social-
facebook
用于使用SpringSocialFacebook Pom
spring-boot-
starter-web-
services
对SpringWeb服务的支持 Pom
spring-boot-
starter-jta-
narayana
SpringBootNarayanaJTAStarter Pom
spring-boot-
starter-
thymeleaf
用于使用Thymeleaf模板引擎构建MVCweb应用 Pom
spring-boot-
starter-mail 用于使用JavaMail和Spring框架email发送支持 Pom
spring-boot-
starter-jta-
bitronix
用于使用Bitronix实现JTA事务 Pom
spring-boot-
starter-data-
mongodb
用于使用基于文档的数据库MongoDB和Spring
DataMongoDB Pom
spring-boot-
starter-
validation
用于使用HibernateValidator实现JavaBean校验 Pom
spring-boot-
starter-jooq
用于使用JOOQ访问SQL数据库,可使用spring-
boot-starter-data-jpa或spring-boot-starter-jdbc替Pom
13.5.Starters
77

starter-jooq 代
spring-boot-
starter-redis
用于使用SpringDataRedis和Jedis客户端操作键-
值存储的Redis,在1.4中已被spring-boot-starter-
data-redis取代
Pom
spring-boot-
starter-data-
cassandra
用于使用分布式数据库Cassandra和SpringData
Cassandra Pom
spring-boot-
starter-hateoas
用于使用SpringMVC和SpringHATEOAS实现基于
超媒体的RESTfulweb应用 Pom
spring-boot-
starter-
integration
用于使用SpringIntegration Pom
spring-boot-
starter-data-solr 通过SpringDataSolr使用ApacheSolr搜索平台 Pom
spring-boot-
starter-
freemarker
用于使用FreeMarker模板引擎构建MVCweb应用 Pom
spring-boot-
starter-jersey
用于使用JAX-RS和Jersey构建RESTfulweb应用,
可使用spring-boot-starter-web替代 Pom
spring-boot-
starter 核心starter,包括自动配置支持,日志和YAML Pom
spring-boot-
starter-data-
couchbase
用于使用基于文档的数据库Couchbase和Spring
DataCouchbase Pom
spring-boot-
starter-artemis 使用ApacheArtemis实现JMS消息 Pom
spring-boot-
starter-cloud-
connectors
对SpringCloudConnectors的支持,用于简化云平
台下(例如CloudFoundry和Heroku)服务的连接 Pom
spring-boot-
starter-social-
linkedin
用于使用SpringSocialLinkedIn Pom
spring-boot-
starter-velocity
用于使用Velocity模板引擎构建MVCweb应用,从
1.4版本过期 Pom
spring-boot-
starter-data-rest
用于使用SpringDataREST暴露基于REST的
SpringData仓库 Pom
spring-boot-
starter-data- 用于使用分布式数据存储GemFire和SpringData
13.5.Starters
78

spring-boot-
starter-groovy-
templates
用于使用Groovy模板引擎构建MVCweb应用 Pom
spring-boot-
starter-amqp 用于使用SpringAMQP和RabbitMQ Pom
spring-boot-
starter-hornetq
用于使用HornetQ实现JMS消息,被spring-boot-
starter-artemis取代 Pom
spring-boot-
starter-ws
用于使用SpringWeb服务,被spring-boot-starter-
web-services取代 Pom
spring-boot-
starter-security 对SpringSecurity的支持 Pom
spring-boot-
starter-data-
redis
用于使用SpringDataRedis和Jedis客户端操作键
—值数据存储Redis Pom
spring-boot-
starter-
websocket
用于使用Spring框架的WebSocket支持构建
WebSocket应用 Pom
spring-boot-
starter-
mustache
用于使用Mustache模板引擎构建MVCweb应用 Pom
spring-boot-
starter-data-
neo4j
用于使用图数据库Neo4j和SpringDataNeo4j Pom
spring-boot-
starter-data-jpa 用于使用Hibernate实现SpringDataJPA Pom
除了应用程序starters,以下starters可用于添加productionready的功能:
表13.2.SpringBoot生产级starters
名称 描述 Pom
spring-boot-
starter-actuator
用于使用SpringBoot的Actuator,它提供了
productionready功能来帮助你监控和管理应用程
序
Pom
spring-boot-
starter-remote-
shell
用于通过SSH,使用CRaSH远程shell监控,管理
你的应用 Pom
最后,SpringBoot还包含一些用于排除或交换某些特定技术方面的starters:
13.5.Starters
79

最后,SpringBoot还包含一些用于排除或交换某些特定技术方面的starters:
表13.3.SpringBoot技术性starters
名称 描述 Pom
spring-boot-
starter-undertow
用于使用Undertow作为内嵌servlet容器,可使
用spring-boot-starter-tomcat替代 Pom
spring-boot-
starter-logging 用于使用Logback记录日志,默认的日志starter Pom
spring-boot-
starter-tomcat
用于使用Tomcat作为内嵌servlet容器,spring-
boot-starter-web使用的默认servlet容器 Pom
spring-boot-
starter-jetty
用于使用Jetty作为内嵌servlet容器,可使用spring-
boot-starter-tomcat替代 Pom
spring-boot-
starter-log4j2
用于使用Log4j2记录日志,可使用spring-boot-
starter-logging代替 Pom
注:查看GitHub上位于 spring-boot-starters模块内的README文件,可以获
取到一个社区贡献的其他starters列表。
13.5.Starters
80

14.组织你的代码
SpringBoot不要求使用任何特殊的代码结构,不过,遵循以下的一些最佳实践还是
挺有帮助的。
14.组织你的代码
81

14.1.使用"default"包
当类没有声明 package时,它被认为处于 defaultpackage下。通常不推荐使
用defaultpackage,因为对于使
用@ComponentScan,@EntityScan或@SpringBootApplication注解的
SpringBoot应用来说,它会扫描每个jar中的类,这会造成一定的问题。
注我们建议你遵循Java推荐的包命名规范,使用一个反转的域名(例
如com.example.project)。
14.1.使用"default"包
82

14.2.放置应用的main类
通常建议将应用的main类放到其他类所在包的顶层(rootpackage),并
将@EnableAutoConfiguration注解到你的main类上,这样就隐式地定义了一个
基础的包搜索路径(searchpackage),以搜索某些特定的注解实体(比如
@Service,@Component等)。例如,如果你正在编写一个JPA应用,Spring将
搜索 @EnableAutoConfiguration注解的类所在包下的 @Entity实体。
采用rootpackage方式,你就可以使用 @ComponentScan注解而不需要指
定basePackage属性,也可以使用 @SpringBootApplication注解,只要将
main类放到rootpackage中。
下面是一个典型的结构:
com
+-example
+-myproject
+-Application.java
|
+-domain
|+-Customer.java
|+-CustomerRepository.java
|
+-service
|+-CustomerService.java
|
+-web
+-CustomerController.java
Application.java将声明 main方法,还有基本的 @Configuration。
14.2.放置应用的main类
83

packagecom.example.myproject;
importorg.springframework.boot.SpringApplication;
importorg.springframework.boot.autoconfigure.EnableAutoConfigur
ation;
importorg.springframework.context.annotation.ComponentScan;
importorg.springframework.context.annotation.Configuration;
@Configuration
@EnableAutoConfiguration
@ComponentScan
publicclassApplication{
publicstaticvoidmain(String[]args){
SpringApplication.run(Application.class,args);
}
}
14.2.放置应用的main类
84

15.配置类
SpringBoot提倡基于Java的配置。尽管你可以使用XML源调
用SpringApplication.run(),不过还是建议你使用 @Configuration类作为
主要配置源。通常定义了 main方法的类也是使用 @Configuration注解的一个
很好的替补。
注:虽然网络上有很多使用XML配置的Spring示例,但你应该尽可能的使用基于
Java的配置,搜索查看 enable*注解就是一个好的开端。
15.配置类
85

15.1.导入其他配置类
你不需要将所有的 @Configuration放进一个单独的类, @Import注解可以用来
导入其他配置类。另外,你也可以使用 @ComponentScan注解自动收集所有
Spring组件,包括 @Configuration类。
15.1.导入其他配置类
86

15.2.导入XML配置
如果必须使用XML配置,建议你仍旧从一个 @Configuration类开始,然后使
用@ImportResource注解加载XML配置文件。
15.2.导入XML配置
87

16.自动配置
SpringBoot自动配置(auto-configuration)尝试根据添加的jar依赖自动配置你的
Spring应用。例如,如果classpath下存在 HSQLDB,并且你没有手动配置任何数据
库连接的beans,那么SpringBoot将自动配置一个内存型(in-memory)数据库。
实现自动配置有两种可选方式,分别是
将@EnableAutoConfiguration或@SpringBootApplication注解
到@Configuration类上。
注:你应该只添加一个 @EnableAutoConfiguration注解,通常建议将它添加到
主配置类(primary @Configuration)上。
16.自动配置
88

16.1.逐步替换自动配置
自动配置(Auto-configuration)是非侵入性的,任何时候你都可以定义自己的配置
类来替换自动配置的特定部分。例如,如果你添加自己的 DataSourcebean,默
认的内嵌数据库支持将不被考虑。
如果需要查看当前应用启动了哪些自动配置项,你可以在运行应用时打开 --
debug开关,这将为核心日志开启debug日志级别,并将自动配置相关的日志输出
到控制台。
16.1.逐步替换自动配置
89

16.2.禁用特定的自动配置项
如果发现启用了不想要的自动配置项,你可以使
用@EnableAutoConfiguration注解的exclude属性禁用它们:
importorg.springframework.boot.autoconfigure.*;
importorg.springframework.boot.autoconfigure.jdbc.*;
importorg.springframework.context.annotation.*;
@Configuration
@EnableAutoConfiguration(exclude={DataSourceAutoConfiguration.cl
ass})
publicclassMyConfiguration{
}
如果该类不在classpath中,你可以使用该注解的excludeName属性,并指定全限定
名来达到相同效果。最后,你可以通过 spring.autoconfigure.exclude属性
exclude多个自动配置项(一个自动配置项集合)。
注通过注解级别或exclude属性都可以定义排除项。
16.2.禁用特定的自动配置
90

17.SpringBeans和依赖注入
你可以自由地使用任何标准的Spring框架技术去定义beans和它们注入的依赖。简
单起见,我们经常使用 @ComponentScan注解搜索beans,并结
合@Autowired构造器注入。
如果遵循以上的建议组织代码结构(将应用的main类放到包的最上层,即root
package),那么你就可以添加 @ComponentScan注解而不需要任何参数,所有应
用组件( @Component, @Service, @Repository, @Controller等)都会自
动注册成SpringBeans。
下面是一个 @ServiceBean的示例,它使用构建器注入获取一个需要
的RiskAssessorbean。
packagecom.example.service;
importorg.springframework.beans.factory.annotation.Autowired;
importorg.springframework.stereotype.Service;
@Service
publicclassDatabaseAccountServiceimplementsAccountService{
privatefinalRiskAssessorriskAssessor;
@Autowired
publicDatabaseAccountService(RiskAssessorriskAssessor){
this.riskAssessor=riskAssessor;
}
//...
}
注注意使用构建器注入允许 riskAssessor字段被标记为 final,这意味
着riskAssessor后续是不能改变的。
17.SpringBeans和依赖注入
91

18.使用@SpringBootApplication注解
很多SpringBoot开发者经常使
用@Configuration,@EnableAutoConfiguration,@ComponentScan注解
他们的main类,由于这些注解如此频繁地一块使用(特别是遵循以上最佳实践的时
候),SpringBoot就提供了一个方便的 @SpringBootApplication注解作为代
替。
@SpringBootApplication注解等价于以默认属性使
用@Configuration,@EnableAutoConfiguration和@ComponentScan:
packagecom.example.myproject;
importorg.springframework.boot.SpringApplication;
importorg.springframework.boot.autoconfigure.SpringBootApplicat
ion;
@SpringBootApplication//sameas@Configuration@EnableAutoConf
iguration@ComponentScan
publicclassApplication{
publicstaticvoidmain(String[]args){
SpringApplication.run(Application.class,args);
}
}
注@SpringBootApplication注解也提供了用于自定
义@EnableAutoConfiguration和@ComponentScan属性的别名(aliases)。
18.使用@SpringBootApplication注解
92

19.运行应用程序
将应用打包成jar,并使用内嵌HTTP服务器的一个最大好处是,你可以像其他方式
那样运行你的应用程序。调试SpringBoot应用也很简单,你都不需要任何特殊IDE
插件或扩展!
注:本章节只覆盖基于jar的打包,如果选择将应用打包成war文件,你最好参考相
关的服务器和IDE文档。
19.运行应用程序
93

19.1.从IDE中运行
你可以从IDE中运行SpringBoot应用,就像一个简单的Java应用,但首先需要导入
项目。导入步骤取决于你的IDE和构建系统,大多数IDEs能够直接导入Maven项
目,例如Eclipse用户可以选择 File菜单的 Import…--> ExistingMaven
Projects。
如果不能直接将项目导入IDE,你可以使用构建系统生成IDE的元数据。Maven有针
对Eclipse和IDEA的插件;Gradle为各种IDEs提供插件。
注如果意外地多次运行一个web应用,你将看到一个"端口已被占用"的错误。STS
用户可以使用 Relaunch而不是 Run按钮,以确保任何存在的实例是关闭的。
19.1.从IDE中运行
94

19.2.作为一个打包后的应用运行
如果使用SpringBootMaven或Gradle插件创建一个可执行jar,你可以使用 java-
jar运行应用。例如:
$java-jartarget/myproject-0.0.1-SNAPSHOT.jar
SpringBoot支持以远程调试模式运行一个打包的应用,下面的命令可以为应用关联
一个调试器:
$java-Xdebug-Xrunjdwp:server=y,transport=dt_socket,address=80
00,suspend=n\
-jartarget/myproject-0.0.1-SNAPSHOT.jar
19.2.作为一个打包后的应用运行
95

19.3.使用Maven插件运行
SpringBootMaven插件包含一个 run目标,可用来快速编译和运行应用程序,并
且跟在IDE运行一样支持热加载。
$mvnspring-boot:run
你可以使用一些有用的操作系统环境变量:
$exportMAVEN_OPTS=-Xmx1024m-XX:MaxPermSize=128M
19.3.使用Maven插件运行
96

19.4.使用Gradle插件运行
SpringBootGradle插件也包含一个 bootRun任务,可用来运行你的应用程序。无
论你何时import spring-boot-gradle-plugin,bootRun任务总会被添加进
去。
$gradlebootRun
你可能想使用一些有用的操作系统环境变量:
$exportJAVA_OPTS=-Xmx1024m-XX:MaxPermSize=128M
19.4.使用Gradle插件运行
97

20.开发者工具
SpringBoot包含了一些额外的工具集,用于提升SpringBoot应用的开发体
验。 spring-boot-devtools模块可以included到任何模块中,以提供
development-time特性,你只需简单的将该模块的依赖添加到构建中:
Maven
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
Gradle
dependencies{
compile("org.springframework.boot:spring-boot-devtools")
}
注在运行一个完整的,打包过的应用时,开发者工具(devtools)会被自动禁用。
如果应用使用 java-jar或特殊的类加载器启动,都会被认为是一个产品级的应
用(productionapplication),从而禁用开发者工具。为了防止devtools传递到项
目中的其他模块,设置该依赖级别为optional是个不错的实践。不过Gradle不支
持optional依赖,所以你可能要了解下propdeps-plugin。如果想确保devtools绝
对不会包含在一个产品级构建中,你可以使用 excludeDevtools构建属性彻底移
除该JAR,Maven和Gradle都支持该属性。
20.开发者工具
99

20.1默认属性
SpringBoot支持的一些库(libraries)使用缓存提高性能,比如Thymeleaf将缓存模
板以避免重复解析XML源文件。虽然缓存在生产环境很有用,但开发期间就是个累
赘了。如果在IDE里修改了模板,你可能会想立即看到结果。
缓存选项通常配置在 application.properties文件中,比如Thymeleaf提供
了spring.thymeleaf.cache属性, spring-boot-devtools模块会自动应用
敏感的 development-time配置,而不是手动设置这些属性。
注查看DevToolsPropertyDefaultsPostProcessor获取完整的被应用的属性列表。
20.1默认属性
100

20.2自动重启
如果应用使用 spring-boot-devtools,则只要classpath下的文件有变动,它就
会自动重启。这在使用IDE时非常有用,因为可以很快得到代码改变的反馈。默认
情况下,classpath下任何指向文件夹的实体都会被监控,注意一些资源的修改比如
静态assets,视图模板不需要重启应用。
触发重启由于DevTools监控classpath下的资源,所以唯一触发重启的方式就是更
新classpath。引起classpath更新的方式依赖于你使用的IDE,在Eclipse里,保存一
个修改的文件将引起classpath更新,并触发重启。在IntelliJIDEA中,构建工程
(Build→MakeProject)有同样效果。
注你也可以通过支持的构建工具(比如,Maven和Gradle)启动应用,只要开启
fork功能,因为DevTools需要一个隔离的应用类加载器执行正确的操作。Gradle默
认支持该行为,按照以下配置可强制Maven插件fork进程:
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<fork>true</fork>
</configuration>
</plugin>
</plugins>
</build>
自动重启跟LiveReload可以一起很好的工作,具体参考下面章节。如果你使用
JRebel,自动重启将禁用以支持动态类加载,其他devtools特性,比如
LiveReload,属性覆盖仍旧可以使用。
DevTools依赖应用上下文的shutdown钩子来关闭处于重启过程的应用,如果禁用
shutdown钩子( SpringApplication.setRegisterShutdownHook(false)),
它将不能正常工作。
20.2自动重启
101

当判定classpath下实体的改变是否会触发重启时,DevTools自动忽略以下工
程: spring-boot,spring-boot-devtools,spring-boot-
autoconfigure,spring-boot-actuator和spring-boot-starter。
RestartvsReloadSpringBoot提供的重启技术是通过使用两个类加载器实现的。
没有变化的类(比如那些第三方jars)会加载进一个基础(basic)classloader,正
在开发的类会加载进一个重启(restart)classloader。当应用重启时,restart类加
载器会被丢弃,并创建一个新的。这种方式意味着应用重启通常比冷启动(cold
starts)快很多,因为基础类加载器已经可用,并且populated(意思是基础类加载
器加载的类比较多?)。
如果发现重启对于你的应用来说不够快,或遇到类加载的问题,那你可以考虑
reload技术,比如JRebel,这些技术是通过重写它们加载过的类实现的。Spring
Loaded提供了另一种选择,然而很多框架不支持它,也得不到商业支持。
20.2自动重启
102

20.2.1排除资源
某些资源的变化没必要触发重启,比如Thymeleaf模板可以随时编辑。默认情况
下,位于 /META-INF/maven,/META-
INF/resources,/resources,/static,/public或/templates下的
资源变更不会触发重启,但会触发实时加载(livereload)。你可以使
用spring.devtools.restart.exclude属性自定义这些排除规则,比如,为了
只排除 /static和/public,你可以这样设置:
spring.devtools.restart.exclude=static/**,public/**
注如果你想保留默认属性,并添加其他的排除规则,可以使
用spring.devtools.restart.additional-exclude属性作为代替。
20.2自动重启
103

20.2.2查看其他路径
如果想让应用在改变没有位于classpath下的文件时也会重启或重新加载,你可以使
用spring.devtools.restart.additional-paths属性来配置监控变化的额外路
径。你可以使用上面描述过的 spring.devtools.restart.exclude属性去控制
额外路径下的变化是否触发一个完整重启或只是一个实时重新加载。
20.2自动重启
104

20.2.3禁用重启
如果不想使用重启特性,你可以通过 spring.devtools.restart.enabled属性
来禁用它,通常情况下可以在 application.properties文件中设置(依旧会初
始化重启类加载器,但它不会监控文件变化)。
如果需要彻底禁用重启支持,比如,不能跟某个特殊库一块工作,你需要在调
用SpringApplication.run(…)之前设置一个系统属性,如下:
publicstaticvoidmain(String[]args){
System.setProperty("spring.devtools.restart.enabled","false"
);
SpringApplication.run(MyApp.class,args);
}
20.2自动重启
105

20.2.4使用触发器文件
如果使用一个IDE连续不断地编译变化的文件,你可能倾向于只在特定时间触发重
启,触发器文件可以帮你实现该功能。触发器文件是一个特殊的文件,只有修改它
才能实际触发一个重启检测。改变该文件只会触发检测,实际的重启只会在
Devtools发现它必须这样做的时候,触发器文件可以手动更新,也可以通过IDE插
件更新。
使用 spring.devtools.restart.trigger-file属性可以指定触发器文件。
注你可能想将 spring.devtools.restart.trigger-file属性设置为全局设
置,这样所有的工程表现都会相同。
20.2自动重启
106

20.2.5自定义restart类加载器
正如以上RestartvsReload章节讨论的,重启功能是通过两个类加载器实现的。对
于大部分应用来说是没问题的,但有时候它可能导致类加载问题。
默认情况,在IDE里打开的项目会通过'restart'类加载器加载,其他常规的 .jar文
件会使用'basic'类加载器加载。如果你工作在一个多模块的项目下,并且不是每个
模块都导入IDE里,你可能需要自定义一些东西。你需要创建一个 META-
INF/spring-devtools.properties文件, spring-devtools.properties文
件可以包含 restart.exclude.,restart.include.前缀的属
性。 include元素定义了那些需要加载进'restart'类加载器中的实
体, exclude元素定义了那些需要加载进'basic'类加载器中的实体,这些属性的
值是一个将应用到classpath的正则表达式。
例如:
restart.include.companycommonlibs=/mycorp-common-[\\w-]+\.jar
restart.include.projectcommon=/mycorp-myproj-[\\w-]+\.jar
注所有属性的keys必须唯一,只要
以restart.include.或restart.exclude.开头都会考虑进去。所有来自
classpath的META-INF/spring-devtools.properties都会被加载,你可以将文
件打包进工程或工程使用的库里。
20.2自动重启
107

20.2.6已知限制
重启功能不能跟使用标准 ObjectInputStream反序列化的对象工作,如果需要反
序列化数据,你可能需要使用Spring的ConfigurableObjectInputStream,并
结合 Thread.currentThread().getContextClassLoader()。
不幸的是,一些第三方库反序列化时没有考虑上下文类加载器,如果发现这样的问
题,你需要请求原作者给处理下。
20.2自动重启
108

20.4全局设置
在$HOME文件夹下添加一个 .spring-boot-devtools.properties的文件可以
用来配置全局的devtools设置(注意文件名以"."开头),添加进该文件的任何属性
都会应用到你机器上使用该devtools的SpringBoot应用。例如,想使用触发器文件
进行重启,可以添加如下配置:
~/.spring-boot-devtools.properties.
spring.devtools.reload.trigger-file=.reloadtrigger
20.4全局设置
110

20.5远程应用
SpringBoot开发者工具并不仅限于本地开发,在运行远程应用时你也可以使用一些
特性。远程支持是可选的,通过设置 spring.devtools.remote.secret属性可
以启用它,例如:
spring.devtools.remote.secret=mysecret
注在远程应用上启用 spring-boot-devtools有一定的安全风险,生产环境中最
好不要使用。
远程devtools支持分两部分:一个是接收连接的服务端端点,另一个是运行在IDE里
的客户端应用。如果设置 spring.devtools.remote.secret属性,服务端组件
会自动启用,客户端组件必须手动启动。
20.5远程应用
111

20.5.1运行远程客户端应用
远程客户端应用程序(remoteclientapplication)需要在IDE中运行,你需要使用
跟将要连接的远程应用相同的classpath运
行org.springframework.boot.devtools.RemoteSpringApplication,传参
为你要连接的远程应用URL。例如,你正在使用Eclipse或STS,并有一个部署到
CloudFoundry的my-app工程,远程连接该应用需要做以下操作:
从Run菜单选择 RunConfigurations…。
创建一个新的 JavaApplication启动配置(launchconfiguration)。
浏览 my-app工程。
将org.springframework.boot.devtools.RemoteSpringApplication作
为main类。
将https://myapp.cfapps.io作为参数传递
给RemoteSpringApplication(或其他任何远程URL)。
运行中的远程客户端看起来如下:
20.5远程应用
112

._____
____
/\\/___'_____(_)__________
\\\\
(()\___|'_|'_||'_\/_`||_\_________||_
___\\\\
\\/___)||_)|||||||(_|[]::::::[]/-_)'\/_\_/
-_)))))
'|____|.__|_||_|_||_\__,||_|_\___|_|_|_\___/\__\
___|////
=========|_|==============|___/================================
===/_/_/_/
::SpringBootRemote::1.4.1.RELEASE
2015-06-1018:25:06.632INFO14938---[main]o.s.b.
devtools.RemoteSpringApplication:StartingRemoteSpringApplic
ationonpwmbpwithPID14938(/Users/pwebb/projects/spring-boot
/code/spring-boot-devtools/target/classesstartedbypwebbin/U
sers/pwebb/projects/spring-boot/code/spring-boot-samples/spring-
boot-sample-devtools)
2015-06-1018:25:06.671INFO14938---[main]s.c.a.
AnnotationConfigApplicationContext:Refreshingorg.springframew
ork.context.annotation.AnnotationConfigApplicationContext@2a17b7
b6:startupdate[WedJun1018:25:06PDT2015];rootofcontext
hierarchy
2015-06-1018:25:07.043WARN14938---[main]o.s.b.
d.r.c.RemoteClientConfiguration:Theconnectiontohttp://lo
calhost:8080isinsecure.YoushoulduseaURLstartingwith'ht
tps://'.
2015-06-1018:25:07.074INFO14938---[main]o.s.b.
d.a.OptionalLiveReloadServer:LiveReloadserverisrunnin
gonport35729
2015-06-1018:25:07.130INFO14938---[main]o.s.b.
devtools.RemoteSpringApplication:StartedRemoteSpringApplica
tionin0.74seconds(JVMrunningfor1.105)
注因为远程客户端使用的classpath跟真实应用相同,所以它能直接读取应用配
置,这就是 spring.devtools.remote.secret如何被读取和传递给服务器做验
证的。
20.5远程应用
113

强烈建议使用 https://作为连接协议,这样传输通道是加密的,密码也不会被截
获。
如果需要使用代理连接远程应用,你需要配
置spring.devtools.remote.proxy.host和spring.devtools.remote.proxy
.port属性。
20.5远程应用
114

20.5.2远程更新
远程客户端将监听应用的classpath变化,任何更新的资源都会发布到远程应用,并
触发重启,这在你使用云服务迭代某个特性时非常有用。通常远程更新和重启比完
整rebuild和deploy快多了。
注文件只有在远程客户端运行时才监控。如果你在启动远程客户端之前改变一个文
件,它是不会被发布到远程server的。
20.5远程应用
115

20.5.3远程调试通道
Java的远程调试在诊断远程应用问题时很有用,不幸的是,当应用部署在你的数据
中心外时,它并不总能够启用远程调试。如果你使用基于容器的技术,比如
Docker,远程调试设置起来非常麻烦。
为了突破这些限制,devtools支持基于HTTP的远程调试通道。远程客户端在8000
端口提供一个本地server,这样远程debugger就可以连接了。一旦连接建立,调试
信息就通过HTTP发送到远程应用。你可以使
用spring.devtools.remote.debug.local-port属性设置不同的端口。
你需要确保远程应用启动时开启了远程调试功能,通常,这可以通过配
置JAVA_OPTS实现,例如,对于CloudFoundry,你可以将以下内容添加到
manifest.yml:
---
env:
JAVA_OPTS:"-Xdebug-Xrunjdwp:server=y,transport=dt_socket,s
uspend=n"
注注意你不需要传递一个 address=NNNN的配置项到 -Xrunjdwp,如果遗漏
了,java会使用一个随机可用端口。
调试基于Internet的远程服务可能很慢,你可能需要增加IDE的超时时间。例如,在
Eclipse中你可以从 Preferences…选择 Java-> Debug,改变 Debugger
timeout(ms)为更合适的值(60000在多数情况下就能解决)。
20.5远程应用
116

21.打包用于生产的应用
可执行jars可用于生产部署。由于它们是自包含的,非常适合基于云的部署。关于
其他“生产准备”的特性,比如健康监控,审计和指标REST,或JMX端点,可以考虑
添加 spring-boot-actuator。具体参考PartV,“SpringBootActuator:
Production-readyfeatures”。
20.5远程应用
117

23.SpringApplication
SpringApplication类提供了一种快捷方式,用于从 main()方法启动Spring应用。
多数情况下,你只需要将该任务委托给 SpringApplication.run静态方法:
publicstaticvoidmain(String[]args){
SpringApplication.run(MySpringConfiguration.class,args);
}
当应用启动时,你应该会看到类似下面的东西:
._________
/\\/___'_____(_)______\\\\
(()\___|'_|'_||'_\/_`|\\\\
\\/___)||_)|||||||(_||))))
'|____|.__|_||_|_||_\__,|////
=========|_|==============|___/=/_/_/_/
::SpringBoot::v1.4.1.RELEASE
2013-07-3100:08:16.117INFO56603---[main]o.s.b.
s.app.SampleApplication:StartingSampleApplication
v0.1.0onmycomputerwithPID56603(/apps/myapp.jarstartedby
pwebb)
2013-07-3100:08:16.166INFO56603---[main]ationC
onfigEmbeddedWebApplicationContext:Refreshingorg.springframew
ork.boot.context.embedded.AnnotationConfigEmbeddedWebApplication
Context@6e5a8246:startupdate[WedJul3100:08:16PDT2013];r
ootofcontexthierarchy
2014-03-0413:09:54.912INFO41370---[main].t.Tom
catEmbeddedServletContainerFactory:Serverinitializedwithpor
t:8080
2014-03-0413:09:56.501INFO41370---[main]o.s.b.
s.app.SampleApplication:StartedSampleApplicationi
n2.992seconds(JVMrunningfor3.658)
默认情况下会显示INFO级别的日志信息,包括一些相关的启动详情,比如启动应用
的用户等。
23.SpringApplication
120

23.SpringApplication
121

23.1启动失败
如果应用启动失败,注册的 FailureAnalyzers就有机会提供一个特定的错误信
息,及具体的解决该问题的动作。例如,如果在 8080端口启动一个web应用,而
该端口已被占用,那你应该可以看到类似如下的内容:
***************************
APPLICATIONFAILEDTOSTART
***************************
Description:
Embeddedservletcontainerfailedtostart.Port8080wasalread
yinuse.
Action:
Identifyandstoptheprocessthat'slisteningonport8080orc
onfigurethisapplicationtolistenonanotherport.
注SpringBoot提供很多的 FailureAnalyzer实现,你自己实现也很容易。
如果没有可用于处理该异常的失败分析器(failureanalyzers),你需要展示完整的
auto-configuration报告以便更好的查看出问题的地方,因此你需要启
用org.springframework.boot.autoconfigure.logging.AutoConfigurationR
eportLoggingInitializer的debug属性,或开启DEBUG日志级别。
例如,使用 java-jar运行应用时,你可以通过如下命令启用 debug属性:
$java-jarmyproject-0.0.1-SNAPSHOT.jar--debug
23.1启动失败
122

23.2.自定义Banner
通过在classpath下添加一个 banner.txt或设置 banner.location来指定相应
的文件可以改变启动过程中打印的banner。如果这个文件有特殊的编码,你可以使
用banner.encoding设置它(默认为UTF-8)。除了文本文件,你也可以添加一
个banner.gif,banner.jpg或banner.png图片,或设
置banner.image.location属性。图片会转换为字符画(ASCIIart)形式,并在
所有文本banner上方显示。
在banner.txt中可以使用如下占位符:
变量 描述
${application.version}
MANIFEST.MF中声明的应用版本号,例
如Implementation-Version:1.0会
打印 1.0
${application.formatted-version}
MANIFEST.MF中声明的被格式化后的应
用版本号(被括号包裹且以v作为前
缀),用于显示,例如(v1.0)
${spring-boot.version} 当前SpringBoot的版本号,例
如1.4.1.RELEASE
${spring-boot.formatted-version}
当前SpringBoot被格式化后的版本号
(被括号包裹且以v作为前缀),用于显
示,例如(v1.4.1.RELEASE)
${Ansi.NAME}(或
${AnsiColor.NAME},
${AnsiBackground.NAME},
${AnsiStyle.NAME})
NAME代表一种ANSI编码,具体详情查
看AnsiPropertySource
${application.title}
MANIFEST.MF中声明的应用title,例
如Implementation-Title:MyApp会
打印 MyApp
注如果想以编程的方式产生一个banner,可以使
用SpringBootApplication.setBanner(…)方法,并实
现org.springframework.boot.Banner接口的 printBanner()方法。
你也可以使用 spring.main.banner-mode属性决定将banner打印到何
处, System.out(console),配置的logger(log)或都不输出
(off)。
23.2.自定义Banner
123

打印的banner将注册成一个名为 springBootBanner的单例bean。
注YAML会将 off映射为 false,如果想在应用中禁用banner,你需要确
保off添加了括号:
spring:
main:
banner-mode:"off"
23.2.自定义Banner
124

23.3.自定义SpringApplication
如果默认的 SpringApplication不符合你的口味,你可以创建一个本地实例并对
它进行自定义。例如,想要关闭banner你可以这样写:
publicstaticvoidmain(String[]args){
SpringApplicationapp=newSpringApplication(MySpringConfig
uration.class);
app.setBannerMode(Banner.Mode.OFF);
app.run(args);
}
注:传递给 SpringApplication的构造器参数将作为springbeans的配置源,多
数情况下,它们是一些 @Configuration类的引用,但也可能是XML配置或要扫
描包的引用。
你也可以使用 application.properties文件来配置 SpringApplication,具
体参考24.Externalized配置,访问SpringApplicationJavadoc可获取完整的配置选
项列表.
23.3.自定义SpringApplication
125

23.4.流式构建API
如果需要创建一个分层的 ApplicationContext(多个具有父子关系的上下
文),或只是喜欢使用流式(fluent)构建API,那你可以使用
SpringApplicationBuilder。SpringApplicationBuilder允许你以链式方式调用多个方
法,包括parent和child方法,这样就可以创建多层次结构,例如:
newSpringApplicationBuilder()
.sources(Parent.class)
.child(Application.class)
.bannerMode(Banner.Mode.OFF)
.run(args);
注:创建ApplicationContext层次时有些限制,比如,Web组件必须包含在子上下文
中,并且父上下文和子上下文使用相同的Environment,具体参
考SpringApplicationBuilderjavadoc。
23.4.流式构建API
126

23.5.Application事件和监听器
除了常见的Spring框架事件,比如
ContextRefreshedEvent,SpringApplication也会发送其他的application事
件。
注有些事件实际上是在 ApplicationContext创建前触发的,所以你不能在那些
事件(处理类)中通过 @Bean注册监听器,只能通
过SpringApplication.addListeners(…)或SpringApplicationBuilder.lis
teners(…)方法注册。如果想让监听器自动注册,而不关心应用的创建方式,你可
以在工程中添加一个 META-INF/spring.factories文件,并使
用org.springframework.context.ApplicationListener作为key指向那些监
听器,如下:
org.springframework.context.ApplicationListener=com.example.proj
ect.MyListener
应用运行时,事件会以下面的次序发送:
1. 在运行开始,但除了监听器注册和初始化以外的任何处理之前,会发送一
个ApplicationStartedEvent。
2. 在Environment将被用于已知的上下文,但在上下文被创建前,会发送一
个ApplicationEnvironmentPreparedEvent。
3. 在refresh开始前,但在bean定义已被加载后,会发送一
个ApplicationPreparedEvent。
4. 在refresh之后,相关的回调处理完,会发送一个 ApplicationReadyEvent,
表示应用准备好接收请求了。
5. 启动过程中如果出现异常,会发送一个 ApplicationFailedEvent。
注通常不需要使用application事件,但知道它们的存在是有用的(在某些场合可能
会使用到),比如,在SpringBoot内部会使用事件处理各种任务。
23.5.Application事件和监听器
127

23.6.Web环境
SpringApplication将尝试为你创建正确类型的 ApplicationContext,默认
情况下,根据你开发的是否为web应用决定使
用AnnotationConfigApplicationContext或AnnotationConfigEmbeddedWeb
ApplicationContext。
用于确定是否为web环境的算法相当简单(判断是否存在某些类),你可以使
用setWebEnvironment(booleanwebEnvironment)覆盖默认行为。
通过调用 setApplicationContextClass(…),你可以完全控
制ApplicationContext的类型。
注在Junit测试中使用 SpringApplication,调
用setWebEnvironment(false)是很有意义的。
23.6.Web环境
128

23.7访问应用参数
如果需要获取传递给 SpringApplication.run(…)的应用参数,你可以注入一
个org.springframework.boot.ApplicationArguments类型的
bean。ApplicationArguments接口即提供对原始 String[]参数的访问,也提
供对解析成 option和non-option参数的访问:
importorg.springframework.boot.*
importorg.springframework.beans.factory.annotation.*
importorg.springframework.stereotype.*
@Component
publicclassMyBean{
@Autowired
publicMyBean(ApplicationArgumentsargs){
booleandebug=args.containsOption("debug");
List<String>files=args.getNonOptionArgs();
//ifrunwith"--debuglogfile.txt"debug=true,files=[
"logfile.txt"]
}
}
注SpringBoot也会注册一个包含Spring Environment属性
的CommandLinePropertySource,这就允许你使用 @Value注解注入单个的应
用参数。
23.7访问应用参数
129

23.8.使用ApplicationRunner或
CommandLineRunner
如果需要在 SpringApplication启动后执行一些特殊的代码,你可以实
现ApplicationRunner或CommandLineRunner接口,这两个接口工作方式相
同,都只提供单一的 run方法,该方法仅在 SpringApplication.run(…)完成
之前调用。
CommandLineRunner接口能够访问string数组类型的应用参数,
而ApplicationRunner使用的是上面描述过的 ApplicationArguments接口:
importorg.springframework.boot.*
importorg.springframework.stereotype.*
@Component
publicclassMyBeanimplementsCommandLineRunner{
publicvoidrun(String...args){
//Dosomething...
}
}
如果某些定义的 CommandLineRunner或ApplicationRunnerbeans需要以特定
的顺序调用,你可以实现 org.springframework.core.Ordered接口或使
用org.springframework.core.annotation.Order注解。
23.8.使用ApplicationRunner或CommandLineRunner
130

23.9Application退出
为确保 ApplicationContext在退出时被平静的(gracefully)关闭,每
个SpringApplication都会注册一个JVM的shutdown钩子,所有标准的Spring生
命周期回调(比如 DisposableBean接口或 @PreDestroy注解)都能使用。
此外,如果想在应用结束时返回特定的退出码(exitcode),这些beans可以实
现org.springframework.boot.ExitCodeGenerator接口。
23.9Application退出
131

24.外部化配置
SpringBoot允许将配置外部化(externalize),这样你就能够在不同的环境下使用
相同的代码。你可以使用properties文件,YAML文件,环境变量和命令行参数来外
部化配置。使用@Value注解,可以直接将属性值注入到beans中,然后通过Spring
的Environment抽象或通过 @ConfigurationProperties绑定到结构化对象来
访问。
SpringBoot设计了一个非常特别的 PropertySource顺序,以允许对属性值进行
合理的覆盖,属性会以如下的顺序进行设值:
1. home目录下的devtools全局设置属性(~/.spring-boot-
devtools.properties,如果devtools激活)。
2. 测试用例上的@TestPropertySource注解。
3. 测试用例上的@SpringBootTest#properties注解。
4. 命令行参数
5. 来自 SPRING_APPLICATION_JSON的属性(环境变量或系统属性中内嵌的内联
JSON)。
6. ServletConfig初始化参数。
7. ServletContext初始化参数。
8. 来自于 java:comp/env的JNDI属性。
9. Java系统属性(System.getProperties())。
10. 操作系统环境变量。
11. RandomValuePropertySource,只包含 random.*中的属性。
12. 没有打进jar包的Profile-specific应用属性(application-
{profile}.properties和YAML变量)。
13. 打进jar包中的Profile-specific应用属性(application-
{profile}.properties和YAML变量)。
14. 没有打进jar包的应用配置( application.properties和YAML变量)。
15. 打进jar包中的应用配置( application.properties和YAML变量)。
16. @Configuration类上的 @PropertySource注解。
17. 默认属性(使用 SpringApplication.setDefaultProperties指定)。
下面是具体的示例,假设你开发一个使用name属性的 @Component:
24.外化配置
132

importorg.springframework.stereotype.*
importorg.springframework.beans.factory.annotation.*
@Component
publicclassMyBean{
@Value("${name}")
privateStringname;
//...
}
你可以将一个 application.properties放到应用的classpath下,为 name提供
一个合适的默认属性值。当在新的环境中运行时,可以在jar包外提供一
个application.properties覆盖 name属性。对于一次性的测试,你可以使用
特定的命令行开关启动应用(比如, java-jarapp.jar--
name="Spring")。
注SPRING_APPLICATION_JSON属性可以通过命令行的环境变量设置,例如,在
一个UNIXshell中可以这样:
$SPRING_APPLICATION_JSON='{"foo":{"bar":"spam"}}'java-jarmya
pp.jar
本示例中,如果是Spring Environment,你可以以 foo.bar=spam结尾;如果
在一个系统变量中,可以提供作为 spring.application.json的JSON字符串:
$java-Dspring.application.json='{"foo":"bar"}'-jarmyapp.jar
或命令行参数:
$java-jarmyapp.jar--spring.application.json='{"foo":"bar"}'
或作为一个JNDI变量 java:comp/env/spring.application.json。
24.外化配置
133

24.1.配置随机值
在注入随机值(比如,密钥或测试用例)时 RandomValuePropertySource很有
用,它能产生整数,longs或字符串,比如:
my.secret=${random.value}
my.number=${random.int}
my.bignumber=${random.long}
my.number.less.than.ten=${random.int(10)}
my.number.in.range=${random.int[1024,65536]}
random.int*语法是 OPENvalue(,max)CLOSE,此处 OPEN,CLOSE可以是
任何字符,并且 value,max是整数。如果提供 max,那么 value是最小
值, max是最大值(不包含在内)。
24.1.配置随机值
134

24.2.访问命令行属性
默认情况下, SpringApplication会将所有命令行配置参数(以'--'开头,比如 -
-server.port=9000)转化成一个 property,并将其添加到Spring
Environment中。正如以上章节提过的,命令行属性总是优先于其他属性源。
如果不想将命令行属性添加到 Environment,你可以使
用SpringApplication.setAddCommandLineProperties(false)来禁用它们。
24.2.访问命令行属性
135

24.3.Application属性文件
SpringApplication将从以下位置加载 application.properties文件,并把
它们添加到Spring Environment中:
1. 当前目录下的 /config子目录。
2. 当前目录。
3. classpath下的 /config包。
4. classpath根路径(root)。
该列表是按优先级排序的(列表中位置高的路径下定义的属性将覆盖位置低的)。
注你可以使用YAML('.yml')文件替代'.properties'。
如果不喜欢将 application.properties作为配置文件名,你可以通过指
定spring.config.name环境属性来切换其他的名称,也可以使
用spring.config.location环境属性引用一个明确的路径(目录位置或文件路
径列表以逗号分割)。
$java-jarmyproject.jar--spring.config.name=myproject
或
$java-jarmyproject.jar--spring.config.location=classpath:/de
fault.properties,classpath:/override.properties
注在初期需要根据 spring.config.name和spring.config.location决定加
载哪个文件,所以它们必须定义为environment属性(通常为OSenv,系统属性或
命令行参数)。
如果 spring.config.location包含目录(相对于文件),那它们应该以 /结尾
(在被加载前, spring.config.name关联的名称将被追加到后面,包括profile-
specific的文件名)。 spring.config.location下定义的文件使用方法跟往常一
样,没有profile-specific变量支持的属性,将被profile-specific的属性覆盖。
24.3.Application属性文件
136

不管 spring.config.location配置什么值,默认总会按
照classpath:,classpath:/config,file:,file:config/的顺序进行搜索,优
先级由低到高,也就是 file:config/获胜。如果你指定自己的位置,它们会优
先于所有的默认位置(locations),并使用相同的由低到高的优先级顺序。那样,
你就可以在 application.properties为应用设置默认值,然后在运行的时候使
用不同的文件覆盖它,同时保留默认配置。
注如果使用环境变量而不是系统属性,需要注意多数操作系统的key名称不允许以
句号分割(period-separated),但你可以使用下划线(underscores)代替(比
如,使用 SPRING_CONFIG_NAME代替 spring.config.name)。
注如果应用运行在容器中,那么JNDI属性(java:comp/env)或servlet上下文初始
化参数可以用来代替环境变量或系统属性,当然也可以使用环境变量或系统属性。
24.3.Application属性文件
137

24.4.Profile-specific属性
除了 application.properties文件,profile-specific属性也能通过命名惯
例application-{profile}.properties定义。 Environment(Spring的环境
抽象接口)有个默认profiles集合(默认情况为 [default]),在没有设置激活的
profiles时会被使用(例如,如果没有明确指定激活的profiles,application-
default.properties中的属性会被加载)。
Profile-specific属性加载路径和标准的 application.properties相同,并且
profile-specific文件总是会覆盖non-specific文件,不管profile-specific文件是否被打
包到jar中。
如果定义多个profiles,最后一个将获胜。例如, spring.profiles.active定义
的profiles被添加到通过 SpringApplicationAPI定义的profiles后面,因此优先级
更高。
注如果你已经在 spring.config.location下定义所有文件(非目录),那些
profile-specific的文件将不被考虑。如果想使用profile-specific属性,那就
在spring.config.location下使用目录。
24.4.Profile-specific属性
138

24.5.属性占位符
当使用 application.properties定义的属性时,Spring会先通过已经存在
的Environment查找该属性,所以你可以引用事先定义的值(比如,系统属
性):
app.name=MyApp
app.description=${app.name}isaSpringBootapplication
注你也可以使用该技巧为存在的SpringBoot属性创建'短'变量,具体参考Section
69.4,“Use‘short’commandlinearguments”。
24.5.属性占位符
139

24.6.1.加载YAML
Spring框架提供两个便利的类用于加载YAML文
档, YamlPropertiesFactoryBean会将YAML加载
为Properties,YamlMapFactoryBean会将YAML加载为 Map。
例如,下面的YAML文档:
environments:
dev:
url:http://dev.bar.com
name:DeveloperSetup
prod:
url:http://foo.bar.com
name:MyCoolApp
会被转化到这些属性:
environments.dev.url=http://dev.bar.com
environments.dev.name=DeveloperSetup
environments.prod.url=http://foo.bar.com
environments.prod.name=MyCoolApp
YAML列表被表示成使用 [index]间接引用作为属性keys的形式,例如下面的
YAML:
my:
servers:
-dev.bar.com
-foo.bar.com
将会转化到这些属性:
my.servers[0]=dev.bar.com
my.servers[1]=foo.bar.com
24.6.使用YAML代替Properties
141

使用Spring DataBinder工具集绑定这些属性(这
是@ConfigurationProperties做的事)时,你需要确保目标bean有
个java.util.List或Set类型的属性,并且需要提供一个setter或使用可变的
值初始化它,比如,下面的代码将绑定上面的属性:
@ConfigurationProperties(prefix="my")
publicclassConfig{
privateList<String>servers=newArrayList<String>();
publicList<String>getServers(){
returnthis.servers;
}
}
24.6.使用YAML代替Properties
142

24.6.2.在Spring环境中使用YAML暴露属性
YamlPropertySourceLoader类能够将YAML作为 PropertySource导出到Sprig
Environment,这允许你使用常用的 @Value注解配合占位符语法访问YAML属
性。
24.6.使用YAML代替Properties
143

24.6.3.Multi-profileYAML文档
你可以在单个文件中定义多个特定配置(profile-specific)的YAML文档,并通
过spring.profiles标示生效的文档,例如:
server:
address:192.168.1.100
---
spring:
profiles:development
server:
address:127.0.0.1
---
spring:
profiles:production
server:
address:192.168.1.120
在以上例子中,如果 developmentprofile被激活, server.address属性将
是127.0.0.1;如果 development和productionprofiles没有启用,则该属
性的值将是 192.168.1.100。
在应用上下文启动时,如果没有明确指定激活的profiles,则默认的profiles将生
效。所以,在下面的文档中我们为 security.user.password设置了一个值,该
值只在"default"profile中有效:
server:
port:8000
---
spring:
profiles:default
security:
user:
password:weak
然而,在这个示例中,由于没有关联任何profile,密码总是会设置,并且如果有必
要的话可以在其他profiles中显式重置:
24.6.使用YAML代替Properties
144

server:
port:8000
security:
user:
password:weak
通过 !可以对 spring.profiles指定的profiles进行取反(negated,跟java中
的!作用一样),如果negated和non-negatedprofiles都指定一个单一文件,至少
需要匹配一个non-negatedprofile,可能不会匹配任何negatedprofiles。
24.6.使用YAML代替Properties
145

24.6.4.YAML缺点
YAML文件不能通过 @PropertySource注解加载,如果需要使用该方式,那就必
须使用properties文件。
24.6.使用YAML代替Properties
146

24.6.5合并YAML列表
正如上面看到的,所有YAML最终都转换为properties,在通过一个profile覆
盖"list"属性时这个过程可能不够直观(counterintuitive)。例如,假设有一
个MyPojo对象,默认它的 name和description属性都为 null,下面我们
将从 FooProperties暴露一个 MyPojo对象列表(list):
@ConfigurationProperties("foo")
publicclassFooProperties{
privatefinalList<MyPojo>list=newArrayList<>();
publicList<MyPojo>getList(){
returnthis.list;
}
}
考虑如下配置:
foo:
list:
-name:myname
description:mydescription
---
spring:
profiles:dev
foo:
list:
-name:myanothername
如果 devprofile没有激活, FooProperties.list将包括一个如上述定义
的MyPojo实体,即使 dev生效,该 list仍旧只包含一个实体( name值
为myanothername,description值为 null)。此配置不会向该列表添加
第二个 MyPojo实例,也不会对该项进行合并。
当一个集合定义在多个profiles时,只使用优先级最高的:
24.6.使用YAML代替Properties
147

foo:
list:
-name:myname
description:mydescription
-name:anothername
description:anotherdescription
---
spring:
profiles:dev
foo:
list:
-name:myanothername
在以上示例中,如果 devprofile激活, FooProperties.list将包含一
个MyPojo实体( name值为 myanothername,description值
为null)。
24.6.使用YAML代替Properties
148

24.7.1.第三方配置
@ConfigurationProperties不仅可以注解在类上,也可以注解在public
@Bean方法上,当你需要为不受控的第三方组件绑定属性时,该方法将非常有
用。
为了从 Environment属性中配置一个bean,你需要使
用@ConfigurationProperties注解该bean:
@ConfigurationProperties(prefix="foo")
@Bean
publicFooComponentfooComponent(){
...
}
和上面 ConnectionSettings的示例方式相同,所有以 foo为前缀的属性定义都
会被映射到 FooComponent上。
24.6.使用YAML代替Properties
149

24.7.2.Relaxed绑定
SpringBoot将Environment属性绑定到 @ConfigurationPropertiesbeans时
会使用一些宽松的规则,所以 Environment属性名和bean属性名不需要精确匹
配。常见的示例中有用的包括虚线分割(比如, context-path绑定
到contextPath),将environment属性转为大写字母(比如, PORT绑
定port)。
例如,给定以下 @ConfigurationProperties类:
@ConfigurationProperties(prefix="person")
publicclassOwnerProperties{
privateStringfirstName;
publicStringgetFirstName(){
returnthis.firstName;
}
publicvoidsetFirstName(StringfirstName){
this.firstName=firstName;
}
}
下面的属性名都能使用:
属性 说明
person.firstName 标准驼峰规则
person.first-name 虚线表示,推荐用于 .properties和.yml文件中
person.first_name 下划线表示,用于 .properties和.yml文件的可
选格式
PERSON_FIRST_NAME 大写形式,使用系统环境变量时推荐
24.6.使用YAML代替Properties
150

24.7.3属性转换
将外部应用配置绑定到 @ConfigurationPropertiesbeans时,Spring会尝试将
属性强制转换为正确的类型。如果需要自定义类型转换器,你可以提供一
个ConversionServicebean(beanid为conversionService),或自定义属
性编辑器(通过 CustomEditorConfigurerbean),或自定
义Converters(bean定义时需要注
解@ConfigurationPropertiesBinding)。
注由于该bean在应用程序生命周期的早期就需要使用,所以确保限制你
的ConversionService使用的依赖。通常,在创建时期任何你需要的依赖可能都
没完全初始化。
24.6.使用YAML代替Properties
151

24.7.4.@ConfigurationProperties校验
SpringBoot将尝试校验外部配置,默认使用JSR-303(如果在classpath路径中),
你只需要将JSR-303 javax.validation约束注解添加
到@ConfigurationProperties类上:
@ConfigurationProperties(prefix="connection")
publicclassConnectionProperties{
@NotNull
privateInetAddressremoteAddress;
//...gettersandsetters
}
为了校验内嵌属性的值,你需要使用 @Valid注解关联的字段以触发它的校验,例
如:
24.6.使用YAML代替Properties
152

@ConfigurationProperties(prefix="connection")
publicclassConnectionProperties{
@NotNull
@Valid
privateRemoteAddressremoteAddress;
//...gettersandsetters
publicstaticclassRemoteAddress{
@NotEmpty
publicStringhostname;
//...gettersandsetters
}
}
你也可以通过创建一个叫做 configurationPropertiesValidator的bean来添加
自定义的Spring Validator。@Bean方法需要声明为 static,因为配置属性
校验器在应用程序生命周期中创建的比较早,将 @Bean方法声明为 static允许
该bean在创建时不需要实例化 @Configuration类,从而避免了早期实例化
(earlyinstantiation)的所有问题。相关的示例可以看这里。
注spring-boot-actuator模块包含一个暴露所
有@ConfigurationPropertiesbeans的端点(endpoint),通过浏览器打
开/configprops进行浏览,或使用等效的JMX端点,具体参考Productionready
features。
24.6.使用YAML代替Properties
153

24.7.5@ConfigurationPropertiesvs.@Value
@Value是Spring容器的一个核心特性,它没有提供跟type-safeConfiguration
Properties相同的特性。下面的表格总结
了@ConfigurationProperties和@Value支持的特性:
特性 @ConfigurationProperties @Value
Relaxed绑定 Yes No
Meta-data支持 Yes No
SpEL表达式 No Yes
如果你为自己的组件定义了一系列的配置keys,我们建议你将它们
以@ConfigurationProperties注解的POJO进行分组。由于 @Value不支持
relaxed绑定,所以如果你使用环境变量提供属性值的话,它就不是很好的选择。最
后,尽管 @Value可以写 SpEL表达式,但这些表达式不会处理来自Application属
性文件的属性。
24.6.使用YAML代替Properties
154

25.Profiles
SpringProfiles提供了一种隔离应用程序配置的方式,并让这些配置只在特定的环
境下生效。任何 @Component或@Configuration都能注解 @Profile,从而限
制加载它的时机:
@Configuration
@Profile("production")
publicclassProductionConfiguration{
//...
}
以正常的Spring方式,你可以使
用spring.profiles.active的Environment属性来指定哪个配置生效。你可
以使用通常的任何方式来指定该属性,例如,可以将它包含
到application.properties中:
spring.profiles.active=dev,hsqldb
或使用命令行开关:
--spring.profiles.active=dev,hsqldb
25.Profiles
155

25.1.添加激活的配置(profiles)
spring.profiles.active属性和其他属性一样都遵循相同的排列规则,优先级
最高的 PropertySource获胜,也就是说,你可以
在application.properties中指定生效的配置,然后使用命令行开关替换它
们。
有时,将profile-specific的属性添加到激活的配置中而不是直接替换它们是有好处
的。 spring.profiles.include属性可以用来无条件的添加激活的配置,
而SpringApplication的入口点也提供了一个用于设置其他配置的JavaAPI,通
过它设置的active配置优先级高于 spring.profiles.active,具体参
考setAdditionalProfiles()方法。
例如,当一个应用使用下面的属性,并用 --spring.profiles.active=prod开
关运行,那 proddb和prodmqprofiles也会激活:
---
my.property:fromyamlfile
---
spring.profiles:prod
spring.profiles.include:proddb,prodmq
注spring.profiles属性可以定义到YAML文档中,以决定何时将该文档包含进
配置,具体参考Section63.6,“Changeconfigurationdependingonthe
environment”
25.1.添加激活的profiles
156

25.2.以编程方式设置profiles
在应用运行前,你可以通过调
用SpringApplication.setAdditionalProfiles(…)方法,以编程的方式设置
激活的配置,也可以使用Spring的ConfigurableEnvironment接口激活配置
(profiles)。
25.2.以编程方式设置profiles
157

25.3.Profile-specific配置文件
Profile-specific的配置,不管
是application.properties(或 application.yml),还是通
过@ConfigurationProperties引用的文件都是被当作文件来加载的,具体参考
Section24.3,“Profilespecificproperties”。
25.3.Profile-specific配置文件
158

26.1.日志格式
SpringBoot默认的日志输出格式如下:
2014-03-0510:57:51.112INFO45469---[main]org.ap
ache.catalina.core.StandardEngine:StartingServletEngine:Ap
acheTomcat/7.0.52
2014-03-0510:57:51.253INFO45469---[ost-startStop-1]o.a.c.
c.C.[Tomcat].[localhost].[/]:InitializingSpringembedde
dWebApplicationContext
2014-03-0510:57:51.253INFO45469---[ost-startStop-1]o.s.we
b.context.ContextLoader:RootWebApplicationContext:
initializationcompletedin1358ms
2014-03-0510:57:51.698INFO45469---[ost-startStop-1]o.s.b.
c.e.ServletRegistrationBean:Mappingservlet:'dispatche
rServlet'to[/]
2014-03-0510:57:51.702INFO45469---[ost-startStop-1]o.s.b.
c.embedded.FilterRegistrationBean:Mappingfilter:'hiddenHttp
MethodFilter'to:[/*]
输出的节点(items)如下:
1. 日期和时间-精确到毫秒,且易于排序。
2. 日志级别- ERROR, WARN, INFO, DEBUG或TRACE。
3. ProcessID。
4. ---分隔符,用于区分实际日志信息开头。
5. 线程名-包括在方括号中(控制台输出可能会被截断)。
6. 日志名-通常是源class的类名(缩写)。
7. 日志信息。
注Logback没有 FATAL级别,它会映射到 ERROR。
26.1.日志格式
159

26.2.控制台输出
默认的日志配置会在写日志消息时将它们回显到控制台,级别为 ERROR,
WARN和INFO的消息会被记录。你可以在启动应用时,通过 --debug标识开启
控制台的 DEBUG级别日志记录,也可以在 application.properties中指
定debug=true。
$java-jarmyapp.jar--debug
当debug模式启用时,一系列核心loggers(内嵌容器,Hibernate,SpringBoot
等)记录的日志会变多,但不会输出所有的信息。
相应地,你可以在启动应用时,通过 --trace(或
在application.properties设置 trace=true)启用"trace"模式,该模式能够
追踪核心loggers(内嵌容器,Hibernate生成的schema,Spring全部的portfolio)
的所有日志信息。
26.2.控制台输出
160

26.2.1Color-coded输出
如果你的终端支持ANSI,SpringBoot将使用彩色编码(coloroutput)输出日志以
增强可读性,你可以将 spring.output.ansi.enabled设置为一个支持的值来覆
盖默认设置。
彩色编码(Colorcoding)使用 %clr表达式进行配置,在其最简单的形式中,转
换器会根据日志级别使用不同的颜色输出日志,例如:
%clr(%5p)
日志级别到颜色的映射如下:
Level Color
FATAL Red
ERROR Red
WARN Yellow
INFO Green
DEBUG Green
TRACE Green
另外,在转换时你可以设定日志展示的颜色或样式,例如,让文本显示成黄色:
%clr(%d{yyyy-MM-ddHH:mm:ss.SSS}){yellow}
支持的颜色,样式如下:
blue
cyan
faint
green
magenta
red
yellow
26.2.控制台输出
161

26.2.控制台输出
162

26.3.文件输出
默认情况下,SpringBoot只会将日志记录到控制台,而不写进日志文件,如果需
要,你可以设置 logging.file或logging.path属性(例
如application.properties)。
下表展示如何组合使用 logging.*:
logging.file logging.path 示例 描述
(none) (none) 只记录到控制台
Specificfile (none) my.log 写到特定的日志文件,名称可以是
精确的位置或相对于当前目录
(none) Specific
directory /var/log
写到特定目录下
的spring.log里,名称可以是精
确的位置或相对于当前目录
日志文件每达到10M就会被分割,跟控制台一样,默认记录 ERROR,
WARN和INFO级别的信息。
26.3.文件输出
163

26.4.日志级别
所有SpringBoot支持的日志系统都可以在Spring Environment中设置级别
(application.properties里也一样),设置格式为'logging.level.*=LEVEL',
其中 LEVEL是TRACE, DEBUG, INFO, WARN, ERROR, FATAL, OFF之
一:
以下是 application.properties示例:
logging.level.root=WARN
logging.level.org.springframework.web=DEBUG
logging.level.org.hibernate=ERROR
注默认情况,SpringBoot会重新映射Thymeleaf的INFO信息到 DEBUG级别,这
能减少标准日志输出的噪声。查看LevelRemappingAppender可以按自己的配置设
置映射。
26.4.日志级别
164

26.5.自定义日志配置
通过将相应的库添加到classpath可以激活各种日志系统,然后在classpath根目录
下提供合适的配置文件可以进一步定制日志系统,配置文件也可以通过Spring
Environment的logging.config属性指定。
使用 org.springframework.boot.logging.LoggingSystem系统属性可以强制
SpringBoot使用指定的日志系统,该属性值需要是 LoggingSystem实现类的全限
定名,如果值为 none,则彻底禁用SpringBoot的日志配置。
注由于日志初始化早于 ApplicationContext的创建,所以不可能通
过@PropertySources指定的Spring @Configuration文件控制日志,系统属性
和SpringBoot外部化配置可以正常工作。
以下文件会根据你选择的日志系统进行加载:
日志系统 定制配置
Logback logback-spring.xml,logback-
spring.groovy,logback.xml或logback.groovy
Log4j log4j.properties或log4j.xml
Log4j2 log4j2-spring.xml或log4j2.xml
JDK(JavaUtil
Logging) logging.properties
注如果可能的话,建议你使用 -spring变种形式定义日志配置(例如,使
用logback-spring.xml而不是 logback.xml)。如果你使用标准的配置路
径,Spring可能不能够完全控制日志初始化。
注JavaUtilLogging从可执行jar运行时会导致一些已知的类加载问题,我们建议尽
可能不使用它。
以下是从Spring Envrionment转换为Systemproperties的一些有助于定制的配置
属性:
26.5.自定义日志配置
165

SpringEnvironment SystemProperty 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
当前的处理进程
(process)ID(能
够找到,且还没
有用作OS环境
变量)
所有支持的日志系统在解析配置文件时都能获取系统属性的值,具体可以参
考spring-boot.jar中的默认配置。
注如果想在日志属性中使用占位符,你需要使用SpringBoot的语法,而不是底层
框架的语法。尤其是使用Logback时,你需要使用 :作为属性名和默认值的分隔
符,而不是 :-。
26.5.自定义日志配置
166

注通过覆盖 LOG_LEVEL_PATTERN(Logback对
应logging.pattern.level),你可以向日志中添加MDC和其他ad-hoc的内
容。例如,将该值设置为 logging.pattern.level=user:%X{user}%5p,则默
认日志格式将包含一个"user"的MDC实体,如果存在的话,比如:
2015-09-3012:30:04.031user:juergenINFO22174---[nio-8080-
exec-0]demo.Controller
Handlingauthenticatedrequest
26.5.自定义日志配置
167

26.6Logback扩展
SpringBoot包含很多有用的Logback扩展,你可以在 logback-spring.xml配置
文件中使用它们。
注你不能在标准的 logback.xml配置文件中使用扩展,因为它加载的太早了,不
过可以使用 logback-spring.xml,或指定 logging.config属性。
26.6Logback扩展
168

26.6.1Profile-specific配置
<springProfile>标签可用于根据激活的Springprofiles,选择性的包含或排除
配置片段。Profile片段可以放在 <configuration>元素内的任何地方,使
用name属性定义哪些profile接受该配置,多个profiles以逗号分隔。
<springProfilename="staging">
<!--configurationtobeenabledwhenthe"staging"profile
isactive-->
</springProfile>
<springProfilename="dev,staging">
<!--configurationtobeenabledwhenthe"dev"or"staging"
profilesareactive-->
</springProfile>
<springProfilename="!production">
<!--configurationtobeenabledwhenthe"production"profi
leisnotactive-->
</springProfile>
26.6Logback扩展
169

26.6.2Environment属性
<springProperty>标签允许你从Spring Environment读取属性,以便在
Logback中使用。如果你想在logback配置获取 application.properties中的属
性值,该功能就很有用。该标签工作方式跟Logback标准 <property>标签类似,
但不是直接指定 value值,你需要定义属性的 source(来
自Environment),也可以指定存储属性作用域的 scope。如
果Environment没有相应属性,你可以通过 defaultValue设置默认值。
<springPropertyscope="context"name="fluentHost"source="myapp.
fluentd.host"
defaultValue="localhost"/>
<appendername="FLUENT"class="ch.qos.logback.more.appenders.Dat
aFluentAppender">
<remoteHost>${fluentHost}</remoteHost>
...
</appender>
注RelaxedPropertyResolver用于获取 Environment属性,如果以中划线的
方式指定 source(my-property-name),则所有relaxed变体都会进行尝试
(myPropertyName,MY_PROPERTY_NAME等)。
26.6Logback扩展
170

27.1.SpringWebMVC框架
SpringWebMVC框架(通常简称为"SpringMVC")是一个富“模型,视图,控制
器”web框架,允许用户创建特定的 @Controller或@RestControllerbeans
来处理传入的HTTP请求,通过 @RequestMapping注解可以将控制器中的方法映
射到相应的HTTP请求。
示例:
@RestController
@RequestMapping(value="/users")
publicclassMyRestController{
@RequestMapping(value="/{user}",method=RequestMethod.GET)
publicUsergetUser(@PathVariableLonguser){
//...
}
@RequestMapping(value="/{user}/customers",method=RequestMet
hod.GET)
List<Customer>getUserCustomers(@PathVariableLonguser){
//...
}
@RequestMapping(value="/{user}",method=RequestMethod.DELETE
)
publicUserdeleteUser(@PathVariableLonguser){
//...
}
}
SpringMVC是Spring框架的核心部分,详细信息可以参考reference
documentation,spring.io/guides也有一些可用的指导覆盖SpringMVC。
27.1.SpringWebMVC框架
172

27.1.1.SpringMVC自动配置
SpringBoot为SpringMVC提供的auto-configuration适用于大多数应用,并在
Spring默认功能上添加了以下特性:
1. 引入 ContentNegotiatingViewResolver和BeanNameViewResolver
beans。
2. 对静态资源的支持,包括对WebJars的支持。
3. 自动注册 Converter,GenericConverter,Formatterbeans。
4. 对HttpMessageConverters的支持。
5. 自动注册 MessageCodeResolver。
6. 对静态 index.html的支持。
7. 对自定义 Favicon的支持。
8. 自动使用 ConfigurableWebBindingInitializerbean。
如果保留SpringBootMVC特性,你只需添加其他的MVC配置(拦截器,格式化处
理器,视图控制器等)。你可以添加自己的 WebMvcConfigurerAdapter类型
的@Configuration类,而不需要注解 @EnableWebMvc。如果希望使用自定义
的RequestMappingHandlerMapping,RequestMappingHandlerAdapter,
或ExceptionHandlerExceptionResolver,你可以声明一
个WebMvcRegistrationsAdapter实例提供这些组件。
如果想全面控制SpringMVC,你可以添加自己的 @Configuration,并使
用@EnableWebMvc注解。
27.1.SpringWebMVC框架
173

27.1.2.HttpMessageConverters
SpringMVC使用 HttpMessageConverter接口转换HTTP请求和响应,合适的默
认配置可以开箱即用,例如对象自动转换为JSON(使用Jackson库)或XML(如果
JacksonXML扩展可用,否则使用JAXB),字符串默认使用 UTF-8编码。
可以使用SpringBoot的HttpMessageConverters类添加或自定义转换类:
importorg.springframework.boot.autoconfigure.web.HttpMessageCon
verters;
importorg.springframework.context.annotation.*;
importorg.springframework.http.converter.*;
@Configuration
publicclassMyConfiguration{
@Bean
publicHttpMessageConverterscustomConverters(){
HttpMessageConverter<?>additional=...
HttpMessageConverter<?>another=...
returnnewHttpMessageConverters(additional,another);
}
}
上下文中出现的所有 HttpMessageConverterbean都将添加到converters列表,
你可以通过这种方式覆盖默认的转换器列表(converters)。
27.1.SpringWebMVC框架
174

27.1.4MessageCodesResolver
SpringMVC有一个实现策略,用于从绑定的errors产生用来渲染错误信息的错误
码: MessageCodesResolver。SpringBoot会自动为你创建该实现,只要设
置spring.mvc.message-codes-resolver.format属性
为PREFIX_ERROR_CODE或POSTFIX_ERROR_CODE(具体查
看DefaultMessageCodesResolver.Format枚举值)。
27.1.SpringWebMVC框架
176

27.1.5静态内容
默认情况下,SpringBoot从classpath下
的/static(/public,/resources或/META-INF/resources)文件夹,
或从 ServletContext根目录提供静态内容。这是通过SpringMVC
的ResourceHttpRequestHandler实现的,你可以自定
义WebMvcConfigurerAdapter并覆写 addResourceHandlers方法来改变该行
为(加载静态文件)。
在单机web应用中,容器会启动默认的servlet,并用它加载 ServletContext根目
录下的内容以响应那些Spring不处理的请求。大多数情况下这都不会发生(除非你
修改默认的MVC配置),因为Spring总能够通过 DispatcherServlet处理这些请
求。
你可以设置 spring.resources.staticLocations属性自定义静态资源的位置
(配置一系列目录位置代替默认的值),如果你这样做,默认的欢迎页面将从自定
义位置加载,所以只要这些路径中的任何地方有一个 index.html,它都会成为
应用的主页。
此外,除了上述标准的静态资源位置,有个例外情况是Webjars内容。任何
在/webjars/**路径下的资源都将从jar文件中提供,只要它们以Webjars的格式
打包。
注如果你的应用将被打包成jar,那就不要使用 src/main/webapp文件夹。尽管
该文件夹是通常的标准格式,但它仅在打包成war的情况下起作用,在打包成jar
时,多数构建工具都会默认忽略它。
SpringBoot也支持SpringMVC提供的高级资源处理特性,可用于清除缓存的静态
资源或对WebJar使用版本无感知的URLs。
如果想使用针对WebJars版本无感知的URLs(versionagnostic),只需要添
加webjars-locator依赖,然后声明你的Webjar。以jQuery为
例, "/webjars/jquery/dist/jquery.min.js"实际
为"/webjars/jquery/x.y.z/dist/jquery.min.js",x.y.z为Webjar的版
本。
注如果使用JBoss,你需要声明 webjars-locator-jboss-vfs依赖而不
是webjars-locator,否则所有的Webjars将解析为 404。
27.1.SpringWebMVC框架
177

以下的配置为所有的静态资源提供一种缓存清除(cachebusting)方案,实际上是
将内容hash添加到URLs中,比如 <linkhref="/css/spring-
2a2d595e6ed9a0b24f027f2b63b134d6.css"/>:
spring.resources.chain.strategy.content.enabled=true
spring.resources.chain.strategy.content.paths=/**
注实现该功能的是 ResourceUrlEncodingFilter,它在模板运行期会重写资源
链接,Thymeleaf,Velocity和FreeMarker会自动配置该filter,JSP需要手动配置。
其他模板引擎还没自动支持,不过你可以使用ResourceUrlProvider自定义模块宏或
帮助类。
当使用比如JavaScript模块加载器动态加载资源时,重命名文件是不行的,这也是
提供其他策略并能结合使用的原因。下面是一个"fixed"策略,在URL中添加一个静
态version字符串而不需要改变文件名:
spring.resources.chain.strategy.content.enabled=true
spring.resources.chain.strategy.content.paths=/**
spring.resources.chain.strategy.fixed.enabled=true
spring.resources.chain.strategy.fixed.paths=/js/lib/
spring.resources.chain.strategy.fixed.version=v12
使用以上策略,JavaScript模块加载器加载 "/js/lib/"下的文件时会使用一个固
定的版本策略 "/v12/js/lib/mymodule.js",其他资源仍旧使用内容hash的方
式<linkhref="/css/spring-
2a2d595e6ed9a0b24f027f2b63b134d6.css"/>。查看ResourceProperties获取更
多支持的选项。
注该特性在一个专门的博文和Spring框架参考文档中有透彻描述。
27.1.SpringWebMVC框架
178

27.1.6ConfigurableWebBindingInitializer
SpringMVC使用 WebBindingInitializer为每个特殊的请求初始化相应
的WebDataBinder,如果你创建自己的 ConfigurableWebBindingInitializer
@Bean,SpringBoot会自动配置SpringMVC使用它。
27.1.SpringWebMVC框架
179

27.1.7模板引擎
正如RESTweb服务,你也可以使用SpringMVC提供动态HTML内容。SpringMVC
支持各种各样的模板技术,包括Velocity,FreeMarker和JSPs,很多其他的模板引
擎也提供它们自己的SpringMVC集成。
SpringBoot为以下的模板引擎提供自动配置支持:
1. FreeMarker
2. Groovy
3. Thymeleaf
4. Velocity(1.4已不再支持)
5. Mustache
注:由于在内嵌servlet容器中使用JSPs存在一些已知的限制,所以建议尽量不使用
它们。
使用以上引擎中的任何一种,并采用默认配置,则模块会
从src/main/resources/templates自动加载。
注:IntelliJIDEA根据你运行应用的方式会对classpath进行不同的排序。在IDE里通
过main方法运行应用,跟从Maven,或Gradle,或打包好的jar中运行相比会导致不
同的顺序,这可能导致SpringBoot不能从classpath下成功地找到模板。如果遇到
这个问题,你可以在IDE里重新对classpath进行排序,将模块的类和资源放到第一
位。或者,你可以配置模块的前缀为 classpath*:/templates/,这样会查找
classpath下的所有模板目录。
27.1.SpringWebMVC框架
180

27.1.8错误处理
SpringBoot默认提供一个 /error映射用来以合适的方式处理所有的错误,并将
它注册为servlet容器中全局的错误页面。对于机器客户端(相对于浏览器而言,浏
览器偏重于人的行为),它会产生一个具有详细错误,HTTP状态,异常信息的
JSON响应。对于浏览器客户端,它会产生一个白色标签样式(whitelabel)的错误
视图,该视图将以HTML格式显示同样的数据(可以添加一个解析为'error'的View来
自定义它)。为了完全替换默认的行为,你可以实现 ErrorController,并注册
一个该类型的bean定义,或简单地添加一个 ErrorAttributes类型的bean以使
用现存的机制,只是替换显示的内容。
注BasicErrorController可以作为自定义 ErrorController的基类,如果你
想添加对新contexttype的处理(默认处理 text/html),这会很有帮助。你只需
要继承 BasicErrorController,添加一个public方法,并注解带
有produces属性的 @RequestMapping,然后创建该新类型的bean。
你也可以定义一个 @ControllerAdvice去自定义某个特殊controller或exception
类型的JSON文档:
27.1.SpringWebMVC框架
181

@ControllerAdvice(basePackageClasses=FooController.class)
publicclassFooControllerAdviceextendsResponseEntityException
Handler{
@ExceptionHandler(YourException.class)
@ResponseBody
ResponseEntity<?>handleControllerException(HttpServletReque
strequest,Throwableex){
HttpStatusstatus=getStatus(request);
returnnewResponseEntity<>(newCustomErrorType(status.v
alue(),ex.getMessage()),status);
}
privateHttpStatusgetStatus(HttpServletRequestrequest){
IntegerstatusCode=(Integer)request.getAttribute("jav
ax.servlet.error.status_code");
if(statusCode==null){
returnHttpStatus.INTERNAL_SERVER_ERROR;
}
returnHttpStatus.valueOf(statusCode);
}
}
在以上示例中,如果跟 FooController相同package的某个controller抛
出YourException,一个 CustomerErrorType类型的POJO的json展示将代
替ErrorAttributes展示。
自定义错误页面
如果想为某个给定的状态码展示一个自定义的HTML错误页面,你需要将文件添加
到/error文件夹下。错误页面既可以是静态HTML(比如,任何静态资源文件夹
下添加的),也可以是使用模板构建的,文件名必须是明确的状态码或一系列标
签。
例如,映射 404到一个静态HTML文件,你的目录结构可能如下:
27.1.SpringWebMVC框架
182

src/
+-main/
+-java/
|+<sourcecode>
+-resources/
+-public/
+-error/
|+-404.html
+-<otherpublicassets>
使用FreeMarker模板映射所有 5xx错误,你需要如下的目录结构:
src/
+-main/
+-java/
|+<sourcecode>
+-resources/
+-templates/
+-error/
|+-5xx.ftl
+-<othertemplates>
对于更复杂的映射,你可以添加实现 ErrorViewResolver接口的beans:
publicclassMyErrorViewResolverimplementsErrorViewResolver{
@Override
publicModelAndViewresolveErrorView(HttpServletRequestrequ
est,
HttpStatusstatus,Map<String,Object>model){
//UsetherequestorstatustooptionallyreturnaMode
lAndView
return...
}
}
27.1.SpringWebMVC框架
183

你也可以使用SpringMVC特性,比如@ExceptionHandler方法和
@ControllerAdvice,ErrorController将处理所有未处理的异常。
映射SpringMVC以外的错误页面
对于不使用SpringMVC的应用,你可以通过 ErrorPageRegistrar接口直接注
册ErrorPages。该抽象直接工作于底层内嵌servlet容器,即使你没有Spring
MVC的DispatcherServlet,它们仍旧可以工作。
@Bean
publicErrorPageRegistrarerrorPageRegistrar(){
returnnewMyErrorPageRegistrar();
}
//...
privatestaticclassMyErrorPageRegistrarimplementsErrorPageRe
gistrar{
@Override
publicvoidregisterErrorPages(ErrorPageRegistryregistry){
registry.addErrorPages(newErrorPage(HttpStatus.BAD_REQU
EST,"/400"));
}
}
注.如果你注册一个 ErrorPage,该页面需要被一个 Filter处理(在一些非
Springweb框架中很常见,比如Jersey,Wicket),那么该 Filter需要明确注册
为一个 ERROR分发器(dispatcher),例如:
27.1.SpringWebMVC框架
184

@Bean
publicFilterRegistrationBeanmyFilter(){
FilterRegistrationBeanregistration=newFilterRegistration
Bean();
registration.setFilter(newMyFilter());
...
registration.setDispatcherTypes(EnumSet.allOf(DispatcherType
.class));
returnregistration;
}
(默认的 FilterRegistrationBean不包含 ERRORdispatcher类型)。
WebSphere应用服务器的错误处理
当部署到一个servlet容器时,SpringBoot通过它的错误页面过滤器将带有错误状态
的请求转发到恰当的错误页面。request只有在response还没提交时才能转发
(forwarded)到正确的错误页面,而WebSphere应用服务器8.0及后续版本默认情
况会在servlet方法成功执行后提交response,你需要设
置com.ibm.ws.webcontainer.invokeFlushAfterService属性为 false来关
闭该行为。
27.1.SpringWebMVC框架
185

27.1.9SpringHATEOAS
如果正在开发基于超媒体的RESTfulAPI,你可能需要SpringHATEOAS,而Spring
Boot会为其提供自动配置,这在大多数应用中都运作良好。自动配置取代
了@EnableHypermediaSupport,只需注册一定数量的beans就能轻松构建基于
超媒体的应用,这些beans包括 LinkDiscoverers(客户端支
持), ObjectMapper(用于将响应编排为想要的形式)。 ObjectMapper可以
根据 spring.jackson.*属性或 Jackson2ObjectMapperBuilderbean进行自
定义。
通过注解 @EnableHypermediaSupport,你可以控制SpringHATEOAS的配置,
但这会禁用上述 ObjectMapper的自定义功能。
27.1.SpringWebMVC框架
186

27.1.10CORS支持
跨域资源共享(CORS)是一个大多数浏览器都实现了的W3C标准,它允许你以灵
活的方式指定跨域请求如何被授权,而不是采用那些不安全,性能低的方式,比如
IFRAME或JSONP。
从4.2版本开始,SpringMVC对CORS提供开箱即用的支持。不用添加任何特殊配
置,只需要在SpringBoot应用的controller方法上注解 @CrossOrigin,并添加
CORS配置。通过注册一个自定义 addCorsMappings(CorsRegistry)方法
的WebMvcConfigurerbean可以指定全局CORS配置:
@Configuration
publicclassMyConfiguration{
@Bean
publicWebMvcConfigurercorsConfigurer(){
returnnewWebMvcConfigurerAdapter(){
@Override
publicvoidaddCorsMappings(CorsRegistryregistry){
registry.addMapping("/api/**");
}
};
}
}
27.1.SpringWebMVC框架
187

27.2JAX-RS和Jersey
如果你更喜欢JAX-RS为REST端点提供的编程模型,可以使用相应的实现代替
SpringMVC。如果将Jersey1.x和ApacheCXF的Servlet或Filter注册到应
用上下文中,那它们可以很好的工作。Spring对Jersey2.x有一些原生支持,所以
在SpringBoot中也为它提供了自动配置及一个starter。
想要使用Jersey2.x,只需添加 spring-boot-starter-jersey依赖,然后创建
一个 ResourceConfig类型的 @Bean,用于注册所有的端点(endpoints):
@Component
publicclassJerseyConfigextendsResourceConfig{
publicJerseyConfig(){
register(Endpoint.class);
}
}
你也可以注册任意数量的,实现 ResourceConfigCustomizer的beans来进一步
自定义。
所有注册的端点都需注解 @Components和HTTP资源annotations(比
如@GET):
@Component
@Path("/hello")
publicclassEndpoint{
@GET
publicStringmessage(){
return"Hello";
}
}
由于 Endpoint是一个Spring组件( @Component),所以它的生命周期受
Spring管理,你可以使用 @Autowired添加依赖,也可以使用 @Value注入外部
配置。Jersey的servlet会被注册,并默认映射到 /*,你可以
将@ApplicationPath添加到 ResourceConfig来改变该映射。
27.2JAX-RS和Jersey
188

默认情况下,Jersey将以Servlet的形式注册为一个 ServletRegistrationBean类
型的 @Bean,name为jerseyServletRegistration,该servlet默认会延迟初
始化,不过可以通过 spring.jersey.servlet.load-on-startup自定义。通过
创建相同name的bean,你可以禁用或覆盖框架默认产生的bean。设
置spring.jersey.type=filter可以使用Filter的形式代替Servlet,相应
的@Bean类型变为 jerseyFilterRegistration,该filter有一个 @Order属
性,你可以通过 spring.jersey.filter.order设置。Servlet和Filter注册时都可
以使用 spring.jersey.init.*定义一个属性集合传递给init参数。
这里有一个Jersey示例,你可以查看如何设置相关事项。
27.2JAX-RS和Jersey
189

27.3内嵌servlet容器支持
SpringBoot支持内嵌的Tomcat,Jetty和Undertow服务器,多数开发者只需要使用合
适的'Starter'来获取一个完全配置好的实例即可,内嵌服务器默认监听8080端口的
HTTP请求。
27.3内嵌servlet容器支持
190

27.3.1Servlets,Filters和listeners
使用内嵌servlet容器时,你可以通过使用Springbeans或扫描Servlet组件的方式注
册Servlets,Filters及特定Servlet相关的所有listeners(比
如HttpSessionListener)。
将Servlets,Filters和listeners注册为Springbeans
所有 Servlet,Filter或Servlet *Listener实例,只要是Springbean,都
会注册到内嵌容器中。如果想在配置期间引用 application.properties的属
性,这是非常方便的。默认情况下,如果上下文只包含单个Servlet,那它将被映射
到/。如果存在多个Servletbeans,那么bean的名称将被用作路径的前缀,过滤
器将映射到 /*。
如果基于约定(convention-based)的映射不够灵活,你可以使
用ServletRegistrationBean,FilterRegistrationBean,ServletListe
nerRegistrationBean实现完全的控制。
27.3内嵌servlet容器支持
191

27.3.2Servlet上下文初始化
内嵌servlet容器不会直接执行Servlet
3.0+的javax.servlet.ServletContainerInitializer接口,或Spring
的org.springframework.web.WebApplicationInitializer接口,这样设计的
目的是降低war包内运行的第三方库破坏SpringBoot应用的风险。
如果需要在SpringBoot应用中执行servlet上下文初始化,你需要注册一个实
现org.springframework.boot.context.embedded.ServletContextInitializ
er接口的bean。onStartup方法可以获取 ServletContext,如果需要的话可
以轻松用来适配一个已存在的 WebApplicationInitializer。
扫描Servlets,Filters和listeners
当使用一个内嵌容器时,通过 @ServletComponentScan可以启用对注
解@WebServlet,@WebFilter和@WebListener类的自动注册。
注在独立的容器(非内嵌)中 @ServletComponentScan不起作用,取为代之的
是容器内建的discovery机制。
27.3内嵌servlet容器支持
192

27.3.4自定义内嵌servlet容器
常见的Servlet容器配置可以通过Spring Environment进行设置,通常将这些属性
定义到 application.properties文件中。
常见的服务器配置包括:
1. 网络设置:监听进入Http请求的端口( server.port),接口绑定地
址server.address等。
2. Session设置:session是否持久化( server.session.persistence),
session超时时间( server.session.timeout),session数据存放位置
(server.session.store-dir),session-cookie配置
(server.session.cookie.*)。
3. Error管理:错误页面的位置( server.error.path)等。
4. SSL。
5. HTTP压缩
SpringBoot会尽量暴露常用设置,但这并不总是可能的。对于不可能的情况,可以
使用专用的命名空间提供server-specific配置(查
看server.tomcat,server.undertow)。例如,可以根据内嵌servlet容器的
特性对accesslogs进行不同的设置。
注具体参考ServerProperties。
编程方式的自定义
如果需要以编程方式配置内嵌servlet容器,你可以注册一个实
现EmbeddedServletContainerCustomizer接口的Spring
bean。EmbeddedServletContainerCustomizer能够获取到包含很多自定义
setter方法的 ConfigurableEmbeddedServletContainer,你可以通过这些setter
方法对内嵌容器自定义。
27.3内嵌servlet容器支持
193

importorg.springframework.boot.context.embedded.*;
importorg.springframework.stereotype.Component;
@Component
publicclassCustomizationBeanimplementsEmbeddedServletContain
erCustomizer{
@Override
publicvoidcustomize(ConfigurableEmbeddedServletContainerc
ontainer){
container.setPort(9000);
}
}
直接自定义ConfigurableEmbeddedServletContainer
如果以上自定义手法过于受限,你可以自己注
册TomcatEmbeddedServletContainerFactory,JettyEmbeddedServletCont
ainerFactory或UndertowEmbeddedServletContainerFactory。
@Bean
publicEmbeddedServletContainerFactoryservletContainer(){
TomcatEmbeddedServletContainerFactoryfactory=newTomcatEm
beddedServletContainerFactory();
factory.setPort(9000);
factory.setSessionTimeout(10,TimeUnit.MINUTES);
factory.addErrorPages(newErrorPage(HttpStatus.NOT_FOUND,"/
notfound.html");
returnfactory;
}
很多配置选项提供setter方法,有的甚至提供一些受保护的钩子方法以满足你的某
些特殊需求,具体参考源码或相关文档。
27.3内嵌servlet容器支持
194

28.安全
如果添加了SpringSecurity的依赖,那么web应用默认对所有的HTTP路径(也称为
终点,端点,表示API的具体网址)使用'basic'认证。为了给web应用添加方法级别
(method-level)的保护,你可以添加 @EnableGlobalMethodSecurity并使用想
要的设置,其他信息参考SpringSecurityReference。
默认的 AuthenticationManager只有一个用户('user'的用户名和随机密码会在
应用启动时以INFO日志级别打印出来),如下:
Usingdefaultsecuritypassword:78fa095d-3f4c-48b1-ad50-e24c31d
5cf35
注如果你对日志配置进行微调,确
保org.springframework.boot.autoconfigure.security类别记录日志级别
为INFO,否则默认的密码不会打印出来。
你可以通过设置 security.user.password改变默认密码,这些和其他有用的属
性通过SecurityProperties(以"security"为前缀的属性)被外部化了。
默认的安全配置是通
过SecurityAutoConfiguration,SpringBootWebSecurityConfiguration
(用于web安全), AuthenticationManagerConfiguration(可用于非web应
用的认证配置)进行管理的。你可以添加一个 @EnableWebSecuritybean来彻底
关掉SpringBoot的默认配置。为了对它进行自定义,你需要使用外部的属性配置
和WebSecurityConfigurerAdapter类型的beans(比如,添加基于表单的登
陆)。想要关闭认证管理的配置,你可以添加一个 AuthenticationManager类
型的bean,或在 @Configuration类的某个方法里注
入AuthenticationManagerBuilder来配置全局的 AuthenticationManager。
这里有一些安全相关的SpringBoot应用示例可以拿来参考。
在web应用中你能得到的开箱即用的基本特性如下:
1. 一个使用内存存储的 AuthenticationManagerbean和一个用户(查
看SecurityProperties.User获取user的属性)。
2. 忽略(不保护)常见的静态资源路径( /css/**,/js/**,
/images/**,/webjars/**和**/favicon.ico)。
28.安全
196

3. 对其他所有路径实施HTTPBasic安全保护。
4. 安全相关的事件会发布到Spring的ApplicationEventPublisher(成功和失
败的认证,拒绝访问)。
5. SpringSecurity提供的常见底层特性(HSTS,XSS,CSRF,缓存)默认都被开
启。
上述所有特性都能通过外部配置( security.*)打开,关闭,或修改。想要覆
盖访问规则而不改变其他自动配置的特性,你可以添加一个注
解@Order(SecurityProperties.ACCESS_OVERRIDE_ORDER)的WebSecurityCo
nfigurerAdapter类型的 @Bean。
注WebSecurityConfigurerAdapter默认会匹配所有路径,如果不想完全覆盖
SpringBoot自动配置的访问规则,你可以精确的配置想要覆盖的路径。
28.安全
197

28.1.1授权服务器
想要创建一个授权服务器,并授予accesstokens,你需要使
用@EnableAuthorizationServer,并提
供security.oauth2.client.client-
id和security.oauth2.client.client-secret配置。
按以上操作后,你就能使用客户端证书创建一个accesstoken,例如:
$curlclient:secret@localhost:8080/oauth/token-dgrant_type=pa
ssword-dusername=user-dpassword=pwd
/token端点basic形式的认证证书是 client-id和client-secret,用户证
书通常是SpringSecurity的user详情(SpringBoot中默认是"user"和一个随机的密
码)。
想要关闭自动配置,自己配置授权服务器特性,你只需添加一
个AuthorizationServerConfigurer类型的 @Bean。
28.1OAuth2
199

28.1.2资源服务器
为了使用accesstoken,你需要一个资源服务器(可以跟授权服务器是同一个)。
创建资源服务器很简单,只需要添加 @EnableResourceServer,提供一些配置以
允许服务器解码accesstoken。如果应用也是授权服务器,由于它知道如何去解码
tokens,所以也就不需要做其他事情。如果你的app是独立的服务,那你就需要给
它添加以下可选配置中的某一项:
security.oauth2.resource.user-info-uri用于 /me资源(例如,PWS
的https://uaa.run.pivotal.io/userinfo)。
security.oauth2.resource.token-info-uri用于token解码端点(例如,
PWS的https://uaa.run.pivotal.io/check_token)。
如果 user-info-uri和token-info-uri都指定了,你可以设置flag筛选出最想
要的那个(默认 prefer-token-info=true)。
另外,如果token是JWTs,你可以配置 security.oauth2.resource.jwt.key-
value解码它们(key是验签的key)。验签的键值可以是一个对称密钥,也可以是
PEM编码的RSA公钥。如果你没有key,并且它是公开的,你可以通
过security.oauth2.resource.jwt.key-uri提供一个下载URI(有一
个"value"字段的JSON对象),例如,在PWS平台上:
$curlhttps://uaa.run.pivotal.io/token_key
{"alg":"SHA256withRSA","value":"-----BEGINPUBLICKEY-----\nMIIB
I...\n-----ENDPUBLICKEY-----\n"}
注如果你使用 security.oauth2.resource.jwt.key-uri,授权服务器需要在
应用启动时也运行起来,如果找不到key,它将输出warning,并告诉你如何解决。
28.1OAuth2
200

28.2UserInfo中的Token类型
Google和其他一些第三方身份(identity)提供商对发送给userinfo端点的请求头中
设置的token类型名有严格要求。默认的 Bearer满足大多数提供商要求,如果需
要你可以设置 security.oauth2.resource.token-type来改变它。
28.2UserInfo中的Token类型
201

28.3自定义UserInfoRestTemplate
如果设置了 user-info-uri,资源服务器在内部将使用一
个OAuth2RestTemplate抓取用于认证的用户信息,这是一个id
为userInfoRestTemplate的@Bean提供的,但你不需要了解这些,只需要用
它即可。默认适用于大多数提供商,但偶尔你可能需要添加其他interceptors,或改
变request的验证器(authenticator)。想要添加自定义,只需创建一
个UserInfoRestTemplateCustomizer类型的bean——它只有单个方法,在
bean创建后,初始化前会调用该方法。此处自定义的resttemplate仅用于内部执行
认证。
注在YAML中设置RSAkey时,需要使用管道符分割多行(“|”),记得缩进key
value,例如:
security:
oauth2:
resource:
jwt:
keyValue:|
-----BEGINPUBLICKEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC...
-----ENDPUBLICKEY-----
28.3自定义UserInfoRestTemplate
202

28.3.1客户端
为了将web-app放入一个OAuth2客户端,你只需注解 @EnableOAuth2Client,
SpringBoot会创
建OAuth2ClientContext和OAuth2ProtectedResourceDetails,这些是创
建OAuth2RestOperations必需的。SpringBoot不会自动创建该bean,但你自己
创建也不费力:
@Bean
publicOAuth2RestTemplateoauth2RestTemplate(OAuth2ClientContext
oauth2ClientContext,
OAuth2ProtectedResourceDetailsdetails){
returnnewOAuth2RestTemplate(details,oauth2ClientContext);
}
注你可能想添加一个限定名(qualifier),因为应用中可能定义多
个RestTemplate。
该配置使用 security.oauth2.client.*作为证书(跟授权服务器使用的相
同),此外,它也需要知道授权服务器中认证和token的URIs,例如:
security:
oauth2:
client:
clientId:bd1c0a783ccdd1c9b9e4
clientSecret:1a9030fbca47a5b2c28e92f19050bb77824b5a
d1
accessTokenUri:https://github.com/login/oauth/acces
s_token
userAuthorizationUri:https://github.com/login/oauth
/authorize
clientAuthenticationScheme:form
具有该配置的应用在使用 OAuth2RestTemplate时会重定向到GitHub以完成授
权,如果已经登陆GitHub,你甚至不会注意到它已经授权过了。那些特殊的凭证
(credentials)只在应用运行于8080端口时有效(为了更灵活,在GitHub或其他提
28.3自定义UserInfoRestTemplate
203

供商上注册自己的客户端app)。
在客户端获取accesstoken时,你可以设
置security.oauth2.client.scope(逗号分隔或一个YAML数组)来限制它请
求的作用域(scope)。作用域默认是空的,默认值取决于授权服务器,通常依赖
于它拥有的客户端在注册时的设置。
注对security.oauth2.client.client-authentication-scheme也有设置,
默认为"header"(如果你的OAuth2提供商不喜欢header认证,例如Github,你可能
需要将它设置为“form”)。实际上, security.oauth2.client.*属性绑定到一
个AuthorizationCodeResourceDetails实例,所以它的所有属性都可以指定。
注在一个非web应用中,你仍旧可以创建一个 OAuth2RestOperations,并且
跟security.oauth2.client.*配置关联。在这种情况下,它是一个“client
credentialstokengrant”,如果你使用它的话就需要获取(此处不需要注
解@EnableOAuth2Client或@EnableOAuth2Sso)。为了防止基础设施定义,
只需要将 security.oauth2.client.client-id从配置中移除(或将它设为空字
符串)。
28.3自定义UserInfoRestTemplate
204

28.3.2单点登陆
OAuth2客户端可用于从提供商抓取用户详情,然后转换为SpringSecurity需要
的Authenticationtoken。上述提到的资源服务器通过 user-info-uri属性来
支持该功能,这是基于OAuth2的单点登陆(SSO)协议最基本的,SpringBoot提
供的 @EnableOAuth2Sso注解让它更容易实践。通过添加该注解及端点配置
(security.oauth2.client.*),Github客户端就可以使用 /user/端点保护
它的所有资源了:
security:
oauth2:
...
resource:
userInfoUri:https://api.github.com/user
preferTokenInfo:false
由于所有路径默认都处于保护下,也就没有主页展示那些未授权的用户,进而邀请
他们去登陆(通过访问 /login路径,或 security.oauth2.sso.login-path指
定的路径)。
为了自定义访问规则或保护的路径(这样你就可以添加主页),你可以
将@EnableOAuth2Sso添加到一个 WebSecurityConfigurerAdapter,该注解
会包装它,增强需要的地方以使 /login路径工作。例如,这里我们允许未授权的
用户访问主页 /,其他的依旧保持默认:
28.3自定义UserInfoRestTemplate
205

@Configuration
publicclassWebSecurityConfigurationextendsWebSecurityConfigu
rerAdapter{
@Override
publicvoidinit(WebSecurityweb){
web.ignore("/");
}
@Override
protectedvoidconfigure(HttpSecurityhttp)throwsException
{
http.antMatcher("/**").authorizeRequests().anyRequest().
authenticated();
}
}
28.3自定义UserInfoRestTemplate
206

28.4Actuator安全
如果Actuator处于使用中,你会发现:
管理的端点是安全的,即使应用端点不安全。
Security事件转换为 AuditEvents,并发布到 AuditService。
默认用户有 ADMIN,USER角色。
Actuator的安全特性可以通过外部配置属性( management.security.*)进行修
改。为了覆盖应用访问规则但不覆盖actuator的访问规则,你可以添加一
个WebSecurityConfigurerAdapter类型的 @Bean,并注
解@Order(SecurityProperties.ACCESS_OVERRIDE_ORDER),如果想覆盖
actuator访问规则,则注
解@Order(ManagementServerProperties.ACCESS_OVERRIDE_ORDER)。
28.4Actuator安全
207

29.使用SQL数据库
Spring框架为使用SQL数据库提供了广泛支持,从使用 JdbcTemplate直接访问
JDBC到完全的‘对象关系映射’技术,比如Hibernate。SpringData提供了更高级的
功能,直接从接口创建 Repository实现,并根据约定从方法名生成查询。
29.使用SQL数据库
208

29.1.配置DataSource
Java的javax.sql.DataSource接口提供了一个标准的使用数据库连接的方法。
通常,DataSource使用 URL和相应的凭证去初始化数据库连接。
29.1.配置DataSource
209

29.1.1.对内嵌数据库的支持
开发应用时使用内存数据库是很方便的。显然,内存数据库不提供持久化存储;你
只需要在应用启动时填充数据库,在应用结束前预先清除数据。
SpringBoot可以自动配置的内嵌数据库包括H2,HSQL和Derby。你不需要提供任
何连接URLs,只需要添加你想使用的内嵌数据库依赖。
示例:典型的POM依赖如下:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.hsqldb</groupId>
<artifactId>hsqldb</artifactId>
<scope>runtime</scope>
</dependency>
注对于自动配置的内嵌数据库,你需要添加 spring-jdbc依赖,在本示例
中, spring-boot-starter-data-jpa已包含该依赖了。
注无论出于什么原因,你需要配置内嵌数据库的连接URL,一定要确保数据库的自
动关闭是禁用的。如果使用H2,你需要设置 DB_CLOSE_ON_EXIT=FALSE。如果使
用HSQLDB,你需要确保没使用 shutdown=true。禁用数据库的自动关闭可以让
SpringBoot控制何时关闭数据库,因此在数据库不需要时可以确保关闭只发生一
次。
29.1.配置DataSource
210

29.1.2.连接生产环境数据库
生产环境的数据库连接可以通过池化的 DataSource进行自动配置,下面是选取
特定实现的算法:
出于tomcat数据源连接池的优秀性能和并发,如果可用总会优先使用它。
如果HikariCP可用,我们将使用它。
如果CommonsDBCP可用,我们将使用它,但生产环境不推荐。
最后,如果CommonsDBCP2可用,我们将使用它。
如果使用 spring-boot-starter-jdbc或spring-boot-starter-data-jpa
'starters',你会自动添加 tomcat-jdbc依赖。
注通过指定 spring.datasource.type属性,你可以完全抛弃该算法,然后指定
数据库连接池。如果你在tomcat容器中运行应用,由于默认提供 tomcat-jdbc,
这就很重要了。
注其他的连接池可以手动配置,如果你定义自己的 DataSourcebean,自动配置
是不会发生的。
DataSource配置被外部的 spring.datasource.*属性控制,例如,你可能会
在application.properties中声明以下片段:
spring.datasource.url=jdbc:mysql://localhost/test
spring.datasource.username=dbuser
spring.datasource.password=dbpass
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
注你应该至少使用 spring.datasource.url属性指定url,或SpringBoot尝试自
动配置内嵌数据库。
注你经常不需要指定 driver-class-name,因为Springboot可以从 url推断大
部分数据库。
注对于将要创建的池化 DataSource,我们需要验证是否有一个可用
的Driver,所以在做其他事前会校验它。比如,如果你设
置spring.datasource.driver-class-name=com.mysql.jdbc.Driver,然后
该class加载出来,否则就会出错。
29.1.配置DataSource
211

其他可选配置可以查看DataSourceProperties,有些标准配置是跟实现无关的,对
于实现相关的配置可以通过相应前缀进行设置
(spring.datasource.tomcat.*,spring.datasource.hikari.*,sprin
g.datasource.dbcp.*和spring.datasource.dbcp2.*),具体参考你使用的
连接池文档。
例如,如果正在使用Tomcat连接池,你可以自定义很多其他设置:
#Numberofmstowaitbeforethrowinganexceptionifnoconnec
tionisavailable.
spring.datasource.tomcat.max-wait=10000
#Maximumnumberofactiveconnectionsthatcanbeallocatedfro
mthispoolatthesametime.
spring.datasource.tomcat.max-active=50
#Validatetheconnectionbeforeborrowingitfromthepool.
spring.datasource.tomcat.test-on-borrow=true
29.1.配置DataSource
212

29.1.3.连接JNDI数据库
如果正在将SpringBoot应用部署到一个应用服务器,你可能想要用应用服务器内建
的特性来配置和管理你的DataSource,并使用JNDI访问它。
spring.datasource.jndi-name属性可用来替
代spring.datasource.url,spring.datasource.username和spring.dat
asource.password去从一个特定的JNDI路径获取 DataSource,比如,以
下application.properties中的片段展示了如何获取JBossAS定义
的DataSource:
spring.datasource.jndi-name=java:jboss/datasources/customers
29.1.配置DataSource
213

29.2.使用JdbcTemplate
Spring的JdbcTemplate和NamedParameterJdbcTemplate类会被自动配置,你
可以将它们直接 @Autowire到自己的beans:
importorg.springframework.beans.factory.annotation.Autowired;
importorg.springframework.jdbc.core.JdbcTemplate;
importorg.springframework.stereotype.Component;
@Component
publicclassMyBean{
privatefinalJdbcTemplatejdbcTemplate;
@Autowired
publicMyBean(JdbcTemplatejdbcTemplate){
this.jdbcTemplate=jdbcTemplate;
}
//...
}
29.2.使用JdbcTemplate
214

29.3.JPA和SpringData
Java持久化API是一个允许你将对象映射为关系数据库的标准技术, spring-
boot-starter-data-jpaPOM提供了一种快速上手的方式,它提供以下关键依
赖:
Hibernate-一个非常流行的JPA实现。
SpringDataJPA-让实现基于JPA的repositories更容易。
SpringORMs-Spring框架支持的核心ORM。
注我们不想在这涉及太多关于JPA或SpringData的细节。你可以参考来自spring.io
的指南使用JPA获取数据,并阅读SpringDataJPA和Hibernate的参考文档。
注SpringBoot默认使用Hibernate5.0.x,如果你希望的话也可以使用4.3.x或
5.2.x,具体参考Hibernate4和Hibernate5.2示例。
29.3.JPA和SpringData
215

29.3.1.实体类
通常,JPA实体类被定义到一个 persistence.xml文件,在SpringBoot中,这个
文件被'实体扫描'取代。默认情况,SpringBoot会查找主配置类
(被 @EnableAutoConfiguration或@SpringBootApplication注解的类)下
的所有包。
任何被 @Entity,@Embeddable或@MappedSuperclass注解的类都将被考
虑,一个普通的实体类看起来像这样:
packagecom.example.myapp.domain;
importjava.io.Serializable;
importjavax.persistence.*;
@Entity
publicclassCityimplementsSerializable{
@Id
@GeneratedValue
privateLongid;
@Column(nullable=false)
privateStringname;
@Column(nullable=false)
privateStringstate;
//...additionalmembers,ofteninclude@OneToManymappings
protectedCity(){
//no-argsconstructorrequiredbyJPAspec
//thisoneisprotectedsinceitshouldn'tbeuseddire
ctly
}
publicCity(Stringname,Stringstate){
this.name=name;
29.3.JPA和SpringData
216

this.country=country;
}
publicStringgetName(){
returnthis.name;
}
publicStringgetState(){
returnthis.state;
}
//...etc
}
注你可以使用 @EntityScan注解自定义实体扫描路径,具体参考Section74.4,
“Separate@EntitydefinitionsfromSpringconfiguration”。
29.3.JPA和SpringData
217

29.3.2.SpringDataJPA仓库
SpringDataJPA仓库(repositories)是用来定义访问数据的接口。根据你的方法
名,JPA查询会被自动创建,比如,一个 CityRepository接口可能声明一
个findAllByState(Stringstate)方法,用来查找给定状态的所有城市。
对于比较复杂的查询,你可以使用SpringData的Query注解你的方法。
SpringData仓库通常继承自 Repository或CrudRepository接口。如果你使用
自动配置,SpringBoot会搜索主配置类(注
解@EnableAutoConfiguration或@SpringBootApplication的类)所在包下
的仓库。
下面是典型的SpringData仓库:
packagecom.example.myapp.domain;
importorg.springframework.data.domain.*;
importorg.springframework.data.repository.*;
publicinterfaceCityRepositoryextendsRepository<City,Long>{
Page<City>findAll(Pageablepageable);
CityfindByNameAndCountryAllIgnoringCase(Stringname,String
country);
}
注:我们仅仅触及了SpringDataJPA的表面,具体查看它的参考指南。
29.3.JPA和SpringData
218

29.3.3.创建和删除JPA数据库
默认情况下,只有在你使用内嵌数据库(H2,HSQL或Derby)时,JPA数据库才会
被自动创建。你可以使用 spring.jpa.*属性显式的设置JPA,比如,将以下配置
添加到 application.properties中可以创建和删除表:
spring.jpa.hibernate.ddl-auto=create-drop
注Hibernate自己内部对创建,删除表支持的属性
是hibernate.hbm2ddl.auto(如果你记得更好)。你可以使
用spring.jpa.properties.*(前缀在被添加到实体管理器之前会被去掉)设置
Hibernate其他的native属性,比
如: spring.jpa.properties.hibernate.globally_quoted_identifiers=true
将传递 hibernate.globally_quoted_identifiers到Hibernate实体管理器。
通常,DDL执行(或验证)被延迟到 ApplicationContext启动后,这可以通
过spring.jpa.generate-ddl标签控制,如果Hibernate自动配置被激活,那该
标识就不会被使用,因为 ddl-auto设置粒度更细。
29.3.JPA和SpringData
219

29.4.1改变H2控制台路径
H2控制台路径默认为 /h2-console,你可以通过设
置spring.h2.console.path属性自定义该路径。
29.4使用H2的web控制台
221

29.4.2保护H2控制台
当添加SpringSecurity依赖,并且启用基本认证时,SpringBoot自动使用基本认证
保护H2控制台。以下属性可用于自定义安全配置:
security.user.role
security.basic.authorize-mode
security.basic.enabled
29.4使用H2的web控制台
222

29.5.1代码生成
为了使用jOOQ类型安全的查询,你需要从数据库schema生成Java类,具体可参考
jOOQ用户指南。如果正在使用 jooq-codegen-maven插件(也使用 spring-
boot-starter-parent“parentPOM”),你可以安全的省略插件
的<version>标签,也可以使用SpringBoot定义的版本变量(比
如h2.version)来声明插件的数据库依赖,示例如下:
<plugin>
<groupId>org.jooq</groupId>
<artifactId>jooq-codegen-maven</artifactId>
<executions>
...
</executions>
<dependencies>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>${h2.version}</version>
</dependency>
</dependencies>
<configuration>
<jdbc>
<driver>org.h2.Driver</driver>
<url>jdbc:h2:~/yourdatabase</url>
</jdbc>
<generator>
...
</generator>
</configuration>
</plugin>
29.5使用jOOQ
224

29.5.2使用DSLContext
jOOQ提供的流式(fluent)API是通过 org.jooq.DSLContext接口初始化的,
SpringBoot将自动配置一个 DSLContext为SpringBean,并将它跟应用
的DataSource连接起来。想要使用 DSLContext,只需 @Autowire注入它:
@Component
publicclassJooqExampleimplementsCommandLineRunner{
privatefinalDSLContextcreate;
@Autowired
publicJooqExample(DSLContextdslContext){
this.create=dslContext;
}
}
注jOOQ手册倾向于使用一个名为 create的变量持有 DSLContext,示例中也
是这样做的。
然后你就可以使用 DSLContext构造查询:
publicList<GregorianCalendar>authorsBornAfter1980(){
returnthis.create.selectFrom(AUTHOR)
.where(AUTHOR.DATE_OF_BIRTH.greaterThan(newGregorianCal
endar(1980,0,1)))
.fetch(AUTHOR.DATE_OF_BIRTH);
}
29.5使用jOOQ
225

29.5.3自定义jOOQ
通过在 application.properties中设置 spring.jooq.sql-dialect属性,你
可以自定义jOOQ使用的SQL方言(dialect)。例如,设置方言为Postgres:
spring.jooq.sql-dialect=Postgres
定义自己的 @Bean,在jOOQ Configuration创建时使用,可以实现更高级的定
制。你可以为以下jOOQ类型定义beans:
ConnectionProvider
TransactionProvider
RecordMapperProvider
RecordListenerProvider
ExecuteListenerProvider
VisitListenerProvider
如果想全面控制jOOQ配置,你甚至可以创建自己的 org.jooq.Configuration
@Bean。
29.5使用jOOQ
226

30.1.1.连接Redis
你可以注入一个自动配置
的RedisConnectionFactory,StringRedisTemplate或普通
的RedisTemplate实例,或任何其他SpringBean只要你愿意。默认情况下,这
个实例将尝试使用 localhost:6379连接Redis服务器:
@Component
publicclassMyBean{
privateStringRedisTemplatetemplate;
@Autowired
publicMyBean(StringRedisTemplatetemplate){
this.template=template;
}
//...
}
如果你添加一个自己的,或任何自动配置类型的 @Bean,它将替换默认实例(除
了RedisTemplate的情况,它是根据 bean的name'redisTemplate'而不是类型
进行排除的)。如果在classpath路径下存在 commons-pool2,默认你会获得一个
连接池工厂。
30.1.Redis
229

30.2.1.连接MongoDB数据库
你可以注入一个自动配置
的org.springframework.data.mongodb.MongoDbFactory来访问Mongo数据
库。默认情况下,该实例将尝试使用URL mongodb://localhost/test连接到
MongoDB服务器:
importorg.springframework.data.mongodb.MongoDbFactory;
importcom.mongodb.DB;
@Component
publicclassMyBean{
privatefinalMongoDbFactorymongo;
@Autowired
publicMyBean(MongoDbFactorymongo){
this.mongo=mongo;
}
//...
publicvoidexample(){
DBdb=mongo.getDb();
//...
}
}
你可以设置 spring.data.mongodb.uri来改变该url,并配置其他的设置,比如
副本集:
spring.data.mongodb.uri=mongodb://user:secret@mongo1.example.com
:12345,mongo2.example.com:23456/test
另外,跟正在使用的Mongo2.x一样,你可以指定 host/port,比如,
在application.properties中添加以下配置:
30.2.MongoDB
231

spring.data.mongodb.host=mongoserver
spring.data.mongodb.port=27017
注Mongo3.0Java驱动不支
持spring.data.mongodb.host和spring.data.mongodb.port,对于这种情
况, spring.data.mongodb.uri需要提供全部的配置信息。
注如果没有指定 spring.data.mongodb.port,默认使用 27017,上述示例中
可以删除这行配置。
注如果不使用SpringDataMongo,你可以注入 com.mongodb.Mongobeans以代
替MongoDbFactory。
如果想完全控制MongoDB连接的建立过程,你可以声明自己
的MongoDbFactory或Mongobean。如果想全面控制MongoDB连接的建立,
你也可以声明自己的MongoDbFactory或Mongo,@Beans。
30.2.MongoDB
232

30.2.2.MongoDBTemplate
SpringDataMongo提供了一个MongoTemplate类,它的设计和Spring
的JdbcTemplate很相似。跟 JdbcTemplate一样,SpringBoot会为你自动配置
一个bean,你只需简单的注入即可:
importorg.springframework.beans.factory.annotation.Autowired;
importorg.springframework.data.mongodb.core.MongoTemplate;
importorg.springframework.stereotype.Component;
@Component
publicclassMyBean{
privatefinalMongoTemplatemongoTemplate;
@Autowired
publicMyBean(MongoTemplatemongoTemplate){
this.mongoTemplate=mongoTemplate;
}
//...
}
具体参考 MongoOperationsJavadoc。
30.2.MongoDB
233

30.2.3.SpringDataMongoDB仓库
SpringData包含的仓库也支持MongoDB,正如上面讨论的JPA仓库,基于方法名
自动创建查询是基本的原则。
实际上,不管是SpringDataJPA还是SpringDataMongoDB都共享相同的基础设
施。所以你可以使用上面的JPA示例,并假设那个 City现在是一个Mongo数据类
而不是JPA @Entity,它将以同样的方式工作:
packagecom.example.myapp.domain;
importorg.springframework.data.domain.*;
importorg.springframework.data.repository.*;
publicinterfaceCityRepositoryextendsRepository<City,Long>{
Page<City>findAll(Pageablepageable);
CityfindByNameAndCountryAllIgnoringCase(Stringname,String
country);
}
注想详细了解SpringDataMongoDB,包括它丰富的对象映射技术,可以查看它的
参考文档。
30.2.MongoDB
234

30.2.4内嵌的Mongo
SpringBoot为内嵌Mongo提供自动配置,你需要添
加de.flapdoodle.embed:de.flapdoodle.embed.mongo依赖才能使用它。
spring.data.mongodb.port属性可用来配置Mongo监听的端口,将该属性值设
为0,表示使用一个随机分配的可用端口。通过 MongoAutoConfiguration创建
的MongoClient将自动配置为使用随机分配的端口。
如果classpath下存在SLF4J依赖,Mongo产生的输出将自动路由到一个名
为org.springframework.boot.autoconfigure.mongo.embedded.EmbeddedMon
go的logger。
想要完全控制Mongo实例的配置和日志路由,你可以声明自己
的IMongodConfig和IRuntimeConfigbeans。
30.2.MongoDB
235

30.3.1连接Neo4j数据库
你可以注入一个自动配置的 Neo4jSession,Session,
或Neo4jOperations实例,就像使用其他SpringBean那样。该实例默认使
用localhost:7474连接Neo4j服务器:
@Component
publicclassMyBean{
privatefinalNeo4jTemplateneo4jTemplate;
@Autowired
publicMyBean(Neo4jTemplateneo4jTemplate){
this.neo4jTemplate=neo4jTemplate;
}
//...
}
添加自己的 org.neo4j.ogm.config.Configuration@Bean,你就能完全控制
该配置了。同时,添加一个 Neo4jOperations类型的 @Bean可以禁用自动配
置。
通过 spring.data.neo4j.*属性可以配置使用的用户和凭证:
spring.data.neo4j.uri=http://my-server:7474
spring.data.neo4j.username=neo4j
spring.data.neo4j.password=secret
30.3Neo4j
237

30.3.2使用内嵌模式
注Neo4j的内嵌模式从属于不同的许可,在将它集成到应用之前确保复查下。
如果将 org.neo4j:neo4j-ogm-embedded-driver依赖添加到应用中,Spring
Boot会自动配置一个进程内(in-process)的内嵌Neo4j实例,当应用关闭时,该实
例不会持久化任何数据。设置 spring.data.neo4j.embedded.enabled=false可
显式关闭该模式,你也可以启用内嵌模式的持久化特性:
spring.data.neo4j.uri=file://var/tmp/graph.db
30.3Neo4j
238

30.3.3Neo4jSession
Neo4jSession默认的生命周期是应用程序范围,如果运行的是web应用,你可以很
轻松的改变它的scope:
spring.data.neo4j.session.scope=session
30.3Neo4j
239

30.3.4SpringDataNeo4j仓库
SpringData包含的仓库也支持Neo4j,实际上,SpringDataJPA和SpringData
Neo4j使用相同的常用设施,所以你可以采用先前JPA的示例,假设 City现在是
一个Neo4jOGM @NodeEntity而不是JPA @Entity,它将以同样的方式工作。
注你可以使用 @EntityScan注解定义实体扫描路径。
将以下两个注解添加到你的Springconfiguration,可以启用repository支持(还有可
选的对 @Transactional的支持):
@EnableNeo4jRepositories(basePackages="com.example.myapp.repos
itory")
@EnableTransactionManagement
30.3Neo4j
240

30.3.5仓库示例
packagecom.example.myapp.domain;
importorg.springframework.data.domain.*;
importorg.springframework.data.repository.*;
publicinterfaceCityRepositoryextendsGraphRepository<City>{
Page<City>findAll(Pageablepageable);
CityfindByNameAndCountry(Stringname,Stringcountry);
}
注想详细了解SpringDataNeo4j,包括它丰富的对象映射技术,可查看它的参考
文档。
30.3Neo4j
241

30.5.1连接Solr
你可以注入一个自动配置的 SolrClient实例,就像其他Springbeans那样,该实
例默认使用 localhost:8983/solr连接Solr服务器:
@Component
publicclassMyBean{
privateSolrClientsolr;
@Autowired
publicMyBean(SolrClientsolr){
this.solr=solr;
}
//...
}
如果你添加自己的 SolrClient类型的 @Bean,它将会替换默认实例。
30.5Solr
244

30.6.1使用Jest连接Elasticsearch
如果添加 Jest依赖,你可以注入一个自动配置的 JestClient,默认目标
为http://localhost:9200/,也可以进一步配置该客户端:
spring.elasticsearch.jest.uris=http://search.example.com:9200
spring.elasticsearch.jest.read-timeout=10000
spring.elasticsearch.jest.username=user
spring.elasticsearch.jest.password=secret
定义一个 JestClientbean以完全控制注册过程。
30.6Elasticsearch
247

30.6.2使用SpringData连接Elasticsearch
你可以注入一个自动配置的 ElasticsearchTemplate或Elasticsearch
Client实例,就想其他SpringBean那样。该实例默认内嵌一个本地,内存型服
务器(在Elasticsearch中被称为 Node),并使用当前工作目录作为服务器的
home目录。在这个步骤中,首先要做的是告诉Elasticsearch将文件存放到什么地
方:
spring.data.elasticsearch.properties.path.home=/foo/bar
另外,你可以通过设置 spring.data.elasticsearch.cluster-nodes(逗号分
隔的‘host:port’列表)来切换为远程服务器:
spring.data.elasticsearch.cluster-nodes=localhost:9300
@Component
publicclassMyBean{
privateElasticsearchTemplatetemplate;
@Autowired
publicMyBean(ElasticsearchTemplatetemplate){
this.template=template;
}
//...
}
如果添加自己的 ElasticsearchTemplate类型的 @Bean,它将覆盖默认实例。
30.6Elasticsearch
248

30.6.3SpringDataElasticseach仓库
SpringData包含的仓库也支持Elasticsearch,正如前面讨论的JPA仓库,基于方法
名自动创建查询是基本的原则。
实际上,不管是SpringDataJPA还是SpringDataElasticsearch都共享相同的基础
设施。所以你可以使用前面的JPA示例,并假设那个 City现在是一个
Elasticsearch @Document类而不是JPA @Entity,它将以同样的方式工作。
注具体参考SpringDataElasticsearch文档。
30.6Elasticsearch
249

30.7.1连接Cassandra
你可以注入一个自动配置的 CassandraTemplate或Cassandra Session实例,
就像注入其他SpringBean那样。 spring.data.cassandra.*属性可用来自定义
该连接,通常你需要提供 keyspace-name和contact-points属性:
spring.data.cassandra.keyspace-name=mykeyspace
spring.data.cassandra.contact-points=cassandrahost1,cassandrahos
t2
@Component
publicclassMyBean{
privateCassandraTemplatetemplate;
@Autowired
publicMyBean(CassandraTemplatetemplate){
this.template=template;
}
//...
}
如果添加自己的 CassandraTemplate类型的 @Bean,它将替换默认实例。
30.7Cassandra
251

30.8.1连接Couchbase
通过添加CouchbaseSDK和一些配置,你可以很容易获取一
个Bucket和Cluster,spring.couchbase.*属性可用于自定义该连接。通
常,你需要提供启动hosts,bucketname和password:
spring.couchbase.bootstrap-hosts=my-host-1,192.168.1.123
spring.couchbase.bucket.name=my-bucket
spring.couchbase.bucket.password=secret
注你至少需要提供启动host(s),在这种情况下,bucketname默认为 default,
password默认为空字符串。另外,你可以定义自己
的org.springframework.data.couchbase.config.CouchbaseConfigurer
@Bean来把控所有配置。
你也可以自定义一些 CouchbaseEnvironment设置,例如,以下配置改变打开
新Bucket的超时时间(timeout),还启用了SSL支持:
spring.couchbase.env.timeouts.connect=3000
spring.couchbase.env.ssl.key-store=/location/of/keystore.jks
spring.couchbase.env.ssl.key-store-password=secret
具体查看 spring.couchbase.env.*属性。
30.8Couchbase
254

30.8.2SpringDataCouchbase仓库
SpringData包含的仓库也支持Couchbase,具体可查看SpringDataCouchbase的
参考文档。
你可以注入一个自动配置的 CouchbaseTemplate实例,就像注入其他Spring
Bean那样,只要默认的 CouchbaseConfigurer可以使用。如果想关闭Spring
DataCouchbase的自动配置,你可以提供自己
的org.springframework.data.couchbase.config.AbstractCouchbaseDataCo
nfiguration实现。
@Component
publicclassMyBean{
privatefinalCouchbaseTemplatetemplate;
@Autowired
publicMyBean(CouchbaseTemplatetemplate){
this.template=template;
}
//...
}
如果添加你自己的 CouchbaseTemplate类型的 @Bean,且名称
为couchbaseTemplate,那它将替换默认实例。
30.8Couchbase
255

31.缓存
Spring框架提供为应用透明添加缓存的支持,核心思想是,将抽象应用到缓存方
法,基于缓存中可用信息减少方法的执行。缓存逻辑的应用是透明的,不会干扰调
用者。
注具体参考Spring框架指南的相应章节。
简而言之,为服务的某个操作添加缓存跟为方法添加相应注解那样简单:
importjavax.cache.annotation.CacheResult;
importorg.springframework.stereotype.Component;
@Component
publicclassMathService{
@CacheResult
publicintcomputePiDecimal(inti){
//...
}
}
注你既可以使用标准的JSR-107(JCache)注解,也可以使用Spring自己的缓存注
解,这是透明的,我们强烈建议你不要混淆使用。
注透明的更新或驱除缓存数据是可以的。
31.缓存
256

31.1支持的缓存提供商
缓存抽象不提供实际的存储,而是依赖
于org.springframework.cache.Cache和org.springframework.cache.Cach
eManager接口的实现。只要通过 @EnableCaching注解开启缓存支持,Spring
Boot就会根据实现自动配置一个合适的 CacheManager。
注如果你使用的缓存设施beans不是基于接口的,确保启
用proxyTargetClass,并设置其属性为 @EnableCaching。
注使用 spring-boot-starter-cache‘Starter’可以快速添加所需缓存依赖,如果
你是手动添加依赖,需要注意一些实现只有 spring-context-supportjar才提
供。
如果你还没有定义一个 CacheManager类型的bean,或一个名
为cacheResolver的CacheResolver(查看 CachingConfigurer),Spring
Boot将尝试以下提供商(按这个顺序):
Generic
JCache(JSR-107)(EhCache3,Hazelcast,Infinispan,etc)
EhCache2.x
Hazelcast
Infinispan
Couchbase
Redis
Caffeine
Guava
Simple
注spring.cache.type属性可强制指定使用的缓存提供商,如果需要在一
些环境(比如,测试)中禁用全部缓存也可以使用该属性。
如果 CacheManager是SpringBoot自动配置的,你可以在它完全初始化前,
通过实现 CacheManagerCustomizer接口进一步配置,以下设置使用的缓存
name:
31.1支持的缓存提供商
257

@Bean
publicCacheManagerCustomizer<ConcurrentMapCacheManager>cac
heManagerCustomizer(){
returnnewCacheManagerCustomizer<ConcurrentMapCacheManager
>(){
@Override
publicvoidcustomize(ConcurrentMapCacheManagercacheMa
nager){
cacheManager.setCacheNames(Arrays.asList("one","tw
o"));
}
};
}
注在以上示例中,需要配置一个 ConcurrentMapCacheManager,如果没有
配置,则自定义器(customizer)将不会被调用。自定义器你添加多少都可
以,并可以使用 @Order或Ordered对它们进行排序。
31.1支持的缓存提供商
258

31.1.1Generic
如果上下文定义至少一个 org.springframework.cache.Cachebean,一个配置
好的 CacheManager包装着它们,那么将使用通用(Generic)缓存。
31.1支持的缓存提供商
259

31.1.3EhCache2.x
如果在classpath下的根目录可以找到一个名为 ehcache.xml的文件,则缓存将使
用EhCache2.x。如果EhCache2.x和这样的文件出现,那它们将用于启动缓存管
理器,使用以下配置可提供替换的配置文件:
spring.cache.ehcache.config=classpath:config/another-config.xml
31.1支持的缓存提供商
260

31.1.4Hazelcast
SpringBoot为Hazelcast提供通常的支持,如果 HazelcastInstance被自动配
置,那它将自动包装进一个 CacheManager。
如果出于某些原因,需要使用另一个不同的 HazelcastInstance,你可以请求
SpringBoot创建一个单独的实例,并只用于该 CacheManager:
spring.cache.hazelcast.config=classpath:config/my-cache-hazelcas
t.xml
注如果以这种方式创建一个单独的 HazelcastInstance,它将不会注册到应用
上下文中。
31.1支持的缓存提供商
261

31.1.5Infinispan
Infinispan没有默认的配置文件位置,所以需要显式指定:
spring.cache.infinispan.config=infinispan.xml
通过设置 spring.cache.cache-names属性可以让缓存在启动时就被创建,如果
定义了 ConfigurationBuilderbean,它将用来定义该实例。
31.1支持的缓存提供商
262

31.1.6Couchbase
如果Couchbase可用,并配置好了, CouchbaseCacheManager将会自动配置,使
用spring.cache.cache-names属性可以在启动时创建其他缓存。对 Bucket的
操作也是自动配置的,你可以使用customizer在另一个 Bucket上创建其他缓存:
假设你需要在“main” Bucket上存放两个缓存( foo和bar),在另一
个Bucket上存放一个存活时间为2秒的 biz缓存。首先,你通过配置创建两个
缓存:
spring.cache.cache-names=foo,bar
然后定义其他 @Configuration来配置另一个 Bucket和biz缓存:
31.1支持的缓存提供商
263

@Configuration
publicclassCouchbaseCacheConfiguration{
privatefinalClustercluster;
publicCouchbaseCacheConfiguration(Clustercluster){
this.cluster=cluster;
}
@Bean
publicBucketanotherBucket(){
returnthis.cluster.openBucket("another","secret");
}
@Bean
publicCacheManagerCustomizer<CouchbaseCacheManager>cacheMa
nagerCustomizer(){
returnc->{
c.prepareCache("biz",CacheBuilder.newInstance(anoth
erBucket())
.withExpirationInMillis(2000));
};
}
}
这个示例配置重用了通过自动配置的 Cluster。
31.1支持的缓存提供商
264

31.1.7Redis
如果Redis可用,并配置好了, RedisCacheManager将被自动配置,使
用spring.cache.cache-names可以在启动时创建其他缓存。
注默认会添加key前缀以防止两个单独的缓存使用相同的key,否则Redis将存在重
复的key,有可能返回不可用的值。如果创建自己的 RedisCacheManager,强烈
建议你保留该配置处于启用状态。
31.1支持的缓存提供商
265

31.1.8Caffeine
Caffeine是Java8对Guava缓存的重写版本,在SpringBoot2.0中将取代Guava。如
果出现Caffeine,CaffeineCacheManager将会自动配置。使
用spring.cache.cache-names属性可以在启动时创建缓存,并可以通过以下配
置进行自定义(按顺序):
1. spring.cache.caffeine.spec定义的特殊缓存
2. com.github.benmanes.caffeine.cache.CaffeineSpecbean定义
3. com.github.benmanes.caffeine.cache.Caffeinebean定义
例如,以下配置创建一个 foo和bar缓存,最大数量为500,存活时间为10分
钟:
spring.cache.cache-names=foo,bar
spring.cache.caffeine.spec=maximumSize=500,expireAfterAccess=600
s
除此之外,如果定义
了com.github.benmanes.caffeine.cache.CacheLoader,它会自动关联
到CaffeineCacheManager。由于该 CacheLoader将关联被该缓存管理器管理
的所有缓存,所以它必须定义为 CacheLoader<Object,Object>,自动配置将
忽略所有泛型类型。
31.1支持的缓存提供商
266

31.1.9Guava
如果存在Guava,GuavaCacheManager会自动配置。使
用spring.cache.cache-names属性可以在启动时创建缓存,并通过以下方式之
一自定义(按此顺序):
1. spring.cache.guava.spec定义的特殊缓存
2. com.google.common.cache.CacheBuilderSpecbean定义的
3. com.google.common.cache.CacheBuilderbean定义的
例如,以下配置创建了一个 foo和bar缓存,该缓存最大数量为500,存活时间
为10分钟:
spring.cache.cache-names=foo,bar
spring.cache.guava.spec=maximumSize=500,expireAfterAccess=600s
此外,如果定义 com.google.common.cache.CacheLoaderbean,它会自动关联
到GuavaCacheManager。由于该 CacheLoader将关联该缓存管理器管理的所有
缓存,它必须定义为 CacheLoader<Object,Object>,自动配置会忽略所有泛
型类型。
31.1支持的缓存提供商
267

31.1.10Simple
如果以上选项都没有采用,一个使用 ConcurrentHashMap作为缓存存储的简单实
现将被配置,这是应用没有添加缓存library的默认设置。
31.1支持的缓存提供商
268

31.1.11None
如果配置类中出现 @EnableCaching,一个合适的缓存配置也同样被期待。如果
在某些环境需要禁用全部缓存,强制将缓存类型设为 none将会使用一个no-op实
现(没有任何实现的实现):
spring.cache.type=none
31.1支持的缓存提供商
269

32.消息
SpringFramework框架为集成消息系统提供了扩展(extensive)支持:从使
用JmsTemplate简化JMSAPI,到实现一个能够异步接收消息的完整的底层设
施。SpringAMQP提供一个相似的用于'高级消息队列协议'的特征集,并且Spring
Boot也为 RabbitTemplate和RabbitMQ提供了自动配置选项。SpringWebsocket
提供原生的STOMP消息支持,并且SpringBoot也提供了starters和自动配置支持。
32.消息
270

32.1.1ActiveQ支持
如果发现ActiveMQ在classpath下可用,SpringBoot会配置一
个ConnectionFactory。如果需要代理,将会开启一个内嵌的,已经自动配置好
的代理(只要配置中没有指定代理URL)。
ActiveMQ是通过 spring.activemq.*外部配置来控制的,例如,你可能
在application.properties中声明以下片段:
spring.activemq.broker-url=tcp://192.168.1.210:9876
spring.activemq.user=admin
spring.activemq.password=secret
具体参考ActiveMQProperties。
默认情况下,如果目标不存在,ActiveMQ将创建一个,所以目标是通过它们提供的
名称解析出来的。
32.1.JMS
272

32.1.2Artemis支持
ApacheArtemis成立于2015年,那时HornetQ刚捐给Apache基金会,确保别使用
了过期的HornetQ支持。注不要尝试同时使用Artemis和HornetQ。
如果发现classpath下存在Artemis依赖,SpringBoot将自动配置一
个ConnectionFactory。如果需要broker,SpringBoot将启动内嵌的broker,并
对其自动配置(除非模式mode属性被显式设置)。支持的modes包
括: embedded(明确需要内嵌broker,如果classpath下不存在则出
错), native(使用 netty传输协议连接broker)。当配置 native模式,
SpringBoot将配置一个连接broker的ConnectionFactory,该broker使用默认的
设置运行在本地机器。注使用 spring-boot-starter-artemis'Starter',则连
接已存在的Artemis实例及Spring设施集成JMS所需依赖都会提供,添
加org.apache.activemq:artemis-jms-server依赖,你可以使用内嵌模式。
Artemis配置控制在外部配置属性 spring.artemis.*中,例如,
在application.properties声明以下片段:
spring.artemis.mode=native
spring.artemis.host=192.168.1.210
spring.artemis.port=9876
spring.artemis.user=admin
spring.artemis.password=secret
当使用内嵌模式时,你可以选择是否启用持久化,及目的地列表。这些可以通过逗
号分割的列表来指定,也可以分别定
义org.apache.activemq.artemis.jms.server.config.JMSQueueConfigurati
on或org.apache.activemq.artemis.jms.server.config.TopicConfigurati
on类型的bean来进一步配置队列和topic,具体支持选项可参
考ArtemisProperties。
32.1.JMS
273

32.1.3HornetQ支持
注HornetQ在1.4版本已过期,可以考虑迁移到artemis。
如果在classpath下发现HornetQ,SpringBoot会自动配置 ConnectionFactory。
如果需要代理,将会开启一个内嵌的,已经自动配置好的代理(除非显式设置
mode属性)。支持的modes有: embedded(显式声明使用内嵌的代理,如果该
代理在classpath下不可用将出错), native(使用 netty传输协议连接代
理)。当后者被配置,SpringBoot配置一个连接到代理的 ConnectionFactory,
该代理运行在使用默认配置的本地机器上。
注:如果使用 spring-boot-starter-hornetq,连接到一个已存在的HornetQ实
例所需的依赖都会被提供,同时还有用于集成JMS的Spring基础设施。
将org.hornetq:hornetq-jms-server添加到应用中,你就可以使
用embedded模式。
HornetQ配置被 spring.hornetq.*中的外部配置属性所控制,例如,
在application.properties声明以下片段:
spring.hornetq.mode=native
spring.hornetq.host=192.168.1.210
spring.hornetq.port=9876
当内嵌代理时,你可以选择是否启用持久化,并且列表中的目标都应该是可用的。
这些可以通过一个以逗号分割的列表来指定一些默认的配置项,或定
义org.hornetq.jms.server.config.JMSQueueConfiguration或org.hornet
q.jms.server.config.TopicConfiguration类型的bean(s)来配置更高级的队列
和主题,具体参考HornetQProperties。
没有涉及JNDI查找,目标是通过名字解析的,名字即可以使用HornetQ配置中的
name属性,也可以是配置中提供的names。
32.1.JMS
274

32.1.4使用JNDIConnectionFactory
如果你的App运行在应用服务器中,SpringBoot将尝试使用JNDI定位一个JMS
ConnectionFactory,默认会检查 java:/JmsXA和java:/
XAConnectionFactory两个地址。如果需要指定替换位置,可以使
用spring.jms.jndi-name属性:
spring.jms.jndi-name=java:/MyConnectionFactory
32.1.JMS
275

32.1.5发送消息
Spring的JmsTemplate会被自动配置,你可以将它直接注入到自己的beans中:
importorg.springframework.beans.factory.annotation.Autowired;
importorg.springframework.jms.core.JmsTemplate;
importorg.springframework.stereotype.Component;
@Component
publicclassMyBean{
privatefinalJmsTemplatejmsTemplate;
@Autowired
publicMyBean(JmsTemplatejmsTemplate){
this.jmsTemplate=jmsTemplate;
}
//...
}
注你可以使用相同方式注入JmsMessagingTemplate。如果定义
了DestinationResolver或MessageConverterbeans,它们将自动关联到自
动配置的 JmsTemplate。
32.1.JMS
276

32.1.6接收消息
当JMS基础设施能够使用时,任何bean都能够被 @JmsListener注解,以创建一
个监听者端点。如果没有定义 JmsListenerContainerFactory,将自动配置一
个默认的。如果定义 DestinationResolver或MessageConverterbeans,它
们将自动关联该默认factory。
默认factory是事务性的,如果运行的设施出现 JtaTransactionManager,它默认
将关联到监听器容器。如果没有, sessionTransacted标记将启用。在后一场景
中,你可以通过在监听器方法上添加 @Transactional,以本地数据存储事务处
理接收的消息,这可以确保接收的消息在本地事务完成后只确认一次。
下面的组件创建了一个以 someQueue为目标的监听器端点:
@Component
publicclassMyBean{
@JmsListener(destination="someQueue")
publicvoidprocessMessage(Stringcontent){
//...
}
}
具体查看@EnableJmsjavadoc。
如果想创建多个 JmsListenerContainerFactory实例或覆盖默认实例,你可以
使用SpringBoot提供的 DefaultJmsListenerContainerFactoryConfigurer,
通过它可以使用跟自动配置的实例相同配置来初始化一
个DefaultJmsListenerContainerFactory。
例如,以下使用一个特殊的 MessageConverter创建另一个factory:
32.1.JMS
277

@Configuration
staticclassJmsConfiguration{
@Bean
publicDefaultJmsListenerContainerFactorymyFactory(
DefaultJmsListenerContainerFactoryConfigurerconfigu
rer){
DefaultJmsListenerContainerFactoryfactory=
newDefaultJmsListenerContainerFactory();
configurer.configure(factory,connectionFactory());
factory.setMessageConverter(myMessageConverter());
returnfactory;
}
}
然后,你可以像下面那样在任何 @JmsListener注解中使用:
@Component
publicclassMyBean{
@JmsListener(destination="someQueue",containerFactory="my
Factory")
publicvoidprocessMessage(Stringcontent){
//...
}
}
32.1.JMS
278

32.2AMQP
高级消息队列协议(AMQP)是一个用于消息中间件的,平台无关的,线路级
(wire-level)协议。SpringAMQP项目使用Spring的核心概念开发基于AMQP的消
息解决方案,SpringBoot为通过RabbitMQ使用AMQP提供了一些便利,包
括spring-boot-starter-amqp‘Starter’。
32.2AMQP
279

32.2.1RabbitMQ支持
RabbitMQ是一个基于AMQP协议,轻量级的,可靠的,可扩展的和可移植的消息
代理,Spring就使用它进行消息传递。RabbitMQ配置被外部属
性spring.rabbitmq.*控制,例如,在 application.properties中声明以下
片段:
spring.rabbitmq.host=localhost
spring.rabbitmq.port=5672
spring.rabbitmq.username=admin
spring.rabbitmq.password=secret
更多选项参考RabbitProperties。
32.2AMQP
280

32.2.2发送消息
Spring的AmqpTemplate和AmqpAdmin会被自动配置,你可以将它们直接注入
beans中:
importorg.springframework.amqp.core.AmqpAdmin;
importorg.springframework.amqp.core.AmqpTemplate;
importorg.springframework.beans.factory.annotation.Autowired;
importorg.springframework.stereotype.Component;
@Component
publicclassMyBean{
privatefinalAmqpAdminamqpAdmin;
privatefinalAmqpTemplateamqpTemplate;
@Autowired
publicMyBean(AmqpAdminamqpAdmin,AmqpTemplateamqpTemplate)
{
this.amqpAdmin=amqpAdmin;
this.amqpTemplate=amqpTemplate;
}
//...
}
注可以使用相似方式注入 RabbitMessagingTemplate,如果定
义MessageConverterbean,它将自动关联到自动配置的 AmqpTemplate。
如果需要的话,所有定义为bean的org.springframework.amqp.core.Queue将
自动在RabbitMQ实例中声明相应的队列。你可以启用 AmqpTemplate的重试选
项,例如代理连接丢失时,重试默认不启用。
32.2AMQP
281

32.2.3接收消息
当Rabbit设施出现时,所有bean都可以注解 @RabbitListener来创建一个监听器
端点。如果没有定义 RabbitListenerContainerFactory,SpringBoot将自动配
置一个默认的。如果定义 MessageConverterbeans,它将自动关联到默认的
factory。
下面的组件创建一个 someQueue队列上的监听器端点:
@Component
publicclassMyBean{
@RabbitListener(queues="someQueue")
publicvoidprocessMessage(Stringcontent){
//...
}
}
注具体参考@EnableRabbit。
如果需要创建多个 RabbitListenerContainerFactory实例,或想覆盖默认实
例,你可以使用SpringBoot提供
的SimpleRabbitListenerContainerFactoryConfigurer,通过它可以使用跟
自动配置实例相同的配置初始化 SimpleRabbitListenerContainerFactory。
例如,下面使用一个特殊的 MessageConverter创建了另一个factory:
32.2AMQP
282

@Configuration
staticclassRabbitConfiguration{
@Bean
publicSimpleRabbitListenerContainerFactorymyFactory(
SimpleRabbitListenerContainerFactoryConfigurerconfi
gurer){
SimpleRabbitListenerContainerFactoryfactory=
newSimpleRabbitListenerContainerFactory();
configurer.configure(factory,connectionFactory);
factory.setMessageConverter(myMessageConverter());
returnfactory;
}
}
然后,你可以像下面那样在所有 @RabbitListener注解方法中使用:
@Component
publicclassMyBean{
@RabbitListener(queues="someQueue",containerFactory="myFa
ctory")
publicvoidprocessMessage(Stringcontent){
//...
}
}
你可以启动重试处理那些监听器抛出异常的情况,当重试次数达到限制时,该消息
将被拒绝,要不被丢弃,要不路由到一个dead-letter交换器,如果broker这样配置
的话,默认禁用重试。
重要如果没启用重试,且监听器抛出异常,则Rabbit会不定期进行重试。你可以采
用两种方式修改该行为:设置 defaultRequeueRejected属性为 false,这样
就不会重试;或抛出一个 AmqpRejectAndDontRequeueException异常表示该消
息应该被拒绝,这是开启重试,且达到最大重试次数时使用的策略。
32.2AMQP
283

32.2AMQP
284

33.调用REST服务
如果应用需要调用远程REST服务,你可以使用Spring框架的 RestTemplate类。
由于 RestTemplate实例经常在使用前需要自定义,SpringBoot就没有提供任何
自动配置的 RestTemplatebean,不过你可以通过自动配置
的RestTemplateBuilder创建自己需要的 RestTemplate实例。自动配置
的RestTemplateBuilder会确保应用到 RestTemplate实例
的HttpMessageConverters是合适的。
以下是典型的示例:
@Service
publicclassMyBean{
privatefinalRestTemplaterestTemplate;
publicMyBean(RestTemplateBuilderrestTemplateBuilder){
this.restTemplate=restTemplateBuilder.build();
}
publicDetailssomeRestCall(Stringname){
returnthis.restTemplate.getForObject("/{name}/details",
Details.class,name);
}
}
注RestTemplateBuilder包含很多有用的方法,可以用于快速配置一
个RestTemplate。例如,你可以使用 builder.basicAuthorization("user",
"password").build()添加基本的认证支持(BASICauth)。
33.调用REST服务
285

33.1自定义RestTemplate
当使用 RestTemplateBuilder构建 RestTemplate时,可以通
过RestTemplateCustomizer进行更高级的定制,所
有RestTemplateCustomizerbeans将自动添加到自动配置
的RestTemplateBuilder。此外,调
用additionalCustomizers(RestTemplateCustomizer…)方法可以创建一个新
的,具有其他customizers的RestTemplateBuilder。
以下示例演示使用自定义器(customizer)配置所有hosts使用代理,除
了192.168.0.5:
33.调用REST服务
286

staticclassProxyCustomizerimplementsRestTemplateCustomizer{
@Override
publicvoidcustomize(RestTemplaterestTemplate){
HttpHostproxy=newHttpHost("proxy.example.com");
HttpClienthttpClient=HttpClientBuilder.create()
.setRoutePlanner(newDefaultProxyRoutePlanner(pr
oxy){
@Override
publicHttpHostdetermineProxy(HttpHosttarg
et,
HttpRequestrequest,HttpContextcon
text)
throwsHttpException{
if(target.getHostName().equals("192.168
.0.5")){
returnnull;
}
returnsuper.determineProxy(target,requ
est,context);
}
}).build();
restTemplate.setRequestFactory(
newHttpComponentsClientHttpRequestFactory(httpC
lient));
}
}
33.调用REST服务
287

35.使用JTA处理分布式事务
SpringBoot通过Atomkos或Bitronix的内嵌事务管理器支持跨多个XA资源的分布式
JTA事务,当部署到恰当的J2EE应用服务器时也会支持JTA事务。
当发现JTA环境时,SpringBoot将使用Spring的JtaTransactionManager来管理
事务。自动配置的JMS,DataSource和JPA beans将被升级以支持XA事务。你可
以使用标准的Springidioms,比如 @Transactional,来参与到一个分布式事务
中。如果处于JTA环境,但仍想使用本地事务,你可以将 spring.jta.enabled属
性设置为 false来禁用JTA自动配置功能。
35.使用JTA处理分布式事务
289

35.1使用Atomikos事务管理器
Atomikos是一个非常流行的开源事务管理器,并且可以嵌入到你的SpringBoot应用
中。你可以使用 spring-boot-starter-jta-atomikosStarter去获取正确的
Atomikos库。SpringBoot会自动配置Atomikos,并将合适的 depends-on应用到
你的SpringBeans上,确保它们以正确的顺序启动和关闭。
默认情况下,Atomikos事务日志将被记录在应用home目录(你的应用jar文件放置
的目录)下的 transaction-logs文件夹中。你可以
在application.properties文件中通过设置 spring.jta.log-dir属性来定
义该目录,以 spring.jta.atomikos.properties开头的属性能用来定义
Atomikos的UserTransactionServiceIml实现,具体参考AtomikosProperties
javadoc。
注为了确保多个事务管理器能够安全地和相应的资源管理器配合,每个Atomikos实
例必须设置一个唯一的ID。默认情况下,该ID是Atomikos实例运行的机器上的IP地
址。为了确保生产环境中该ID的唯一性,你需要为应用的每个实例设置不同
的spring.jta.transaction-manager-id属性值。
35.1使用Atomikos事务管理器
290

35.2使用Bitronix事务管理器
Bitronix是一个流行的开源JTA事务管理器实现,你可以使用 spring-boot-
starter-jta-bitronixstarter为项目添加合适的Birtronix依赖。和Atomikos类
似,SpringBoot将自动配置Bitronix,并对beans进行后处理(post-process)以确
保它们以正确的顺序启动和关闭。
默认情况下,Bitronix事务日志( part1.btm和part2.btm)将被记录到应用
home目录下的 transaction-logs文件夹中,你可以通过设
置spring.jta.log-dir属性来自定义该目录。
以spring.jta.bitronix.properties开头的属性将被绑定
到bitronix.tm.Configurationbean,你可以通过这完成进一步的自定义,具
体参考Bitronix文档。
注为了确保多个事务管理器能够安全地和相应的资源管理器配合,每个Bitronix实
例必须设置一个唯一的ID。默认情况下,该ID是Bitronix实例运行的机器上的IP地
址。为了确保生产环境中该ID的唯一性,你需要为应用的每个实例设置不同
的spring.jta.transaction-manager-id属性值。
35.2使用Bitronix事务管理器
291

35.3使用Narayana事务管理器
Narayana是一个流行的开源JTA事务管理器实现,目前只有JBoss支持。你可以使
用spring-boot-starter-jta-narayanastarter添加合适的Narayana依赖,像
Atomikos和Bitronix那样,SpringBoot将自动配置Narayana,并对你的beans后处
理(post-process)以确保正确启动和关闭。
Narayana事务日志默认记录到应用home目录(放置应用jar的目录)
的transaction-logs目录下,你可以通过设置 application.properties中
的spring.jta.log-dir属性自定义该目录。
以spring.jta.narayana.properties开头的属性可用于自定义Narayana配置,
具体参考NarayanaProperties。
注为了确保多事务管理器能够安全配合相应资源管理器,每个Narayana实例必须
配置唯一的ID,默认ID设为 1。为确保生产环境中ID唯一性,你可以为应用的每
个实例配置不同的 spring.jta.transaction-manager-id属性值。
35.3使用Narayana事务管理器
292

35.4使用J2EE管理的事务管理器
如果你将SpringBoot应用打包为一个 war或ear文件,并将它部署到一个J2EE
的应用服务器中,那你就能使用应用服务器内建的事务管理器。SpringBoot将尝试
通过查找常见的JNDI路径( java:comp/UserTransaction,
java:comp/TransactionManager等)来自动配置一个事务管理器。如果使用应
用服务器提供的事务服务,你通常需要确保所有的资源都被应用服务器管理,并通
过JNDI暴露出去。SpringBoot通过查找JNDI路
径java:/JmsXA或java:/XAConnectionFactory获取一
个ConnectionFactory来自动配置JMS,并且你可以使
用spring.datasource.jndi-name属性配置你的 DataSource。
35.4使用J2EE管理的事务管理器
293

35.5混合XA和non-XA的JMS连接
当使用JTA时,primaryJMS ConnectionFactorybean将能识别XA,并参与到分
布式事务中。有些情况下,你可能需要使用non-XA的ConnectionFactory去处
理一些JMS消息。例如,你的JMS处理逻辑可能比XA超时时间长。
如果想使用一个non-XA的ConnectionFactory,你可以注
入nonXaJmsConnectionFactory bean而不是 @Primary
jmsConnectionFactorybean。为了保持一致, jmsConnectionFactory
bean将以别名 xaJmsConnectionFactor来被使用。
示例如下:
//Injecttheprimary(XAaware)ConnectionFactory
@Autowired
privateConnectionFactorydefaultConnectionFactory;
//InjecttheXAawareConnectionFactory(usesthealiasandinj
ectsthesameasabove)
@Autowired
@Qualifier("xaJmsConnectionFactory")
privateConnectionFactoryxaConnectionFactory;
//Injectthenon-XAawareConnectionFactory
@Autowired
@Qualifier("nonXaJmsConnectionFactory")
privateConnectionFactorynonXaConnectionFactory;
35.5混合XA和non-XA的JMS连接
294

35.6支持可替代的内嵌事务管理器
XAConnectionFactoryWrapper和XADataSourceWrapper接口用于支持可替换的内
嵌事务管理器。该接口用于包装 XAConnectionFactory和XADataSource
beans,并将它们暴露为普通的 ConnectionFactory和DataSourcebeans,这
样在分布式事务中可以透明使用。SpringBoot将使用注册
到ApplicationContext的合适的XA包装器及 JtaTransactionManagerbean
自动配置你的DataSource和JMS。
BitronixXAConnectionFactoryWrapper和BitronixXADataSourceWrapper提供很好
的示例用于演示怎么编写XA包装器。
35.6支持可替代的内嵌事务管理器
295

36.Hazelcast
如果添加hazelcast依赖,SpringBoot将自动配置一个 HazelcastInstance,你
可以注入到应用中, HazelcastInstance实例只有存在相关配置时才会创建。
如果定义了 com.hazelcast.config.Configbean,则SpringBoot将使用它。如
果你的配置指定了实例的名称,SpringBoot将尝试定位已存在的而不是创建一个新
实例。你可以在配置中指定将要使用的 hazelcast.xml配置文件:
spring.hazelcast.config=classpath:config/my-hazelcast.xml
否则,SpringBoot尝试从默认路径查找Hazelcast配置,也就
是hazelcast.xml所在的工作路径或classpath的根路径。SpringBoot也会检查
是否设置 hazelcast.config系统属性,具体参考Hazelcast文档。
注SpringBoot为Hazelcast提供了缓存支持,如果开启缓存的
话, HazelcastInstance实例将自动包装进一个 CacheManager实现中。
36.Hazelcast
296

38.SpringSession
SpringBoot为SpringSession自动配置了各种存储:
JDBC
MongoDB
Redis
Hazelcast
HashMap
如果SpringSession可用,你只需选择想要的存储sessions的存储类型StoreType。
例如,按如下配置将使用JDBC作为后端存储:
spring.session.store-type=jdbc
注出于向后兼容,如果Redis可用,SpringSession将自动配置使用Redis存储。
注设置 store-type为none可以禁用SpringSession。
每个存储都有特殊设置,例如,对于jdbc存储可自定义表名:
spring.session.jdbc.table-name=SESSIONS
38.SpringSession
298

40.测试
SpringBoot提供很多有用的工具类和注解用于帮助你测试应用,主要分两个模
块: spring-boot-test包含核心组件, spring-boot-test-
autoconfigure为测试提供自动配置。
大多数开发者只需要引用 spring-boot-starter-test‘Starter’,它既提供
SpringBoot测试模块,也提供JUnit,AssertJ,Hamcrest和很多有用的依赖。
40.测试
300

40.1测试作用域依赖
如果使用 spring-boot-starter-test‘Starter’(在 test``scope内),你将
发现下列被提供的库:
JUnit-事实上的(de-facto)标准,用于Java应用的单元测试。
SpringTest&SpringBootTest -对Spring应用的集成测试支持。
AssertJ-一个流式断言库。
Hamcrest-一个匹配对象的库(也称为约束或前置条件)。
Mockito-一个Java模拟框架。
JSONassert-一个针对JSON的断言库。
JsonPath-用于JSON的XPath。
这是写测试用例经常用到的库,如果它们不能满足要求,你可以随意添加其他的依
赖。
40.1测试作用域依赖
301

40.2测试Spring应用
依赖注入主要优势之一就是它能够让你的代码更容易进行单元测试。你只需简单的
通过 new操作符实例化对象,甚至不需要涉及Spring,也可以使用模拟对象替换
真正的依赖。
你常常需要在进行单元测试后,开始集成测试(在这个过程中只需要涉及到Spring
的ApplicationContext)。在执行集成测试时,不需要部署应用或连接到其他
基础设施是非常有用的,Spring框架为实现这样的集成测试提供了一个专用的测试
模块,通过声明 org.springframework:spring-test的依赖,或使用 spring-
boot-starter-test‘Starter’就可以使用它了。
如果以前没有使用过 spring-test模块,可以查看Spring框架参考文档中的相关
章节。
40.2测试Spring应用
302

40.3测试SpringBoot应用
SpringBoot应用只是一个Spring ApplicationContext,所以在测试时对它只需
要像处理普通Springcontext那样即可。唯一需要注意的是,如果你使
用SpringApplication创建上下文,外部配置,日志和SpringBoot的其他特性只
会在默认的上下文中起作用。
SpringBoot提供一个 @SpringApplicationConfiguration注解用于替换标准
的spring-test@ContextConfiguration注解,该组件工作方式是通
过SpringApplication创建用于测试的 ApplicationContext。
你可以使用 @SpringBootTest的webEnvironment属性定义怎么运行测试:
MOCK-加载 WebApplicationContext,并提供一个mockservlet环境,使
用该注解时内嵌servlet容器将不会启动。如果classpath下不存在servlet
APIs,该模式将创建一个常规的non-web ApplicationContext。
RANDOM_PORT-加载 EmbeddedWebApplicationContext,并提供一个真实
的servlet环境。使用该模式内嵌容器将启动,并监听在一个随机端口。
DEFINED_PORT-加载 EmbeddedWebApplicationContext,并提供一个真
实的servlet环境。使用该模式内嵌容器将启动,并监听一个定义好的端口(比
如application.properties中定义的或默认的 8080端口)。
NONE-使用 SpringApplication加载一个 ApplicationContext,但不
提供任何servlet环境(不管是mock还是其他)。
注不要忘记在测试用例上添加 @RunWith(SpringRunner.class),否则该注解将
被忽略。
40.3测试SpringBoot应用
303

40.3.1发现测试配置
如果熟悉Spring测试框架,你可能经常通
过@ContextConfiguration(classes=…)指定加载哪些Spring
@Configuration,也可能经常在测试类中使用内嵌 @Configuration类。当测
试SpringBoot应用时这些就不需要了,SpringBoot的@*Test注解会自动搜索主
配置类,即使你没有显式定义它。
搜索算法是从包含测试类的package开始搜索,直到发
现@SpringBootApplication或@SpringBootConfiguration注解的类,只要
按恰当的方式组织代码,通常都会发现主配置类。
如果想自定义主配置类,你可以使用一个内嵌的 @TestConfiguration类。不像
内嵌的 @Configuration类(会替换应用主配置类),内嵌
的@TestConfiguration类是可以跟应用主配置类一块使用的。
注Spring测试框架在测试过程中会缓存应用上下文,因此,只要你的测试共享相同
的配置(不管是怎么发现的),加载上下文的潜在时间消耗都只会发生一次。
40.3测试SpringBoot应用
304

40.3.2排除测试配置
如果应用使用组件扫描,比如 @SpringBootApplication或@ComponentScan,
你可能发现为测试类创建的组件或配置在任何地方都可能偶然扫描到。为了防止这
种情况,SpringBoot提供了 @TestComponent和@TestConfiguration注解,
可用在 src/test/java目录下的类,以暗示它们不应该被扫描。
注只有上层类需要 @TestComponent和@TestConfiguration注解,如果你在
测试类(任何有 @Test方法或 @RunWith注解的类)中定
义@Configuration或@Component内部类,它们将被自动过滤。
注如果直接使用 @ComponentScan(比如不通
过@SpringBootApplication),你需要为它注册 TypeExcludeFilter,具体
参考Javadoc。
40.3测试SpringBoot应用
305

40.3.3使用随机端口
如果你需要为测试启动一个完整运行的服务器,我们建议你使用随机端口。如果你
使用 @SpringBootTest(webEnvironment=WebEnvironment.RANDOM_PORT),每
次运行测试都会为你分配一个可用的随机端口。
@LocalServerPort注解用于注入测试用例实际使用的端口,简单起见,需要发
起REST调用到启动服务器的测试可以额外 @Autowire一
个TestRestTemplate,它可以解析到运行服务器的相关链接:
importorg.junit.*;
importorg.junit.runner.*;
importorg.springframework.boot.test.context.web.*;
importorg.springframework.boot.test.web.client.*;
importorg.springframework.test.context.junit4.*;
importstaticorg.assertj.core.api.Assertions.*
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment=WebEnvironment.RANDOM_PORT)
publicclassMyWebIntegrationTests{
@Autowired
privateTestRestTemplaterestTemplate;
@Test
publicvoidexampleTest(){
Stringbody=this.restTemplate.getForObject("/",String
.class);
assertThat(body).isEqualTo("HelloWorld");
}
}
40.3测试SpringBoot应用
306

40.3.4模拟和监视beans
有时候需要在运行测试用例时mock一些组件,例如,你可能需要一些远程服务的门
面,但在开发期间不可用。Mocking在模拟真实环境很难复现的失败情况时非常有
用。
SpringBoot提供一个 @MockBean注解,可用于为 ApplicationContext中的
bean定义一个Mockitomock,你可以使用该注解添加新beans,或替换已存在的
bean定义。该注解可直接用于测试类,也可用于测试类的字段,或用
于@Configuration注解的类和字段。当用于字段时,创建mock的实例也会被注
入。Mockbeans每次调用完测试方法后会自动重置。
下面是一个典型示例,演示使用mock实现替换真实存在的 RemoteService
bean:
40.3测试SpringBoot应用
307

importorg.junit.*;
importorg.junit.runner.*;
importorg.springframework.beans.factory.annotation.*;
importorg.springframework.boot.test.context.*;
importorg.springframework.boot.test.mock.mockito.*;
importorg.springframework.test.context.junit4.*;
importstaticorg.assertj.core.api.Assertions.*;
importstaticorg.mockito.BDDMockito.*;
@RunWith(SpringRunner.class)
@SpringBootTest
publicclassMyTests{
@MockBean
privateRemoteServiceremoteService;
@Autowired
privateReverserreverser;
@Test
publicvoidexampleTest(){
//RemoteServicehasbeeninjectedintothereverserbean
given(this.remoteService.someCall()).willReturn("mock");
Stringreverse=reverser.reverseSomeCall();
assertThat(reverse).isEqualTo("kcom");
}
}
此外,你可以使用 @SpyBean和Mockito spy包装一个已存在的bean,具体参考
文档。
40.3测试SpringBoot应用
308

40.3.5自动配置测试
SpringBoot的自动配置系统对应用来说很合适,但用于测试就有点杀鸡用牛刀了,
测试时只加载需要的应用片段(slice)通常是有好处的。例如,你可能想测试
SpringMVC控制器映射URLs是否正确,且不想在这些测试中涉及到数据库调用;
或者你想测试JPA实体,那测试运行时你可能对web层不感兴趣。
spring-boot-test-autoconfigure模块包含很多用来自动配置这些片段
(slices)的注解,每个工作方式都相似,都是提供一个 @…Test注解,然后加
载ApplicationContext,使用一个或多个 @AutoConfigure…注解自定义设
置。
注@AutoConfigure…注解也可以跟标准的 @SpringBootTest注解一块使用,
如果对应用片段不感兴趣,只是想获取自动配置的一些测试beans,你可以使用该
组合。
40.3测试SpringBoot应用
309

40.3.6自动配置的JSON测试
你可以使用 @JsonTest测试对象JSON序列化和反序列化是否工作正常,该注解
将自动配置Jackson ObjectMapper,@JsonComponent和Jackson
Modules。如果碰巧使用gson代替Jackson,该注解将配置 Gson。使
用@AutoConfigureJsonTesters可以配置auto-configuration的元素。
SpringBoot提供基于AssertJ的帮助类(helpers),可用来配合JSONassert和
JsonPathlibraries检测JSON是否为期望
的, JacksonHelper,GsonHelper,BasicJsonTester分别用于Jackson,
Gson,Strings。当使用 @JsonTest时,你可以在测试类中 @Autowired任何
helper字段:
importorg.junit.*;
importorg.junit.runner.*;
importorg.springframework.beans.factory.annotation.*;
importorg.springframework.boot.test.autoconfigure.json.*;
importorg.springframework.boot.test.context.*;
importorg.springframework.boot.test.json.*;
importorg.springframework.test.context.junit4.*;
importstaticorg.assertj.core.api.Assertions.*;
@RunWith(SpringRunner.class)
@JsonTest
publicclassMyJsonTests{
@Autowired
privateJacksonTester<VehicleDetails>json;
@Test
publicvoidtestSerialize()throwsException{
VehicleDetailsdetails=newVehicleDetails("Honda","Ci
vic");
//Assertagainsta`.json`fileinthesamepackageas
thetest
assertThat(this.json.write(details)).isEqualToJson("expe
cted.json");
40.3测试SpringBoot应用
310

//OruseJSONpathbasedassertions
assertThat(this.json.write(details)).hasJsonPathStringVa
lue("@.make");
assertThat(this.json.write(details)).extractingJsonPathS
tringValue("@.make")
.isEqualTo("Honda");
}
@Test
publicvoidtestDeserialize()throwsException{
Stringcontent="{\"make\":\"Ford\",\"model\":\"Focus\"
}";
assertThat(this.json.parse(content))
.isEqualTo(newVehicleDetails("Ford","Focus"));
assertThat(this.json.parseObject(content).getMake()).isE
qualTo("Ford");
}
}
注JSON帮助类可用于标准单元测试类,如果没有使用 @JsonTest,你需要
在@Before方法中调用帮助类的 initFields方法。
在附录中可以查看 @JsonTest开启的自动配置列表。
40.3测试SpringBoot应用
311

40.3.7自动配置的SpringMVC测试
你可以使用 @WebMvcTest检测SpringMVC控制器是否工作正常,该注解将自动配
置SpringMVC设施,并且只扫描注
解@Controller,@ControllerAdvice,@JsonComponent,Filter,W
ebMvcConfigurer和HandlerMethodArgumentResolver的beans,其他常规
的@Componentbeans将不会被扫描。
通常 @WebMvcTest只限于单个控制器(controller)使用,并结合 @MockBean以
提供需要的协作者(collaborators)的mock实现。 @WebMvcTest也会自动配
置MockMvc,MockMVC为快速测试MVC控制器提供了一种强大的方式,并且不
需要启动一个完整的HTTP服务器。
注使用 @AutoConfigureMockMvc注解一个non- @WebMvcTest的类(比
如SpringBootTest)也可以自动配置 MockMvc。
40.3测试SpringBoot应用
312

importorg.junit.*;
importorg.junit.runner.*;
importorg.springframework.beans.factory.annotation.*;
importorg.springframework.boot.test.autoconfigure.web.servlet.*
;
importorg.springframework.boot.test.mock.mockito.*;
importstaticorg.assertj.core.api.Assertions.*;
importstaticorg.mockito.BDDMockito.*;
importstaticorg.springframework.test.web.servlet.request.MockM
vcRequestBuilders.*;
importstaticorg.springframework.test.web.servlet.result.MockMv
cResultMatchers.*;
@RunWith(SpringRunner.class)
@WebMvcTest(UserVehicleController.class)
publicclassMyControllerTests{
@Autowired
privateMockMvcmvc;
@MockBean
privateUserVehicleServiceuserVehicleService;
@Test
publicvoidtestExample()throwsException{
given(this.userVehicleService.getVehicleDetails("sboot")
)
.willReturn(newVehicleDetails("Honda","Civic")
);
this.mvc.perform(get("/sboot/vehicle").accept(MediaType.
TEXT_PLAIN))
.andExpect(status().isOk()).andExpect(content().
string("HondaCivic"));
}
}
40.3测试SpringBoot应用
313

注如果需要定义自定配置(auto-configuration)的元素(比如什么时候使用servlet
filters),你可以使用 @AutoConfigureMockMvc的属性。
如果你使用HtmlUnit或Selenium,自动配置将提供一个 WebClientbean和/
或WebDriverbean,以下是使用HtmlUnit的示例:
40.3测试SpringBoot应用
314

importcom.gargoylesoftware.htmlunit.*;
importorg.junit.*;
importorg.junit.runner.*;
importorg.springframework.beans.factory.annotation.*;
importorg.springframework.boot.test.autoconfigure.web.servlet.*
;
importorg.springframework.boot.test.mock.mockito.*;
importstaticorg.assertj.core.api.Assertions.*;
importstaticorg.mockito.BDDMockito.*;
@RunWith(SpringRunner.class)
@WebMvcTest(UserVehicleController.class)
publicclassMyHtmlUnitTests{
@Autowired
privateWebClientwebClient;
@MockBean
privateUserVehicleServiceuserVehicleService;
@Test
publicvoidtestExample()throwsException{
given(this.userVehicleService.getVehicleDetails("sboot")
)
.willReturn(newVehicleDetails("Honda","Civic")
);
HtmlPagepage=this.webClient.getPage("/sboot/vehicle.h
tml");
assertThat(page.getBody().getTextContent()).isEqualTo("H
ondaCivic");
}
}
在附录中可以查看 @WebMvcTest开启的自动配置列表。
40.3测试SpringBoot应用
315

40.3测试SpringBoot应用
316

40.3.8自动配置的DataJPA测试
你可以使用 @DataJpaTest测试JPA应用,它默认配置一个内存型的内嵌数据库,
扫描 @Entity类,并配置SpringDataJPA仓库,其他常规的 @Component
beans不会加载进 ApplicationContext。
DataJPA测试类是事务型的,默认在每个测试结束后回滚,具体查看Spring参考文
档的相关章节。如果这不是你想要的结果,可以通过禁用事务管理器来改变:
importorg.junit.Test;
importorg.junit.runner.RunWith;
importorg.springframework.boot.test.autoconfigure.orm.jpa.DataJ
paTest;
importorg.springframework.test.context.junit4.SpringRunner;
importorg.springframework.transaction.annotation.Propagation;
importorg.springframework.transaction.annotation.Transactional;
@RunWith(SpringRunner.class)
@DataJpaTest
@Transactional(propagation=Propagation.NOT_SUPPORTED)
publicclassExampleNonTransactionalTests{
}
DataJPA测试类可能会注入一个专为测试设计的 [TestEntityManager]
(https://github.com/spring-projects/spring-
boot/tree/v1.4.1.RELEASE/spring-boot-test-
autoconfigure/src/main/java/org/springframework/boot/test/autoconfig
ure/orm/jpa/TestEntityManager.java)bean以替换标准的JPA
EntityManager。如果想在 @DataJpaTests外使用 TestEntityManager,你
可以使用 @AutoConfigureTestEntityManager注解。如果需
要, JdbcTemplate也是可用的。
40.3测试SpringBoot应用
317

importorg.junit.*;
importorg.junit.runner.*;
importorg.springframework.boot.test.autoconfigure.orm.jpa.*;
importstaticorg.assertj.core.api.Assertions.*;
@RunWith(SpringRunner.class)
@DataJpaTest
publicclassExampleRepositoryTests{
@Autowired
privateTestEntityManagerentityManager;
@Autowired
privateUserRepositoryrepository;
@Test
publicvoidtestExample()throwsException{
this.entityManager.persist(newUser("sboot","1234"));
Useruser=this.repository.findByUsername("sboot");
assertThat(user.getUsername()).isEqualTo("sboot");
assertThat(user.getVin()).isEqualTo("1234");
}
}
对于测试来说,内存型的内嵌数据库通常是足够的,因为它们既快又不需要任何安
装。如果比较喜欢在真实数据库上运行测试,你可以使
用@AutoConfigureTestDatabase注解:
@RunWith(SpringRunner.class)
@DataJpaTest
@AutoConfigureTestDatabase(replace=Replace.NONE)
publicclassExampleRepositoryTests{
//...
}
40.3测试SpringBoot应用
318

40.3.9自动配置的REST客户端
你可以使用 @RestClientTest测试REST客户端,它默认会自动配置Jackson和
GSON,配置 RestTemplateBuilder,并添加 MockRestServiceServer支
持。你需要将 @RestClientTest的value或components属性值设置为待测试
类:
@RunWith(SpringRunner.class)
@RestClientTest(RemoteVehicleDetailsService.class)
publicclassExampleRestClientTest{
@Autowired
privateRemoteVehicleDetailsServiceservice;
@Autowired
privateMockRestServiceServerserver;
@Test
publicvoidgetVehicleDetailsWhenResultIsSuccessShouldReturn
Details()
throwsException{
this.server.expect(requestTo("/greet/details"))
.andRespond(withSuccess("hello",MediaType.TEXT_
PLAIN));
Stringgreeting=this.service.callRestService();
assertThat(greeting).isEqualTo("hello");
}
}
在附录中可以查看 @RestClientTest启用的自动配置列表。
40.3测试SpringBoot应用
320

40.3.10自动配置的SpringRESTDocs测试
如果想在测试类中使用SpringRESTDocs,你可以使
用@AutoConfigureRestDocs注解,它会自动配置 MockMvc去使用Spring
RESTDocs,并移除对SpringRESTDocs的JUnit规则的需要。
40.3测试SpringBoot应用
321

importorg.junit.Test;
importorg.junit.runner.RunWith;
importorg.springframework.beans.factory.annotation.Autowired;
importorg.springframework.boot.test.autoconfigure.web.servlet.W
ebMvcTest;
importorg.springframework.http.MediaType;
importorg.springframework.test.context.junit4.SpringRunner;
importorg.springframework.test.web.servlet.MockMvc;
importstaticorg.springframework.restdocs.mockmvc.MockMvcRestDo
cumentation.document;
importstaticorg.springframework.test.web.servlet.request.MockM
vcRequestBuilders.get;
importstaticorg.springframework.test.web.servlet.result.MockMv
cResultMatchers.*;
@RunWith(SpringRunner.class)
@WebMvcTest(UserController.class)
@AutoConfigureRestDocs("target/generated-snippets")
publicclassUserDocumentationTests{
@Autowired
privateMockMvcmvc;
@Test
publicvoidlistUsers()throwsException{
this.mvc.perform(get("/users").accept(MediaType.TEXT_PLA
IN))
.andExpect(status().isOk())
.andDo(document("list-users"));
}
}
此外,除了配置输出目录, @AutoConfigureRestDocs也能配置将出现在任何文
档化的URLs中的部分,比如host,scheme和port等。如果需要控制更多Spring
RESTDocs的配置,你可以使用 RestDocsMockMvcConfigurationCustomizer
bean:
40.3测试SpringBoot应用
322

@TestConfiguration
staticclassCustomizationConfiguration
implementsRestDocsMockMvcConfigurationCustomizer{
@Override
publicvoidcustomize(MockMvcRestDocumentationConfigurercon
figurer){
configurer.snippets().withTemplateFormat(TemplateFormats
.markdown());
}
}
如果想充分利用SpringRESTDocs对参数化输出目录的支持,你可以创建一
个RestDocumentationResultHandlerbean,自动配置将使用它调
用alwaysDo方法,进而促使每个 MockMvc调用都会自动产生默认片段:
@TestConfiguration
staticclassResultHandlerConfiguration{
@Bean
publicRestDocumentationResultHandlerrestDocumentation(){
returnMockMvcRestDocumentation.document("{method-name}"
);
}
}
40.3测试SpringBoot应用
323

40.3.11使用Spock测试SpringBoot应用
如果想使用Spock测试SpringBoot应用,你需要为应用添加Spock的spock-
spring依赖,该依赖已将Spring测试框架集成进Spock,怎么使用Spock测试
SpringBoot应用取决于你使用的Spock版本。
注SpringBoot为Spock1.0提供依赖管理,如果希望使用Spock1.1,你需要覆
盖build.gradle或pom.xml文件中的 spock.version属性。
当使用Spock1.1时,只能使用上述注解,你可以使用 @SpringBootTest注解你
的Specification以满足测试需求。
当使用Spock1.0时, @SpringBootTest将不能用于web项目,你需要使
用@SpringApplicationConfiguration和@WebIntegrationTest(randomPort
=true)。不能使用 @SpringBootTest也就意味着你失去了自动配置
的TestRestTemplatebean,不过可以通过以下配置创建一个等价的bean:
@Configuration
staticclassTestRestTemplateConfiguration{
@Bean
publicTestRestTemplatetestRestTemplate(
ObjectProvider<RestTemplateBuilder>builderProvider,
Environmentenvironment){
RestTemplateBuilderbuilder=builderProvider.getIfAvail
able();
TestRestTemplatetemplate=builder==null?newTestRe
stTemplate()
:newTestRestTemplate(builder.build());
template.setUriTemplateHandler(newLocalHostUriTemplateH
andler(environment));
returntemplate;
}
}
40.3测试SpringBoot应用
324

40.3测试SpringBoot应用
325

40.4测试工具类
一些测试工具类也打包进了 spring-boot,在测试时使用它们会有很大帮助。
40.4测试工具类
326

40.4.1ConfigFileApplicationContextInitializer
ConfigFileApplicationContextInitializer是一
个ApplicationContextInitializer,可在测试类中用于加载SpringBoot
的application.properties文件。当不需要使用 @SpringBootTest提供的全
部特性时,你可以使用它。
@ContextConfiguration(classes=Config.class,initializers=Conf
igFileApplicationContextInitializer.class)
注单独使用 ConfigFileApplicationContextInitializer不会提
供@Value("${…}")注入支持,它只负责确保 application.properties文件加
载进Spring的Environment。为了 @Value支持,你需要额外配置一
个PropertySourcesPlaceholderConfigurer或使用 @SpringBootTest为你自
动配置一个。
40.4测试工具类
327

40.4.2EnvironmentTestUtils
使用简单的 key=value字符串调用 EnvironmentTestUtils就可以快速添加属
性到 ConfigurableEnvironment或ConfigurableApplicationContext:
```javaEnvironmentTestUtils.addEnvironment(env,"org=Spring","name=Boot");
40.4测试工具类
328

40.4.3OutputCapture
OutputCapture是JUnit的一个 Rule,用于捕
获System.out和System.err输出,只需简单的将 @Rule注解capture,然后
在断言中调用 toString():
importorg.junit.Rule;
importorg.junit.Test;
importorg.springframework.boot.test.OutputCapture;
importstaticorg.hamcrest.Matchers.*;
importstaticorg.junit.Assert.*;
publicclassMyTest{
@Rule
publicOutputCapturecapture=newOutputCapture();
@Test
publicvoidtestName()throwsException{
System.out.println("HelloWorld!");
assertThat(capture.toString(),containsString("World"));
}
}
40.4测试工具类
329

40.4.4TestRestTemplate
在集成测试中,TestRestTemplate是Spring RestTemplate的便利替代。你可
以获取一个普通的或发送基本HTTP认证(使用用户名和密码)的模板,不管哪种
情况,这些模板都有益于测试:不允许重定向(这样你可以对响应地址进行断
言),忽略cookies(这样模板就是无状态的),对于服务端错误不会抛出异常。推
荐使用ApacheHTTPClient(4.3.2或更高版本),但不强制这样做,如果相关库在
classpath下存在, TestRestTemplate将以正确配置的client进行响应。
publicclassMyTest{
RestTemplatetemplate=newTestRestTemplate();
@Test
publicvoidtestRequest()throwsException{
HttpHeadersheaders=template.getForEntity("http://myhost.com",
String.class).getHeaders();
assertThat(headers.getLocation().toString(),containsString("myo
therhost"));
}
}
如果正在使用 @SpringBootTest,且设置
了WebEnvironment.RANDOM_PORT或WebEnvironment.DEFINED_PORT属性,你
可以注入一个配置完全的 TestRestTemplate,并开始使用它。如果有需要,你
还可以通过 RestTemplateBuilderbean进行额外的自定义:
40.4测试工具类
330

@RunWith(SpringRunner.class)
@SpringBootTest
publicclassMyTest{
@Autowired
privateTestRestTemplatetemplate;
@Test
publicvoidtestRequest()throwsException{
HttpHeadersheaders=template.getForEntity("http://myho
st.com",String.class).getHeaders();
assertThat(headers.getLocation().toString(),containsStr
ing("myotherhost"));
}
@TestConfiguration
staticclassConfig{
@Bean
publicRestTemplateBuilderrestTemplateBuilder(){
returnnewRestTemplateBuilder()
.additionalMessageConverters(...)
.customizers(...);
}
}
}
40.4测试工具类
331

43.创建自己的auto-configuration
如果你在公司里开发共享libraries,或者正在开发一个开源或商业library,你可能想
开发自己的自动配置(auto-configuration)。自动配置类可以打包到外部jars,并
且依旧可以被SpringBoot识别。自动配置可以关联一个"starter",用于提供auto-
configuration的代码及需要引用的libraries。我们首先讲解构建自己的auto-
configuration需要知道哪些内容,然后讲解创建自定义starter的常见步骤。
注可参考demo工程了解如何一步步创建一个starter。
43.创建自己的auto-configuration
334

43.1理解自动配置的beans
从底层来讲,自动配置(auto-configuration)是通过标准的 @Configuration类
实现的。此外, @Conditional注解用来约束自动配置生效的条件。通常自动配
置类需要使用 @ConditionalOnClass和@ConditionalOnMissingBean注解,
这是为了确保只有在相关的类被发现及没有声明自定义的 @Configuration时才
应用自动配置,具体查看 spring-boot-autoconfigure源码中
的@Configuration类( META-INF/spring.factories文件)。
43.1理解自动配置的beans
335

43.2定位自动配置候选者
SpringBoot会检查你发布的jar中是否存在 META-INF/spring.factories文件,
该文件中以 EnableAutoConfiguration为key的属性应该列出你的配置类:
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.mycorp.libx.autoconfigure.LibXAutoConfiguration,\
com.mycorp.libx.autoconfigure.LibXWebAutoConfiguration
你可以使用 @AutoConfigureAfter或@AutoConfigureBefore注解为配置类指
定特定的顺序。例如,如果你提供web-specific配置,你的类就需要应用
在WebMvcAutoConfiguration后面。
你也可以使用 @AutoconfigureOrder注解为那些相互不知道存在的自动配置类提
供排序,该注解语义跟常规的 @Order注解相同,但专为自动配置类提供顺序。
注自动配置类只能通过这种方式加载,确保它们定义在一个特殊的package中,特
别是不能成为组件扫描的目标。
43.2定位自动配置候选者
336

43.3条件注解
你几乎总是需要在自己的自动配置类里添加一个或更多的 @Conditional注
解。 @ConditionalOnMissingBean注解是一个常见的示例,开发者可以用它覆
盖自动配置类提供的默认行为。
SpringBoot包含很多 @Conditional注解,你可以在自己的代码中通过注
解@Configuration类或单独的 @Bean方法来重用它们。
43.3条件注解
337

43.3.2Bean条件
@ConditionalOnBean和@ConditionalOnMissingBean注解可以根据特定类是
否存在决定bean的包含,你可以使用 value属性指定beans(bytype),也可以
使用 name定义beans(byname), search属性用于限制搜索beans时需要考
虑的 ApplicationContext层次。
注你需要注意bean定义添加的顺序,因为这些条件的计算是基于目前处理内容
的。出于这个原因,我们推荐在自动配置类上只使
用@ConditionalOnBean和@ConditionalOnMissingBean注解(即使保证它们
在其他用户定义的beans后加载)。
注@ConditionalOnBean和@ConditionalOnMissingBean不会阻
止@Configuration类的创建,在类级别使用那些conditions跟使用注解标记每
个@Bean方法是等价的。
43.3条件注解
339

43.3.3Property条件
@ConditionalOnProperty注解可以根据一个Spring Environment属性来决定
是否包含配置,使用 prefix和name属性指定要检查的配置。默认情况下,任
何存在的只要不是 false的属性都会匹配,你也可以使
用havingValue和matchIfMissing属性创建更高级的检测。
43.3条件注解
340

43.3.4Resource条件
@ConditionalOnResource注解只在特定资源出现时才会包含配置,可以使用常
见的Spring约定命名资源,例如 file:/home/user/test.dat。
43.3条件注解
341

43.3.5WebApplication条件
@ConditionalOnWebApplication和@ConditionalOnNotWebApplication注
解可以根据应用是否为'web应用'来决定是否包含配置,web应用是任何使用Spring
WebApplicationContext,定义一个 session作用域,或有一
个StandardServletEnvironment的应用。
43.3条件注解
342

43.4创建自己的starter
一个完整的SpringBootstarter可能包含以下组件:
autoconfigure模块,包含自动配置类的代码。
starter模块,提供自动配置模块及其他有用的依赖,简而言之,添加本
starter就能开始使用该library。
注如果不需要将它们分离开来,你可以将自动配置代码和依赖管理放到一个单一模
块中。
43.4创建自己的starter
344

43.4.1命名
确保为你的starter提供一个合适的命名空间(namespace),模块名不要
以spring-boot作为开头,尽管使用一个不同的MavengroupId,未来我们可能
会为你正在做的自动配置提供官方支持。
这里是经验之谈,假设你正在为“acme”创建一个starter,命名自动配置模块
为acme-spring-boot-autoconfigure,命名starter为acme-spring-boot-
starter,如果只有一个模块结合它们,通常会使用 acme-spring-boot-
starter。
此外,如果你的starter提供配置keys,需要为它们提供一个合适的命名空间,特别
是不要使用SpringBoot的命名空间(比
如, server,management,spring等),这些是属于SpringBoot的,我们
可能会在将来以相同方式提高/修改它们,这可能会破坏你的东西。
确保触发meta-data生成,这样IDE辅助也就可以用于你的keys了,你可能想检查生
成的元数据( META-INF/spring-configuration-metadata.json)以确保keys
被正确的文档化。
43.4创建自己的starter
345

43.4.2自动配置模块
自动配置模块包含了使用该library需要的任何东西,它可能还包含配置的keys定义
(@ConfigurationProperties)和用于定义组件如何初始化的回调接口。
注你需要将对该library的依赖标记为可选的,这样在项目中添加该自动配置模块就
更容易了。如果你这样做,该library将不会提供,SpringBoot会回退到默认设置。
43.4创建自己的starter
346

43.4.3Starter模块
starter模块实际是一个空jar,它的目的是提供使用该library所需的必要依赖。不要
对添加你的starter的项目做任何假设,如果你正在自动配置的library需要其他
starters,一定要提到它。提供一个合适的默认依赖集可能比较困难,特别是存在大
量可选依赖时,你应该避免引入任何非必需的依赖。
43.4创建自己的starter
347

45.开启production-ready特性
spring-boot-actuator模块提供SpringBoot所有的production-ready特性,启用该特
性的最简单方式是添加 spring-boot-starter-actuator‘Starter’依赖。
执行器(Actuator)的定义:执行器是一个制造业术语,指的是用于移动或控制东
西的一个机械装置,一个很小的改变就能让执行器产生大量的运动。
按以下配置为Maven项目添加执行器:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
</dependencies>
对于Gradle,使用下面的声明:
dependencies{
compile("org.springframework.boot:spring-boot-starter-actuat
or")
}
45.开启production-ready特性
350

46.端点
执行器端点(endpoints)可用于监控应用及与应用进行交互,SpringBoot包含很
多内置的端点,你也可以添加自己的。例如, health端点提供了应用的基本健康
信息。端点暴露的方式取决于你采用的技术类型,大部分应用选择HTTP监控,端
点的ID映射到一个URL。例如, health端点默认映射到 /health。
下面的端点都是可用的:
ID 描述 是否
敏感
actuator 为其他端点提供基于超文本的导航页面,需要添加
SpringHATEOAS依赖 true
autoconfig 显示一个自动配置类的报告,该报告展示所有自动
配置候选者及它们被应用或未被应用的原因 true
beans 显示一个应用中所有SpringBeans的完整列表 true
configprops 显示一个所有 @ConfigurationProperties的集
合列表 true
dump 执行一个线程转储 true
env 暴露来自Spring ConfigurableEnvironment的属
性true
flyway 显示数据库迁移路径,如果有的话 true
health
展示应用的健康信息(当使用一个未认证连接访问
时显示一个简单的'status',使用认证连接访问则显
示全部信息详情)
false
info 显示任意的应用信息 false
liquibase 展示任何Liquibase数据库迁移路径,如果有的话 true
metrics 展示当前应用的'metrics'信息 true
mappings 显示一个所有 @RequestMapping路径的集合列表 true
shutdown 允许应用以优雅的方式关闭(默认情况下不启用) true
trace 显示trace信息(默认为最新的100条HTTP请求) true
如果使用SpringMVC,你还可以使用以下端点:
46.端点
351

ID 描述 是否
敏感
docs 展示Actuator的文档,包括示例请求和响应,需添
加spring-boot-actuator-docs依赖 false
heapdump 返回一个GZip压缩的 hprof堆转储文件 true
jolokia 通过HTTP暴露JMXbeans(依赖Jolokia)true
logfile
返回日志文件内容(如果设
置logging.file或logging.path属性),支持使
用HTTP Range头接收日志文件内容的部分信息
注:根据端点暴露的方式, sensitive属性可用做安全提示,例如,在使用
HTTP访问敏感(sensitive)端点时需要提供用户名/密码(如果没有启用web安
全,可能会简化为禁止访问该端点)。
46.端点
352

46.1自定义端点
使用Spring属性可以自定义端点,你可以设置端点是否开启( enabled),是否
敏感( sensitive),甚至改变它的 id。例如,下面
的application.properties改变 beans端点的敏感性及id,并启
用shutdown:
endpoints.beans.id=springbeans
endpoints.beans.sensitive=false
endpoints.shutdown.enabled=true
注:前缀 endpoints+.+name用于被配置端点的唯一标识。
默认情况,所有端点除了 shutdown以外都是开启的,你可以使
用endpoints.enabled属性指定可选端点是否启用。例如,所有端点除 info外
都被禁用:
endpoints.enabled=false
endpoints.info.enabled=true
同样地,你可以全局范围内设置所有端点的 sensitive标记,敏感标记默认取决
于端点类型(查看上面表格)。例如,所有端点除 info外都标记为敏感:
endpoints.sensitive=true
endpoints.info.sensitive=false
46.1自定义端点
353

46.2执行器MVC端点的超媒体支持
如果classpath下存在SpringHATEOAS库(比如,通过 spring-boot-starter-
hateoas或使用SpringDataREST),来自执行器(Actuator)的HTTP端点将使
用超媒体链接进行增强(hypermedialinks),也就是使用一个“导航页”汇总所有端
点链接,该页面默认路径为 /actuator。该实现也是一个端点,可以通过属性配
置它的路径( endpoints.actuator.path)及是否开启
(endpoints.actuator.enabled)。
当指定了一个自定义管理上下文路径时,“导航页”路径自动从 /actuator迁移到
管理上下文根目录。例如,如果管理上下文路径为 /management,那就可以通
过/management访问“导航页”。
如果classpath下存在HALBrowser(通过webjar:org.webjars:hal-browser,
或spring-data-rest-hal-browser),SpringBoot将提供一个以HALBrowser
格式的HTML“导航页”。
46.2执行器MVC端点的超媒体支持
354

46.3CORS支持
跨域资源共享(CORS)是一个W3C规范,用于以灵活的方式指定跨域请求的认证
类型,执行器的MVC端点也可以配置成支持该场景。
CORS支持默认是禁用的,只有在 endpoints.cors.allowed-origins属性设置
时才启用。以下配置允许来自 example.com域的 GET和POST调用:
endpoints.cors.allowed-origins=http://example.com
endpoints.cors.allowed-methods=GET,POST
注查看EndpointCorsProperties获取完整的配置选项列表。
46.3CORS支持
355

46.4添加自定义端点
如果添加一个 Endpoint类型的 @Bean,SpringBoot会自动通过JMX和
HTTP(如果有可用服务器)将该端点暴露出去。通过创建 MvcEndpoint类型的
bean可进一步定义HTTP端点,虽然该bean不是 @Controller,但仍能使
用@RequestMapping(和 @Managed*)暴露资源。
注如果你的用户需要一个单独的管理端口或地址,你可以将注
解@ManagementContextConfiguration的配置类添加到 /META-
INF/spring.factories中,且key
为org.springframework.boot.actuate.autoconfigure.ManagementContextC
onfiguration,这样该端点将跟其他MVC端点一样移动到一个子上下文中,通
过WebConfigurerAdapter可以为管理端点添加静态资源。
46.4添加自定义端点
356

46.6安全与HealthIndicators
HealthIndicators返回的信息通常有点敏感,例如,你可能不想将数据库服务
器的详情发布到外面。因此,在使用一个未认证的HTTP连接时,默认只会暴露健
康状态(healthstatus)。如果想将所有的健康信息暴露出去,你可以
把endpoints.health.sensitive设置为 false。
为防止'拒绝服务'攻击,Health响应会被缓存,你可以使
用endpoints.health.time-to-live属性改变默认的缓存时间(1000毫秒)。
46.6安全与HealthIndicators
358

46.6.1自动配置的HealthIndicators
SpringBoot在合适的时候会自动配置以下 HealthIndicators:
名称 描述
CassandraHealthIndicator 检查Cassandra数据库状况
DiskSpaceHealthIndicator 低磁盘空间检查
DataSourceHealthIndicator 检查是否能从 DataSource获取连接
ElasticsearchHealthIndicator 检查Elasticsearch集群状况
JmsHealthIndicator 检查JMS消息代理状况
MailHealthIndicator 检查邮件服务器状况
MongoHealthIndicator 检查Mongo数据库状况
RabbitHealthIndicator 检查Rabbit服务器状况
RedisHealthIndicator 检查Redis服务器状况
SolrHealthIndicator 检查Solr服务器状况
注使用 management.health.defaults.enabled属性可以禁用以上全
部HealthIndicators。
46.6安全与HealthIndicators
359

46.6.2编写自定义HealthIndicators
你可以注册实现HealthIndicator接口的Springbeans来提供自定义健康信息。你需
要实现 health()方法,并返回一个 Health响应,该响应需要包含一
个status和其他用于展示的详情。
importorg.springframework.boot.actuate.health.HealthIndicator;
importorg.springframework.stereotype.Component;
@Component
publicclassMyHealthimplementsHealthIndicator{
@Override
publicHealthhealth(){
interrorCode=check();//performsomespecifichealth
check
if(errorCode!=0){
returnHealth.down().withDetail("ErrorCode",errorC
ode).build();
}
returnHealth.up().build();
}
}
注对于给定 HealthIndicator的标识是beanname去掉 HealthIndicator后
缀剩下的部分。在以上示例中,可以在 my的实体中获取健康信息。
除SpringBoot预定义的 Status类型, Health也可以返回一个代表新的系统状
态的自定义 Status。在这种情况下,你需要提供一个 HealthAggregator接口
的自定义实现,或使用 management.health.status.order属性配置默认实现。
例如,假设一个新的,代码为 FATAL的Status被用于你的一
个HealthIndicator实现中。为了配置严重性级别,你需要将以下配置添加到
application属性文件中:
management.health.status.order=DOWN,OUT_OF_SERVICE,UNKNOWN,UP
46.6安全与HealthIndicators
360

如果使用HTTP访问health端点,你可能想要注册自定义的status,并使
用HealthMvcEndpoint进行映射。例如,你可以将 FATAL映射
为HttpStatus.SERVICE_UNAVAILABLE。
46.6安全与HealthIndicators
361

46.7.1自动配置的InfoContributors
SpringBoot会在合适的时候自动配置以下 InfoContributors:
名称 描述
EnvironmentInfoContributor 暴露 Environment中key为info的所
有key
GitInfoContributor 暴露git信息,如果存
在git.properties文件
BuildInfoContributor 暴露构建信息,如果存在 META-
INF/build-info.properties文件
注使用 management.info.defaults.enabled属性可禁用以上所
有InfoContributors。
46.7应用信息
363

46.7.2自定义应用info信息
通过设置Spring属性 info.*,你可以定义 info端点暴露的数据。所有
在info关键字下的 Environment属性都将被自动暴露,例如,你可以将以下配
置添加到 application.properties:
info.app.encoding=UTF-8
info.app.java.source=1.8
info.app.java.target=1.8
注你可以在构建时扩展info属性,而不是硬编码这些值。假设使用Maven,你可以
按以下配置重写示例:
info.app.encoding=@project.build.sourceEncoding@
info.app.java.source=@java.version@
info.app.java.target=@java.version@
46.7应用信息
364

46.7.3Git提交信息
info端点的另一个有用特性是,在项目构建完成后发布 git源码仓库的状态信
息。如果 GitPropertiesbean可用,SpringBoot将暴
露git.branch,git.commit.id和git.commit.time属性。
注如果classpath根目录存在 git.properties文件,SpringBoot将自动配
置GitPropertiesbean。查看Generategitinformation获取更多详细信息。
使用 management.info.git.mode属性可展示全部git信息(比
如git.properties全部内容):
management.info.git.mode=full
46.7应用信息
365

46.7.5编写自定义的InfoContributors
你可以注册实现了 InfoContributor接口的Springbeans来提供自定义应用信
息。以下示例暴露一个只有单个值的 example实体:
importjava.util.Collections;
importorg.springframework.boot.actuate.info.Info;
importorg.springframework.boot.actuate.info.InfoContributor;
importorg.springframework.stereotype.Component;
@Component
publicclassExampleInfoContributorimplementsInfoContributor{
@Override
publicvoidcontribute(Info.Builderbuilder){
builder.withDetail("example",
Collections.singletonMap("key","value"));
}
}
如果点击 info端点,你应该可以看到包含以下实体的响应:
{
"example":{
"key":"value"
}
}
46.7应用信息
367

47.基于HTTP的监控和管理
如果你正在开发一个SpringMVC应用,SpringBoot执行器自动将所有启用的端点
通过HTTP暴露出去。默认约定使用端点的 id作为URL路径,例如, health暴
露为 /health。
47.基于HTTP的监控和管理
368

47.1保护敏感端点
如果你的项目添加了‘SpringSecurity’依赖,所有通过HTTP暴露的敏感端点都会受
到保护,默认情况下会使用用户名为 user的基本认证(basicauthentication),
产生的密码会在应用启动时打印到控制台上。
注在应用启动时会记录生成的密码,具体搜索 Usingdefaultsecurity
password。
你可以使用Spring属性改变用户名,密码和访问端点需要的安全角色。例如,你可
以将以下配置添加到 application.properties中:
security.user.name=admin
security.user.password=secret
management.security.role=SUPERUSER
注如果不使用SpringSecurity,并且公开暴露HTTP端点,你应该慎重考虑启用哪
些端点,具体参考Section46.1,“Customizingendpoints”。
47.1保护敏感端点
369

47.2自定义管理端点路径
有时将所有管理端点划分到单个路径下是有用的。例如, /info可能已被应用占
用,你可以用 management.contextPath属性为管理端点设置一个前缀:
management.context-path=/manage
以上的 application.properties示例将把端点从 /{id}改
为/manage/{id}(比如 /manage/info)。
你也可以改变端点的 id(使用 endpoints.{name}.id)来改变MVC端点的默
认资源路径,合法的端点ids只能由字母数字组成(因为它们可以暴露到很多地方,
包括不允许特殊字符的JMX对象name)。MVC路径也可以通过配置 endpoints.
{name}.path来单独改变,SpringBoot不会校验这些值(所以你可以使用URL中
任何合法的字符)。例如,想要改变 /health端点路径为 /ping/me,你可以设
置endpoints.health.path=/ping/me。
注如果你提供一个自定义 MvcEndpoint,记得包含一个可设置的 path属性,
并像标准MVC端点那样将该属性默认设置为 /{id}(具体可参
考HealthMvcEndpoint)。如果你的自定义端点是一个 Endpoint(不
是MvcEndpoint),SpringBoot将会为你分配路径。
47.2自定义管理端点路径
370

47.4配置管理相关的SSL
当配置使用一个自定义端口时,管理服务器可以通过各种 management.ssl.*属
性配置自己的SSL。例如,以下配置允许通过HTTP访问管理服务器,通过HTTPS
访问主应用:
server.port=8443
server.ssl.enabled=true
server.ssl.key-store=classpath:store.jks
server.ssl.key-password=secret
management.port=8080
management.ssl.enable=false
或者,主应用服务器和管理服务器都使用SSL,但keystores不一样:
server.port=8443
server.ssl.enabled=true
server.ssl.key-store=classpath:main.jks
server.ssl.key-password=secret
management.port=8080
management.ssl.enable=true
management.ssl.key-store=classpath:management.jks
management.ssl.key-password=secret
47.4配置管理相关的SSL
371

47.5自定义管理服务器地址
你可以通过设置 management.address属性来定义管理端点使用的地址,这在你
只想监听内部或面向生产环境的网络,或只监听来自 localhost的连接时非常有
用。
注如果端口跟主应用服务器不一样,你只能监听一个不同的地址。
下面的application.properties示例不允许远程访问管理服务器:
management.port=8081
management.address=127.0.0.1
47.5自定义管理服务器地址
372

47.6禁用HTTP端点
如果不想通过HTTP暴露端点,你可以将管理端口设置为-1:
management.port=-1
47.6禁用HTTP端点
373

47.7HTTPhealth端点访问限制
health端点暴露的信息依赖于是否为匿名访问,应用是否受保护。默认情况下,
当匿名访问一个受保护的应用时,任何有关服务器的健康详情都被隐藏了,该端点
只简单的展示服务器运行状况(up或down)。此外,响应会被缓存一个可配置的
时间段以防止端点被用于'拒绝服务'攻击,你可以通过 endpoints.health.time-
to-live属性设置缓存时间(单位为毫秒),默认为1000毫秒,也就是1秒。
你可以增强上述限制,从而只允许认证用户完全访问一个受保护应用的 health端
点,将 endpoints.health.sensitive设为 true可以实现该效果,具体可查看
以下总结( sensitive标识值为"false"的默认加粗):
management.security.enabled endpoints.health.sensitive 未认
证
false false 全部
内容
false true
只能
查看
Status
true false
只能
查看
Status
true true
不能
查看
任何
内容
47.7HTTPhealth端点访问限制
374

48.基于JMX的监控和管理
Java管理扩展(JMX)提供了一种标准的监控和管理应用的机制。默认情况下,
SpringBoot在org.springframework.boot域下将管理端点暴露为JMX
MBeans。
48.基于JMX的监控和管理
375

48.1自定义MBean名称
MBean的名称通常产生于端点的id,例如, health端点被暴露
为org.springframework.boot/Endpoint/healthEndpoint。
如果应用包含多个Spring ApplicationContext,你会发现存在名称冲突。为了
解决这个问题,你可以将 endpoints.jmx.uniqueNames设置为 true,这样
MBean的名称总是唯一的。
你也可以自定义端点暴露的JMX域,具体可参考以
下application.properties示例:```propertiesendpoints.jmx.domain=myapp
endpoints.jmx.uniqueNames=true
48.1自定义MBean名称
376

48.2禁用JMX端点
如果不想通过JMX暴露端点,你可以将 endpoints.jmx.enabled属性设置
为false:
endpoints.jmx.enabled=false
48.2禁用JMX端点
377

48.3使用Jolokia通过HTTP实现JMX远程管理
Jolokia是一个JMX-HTTP桥,它提供了一种访问JMXbeans的替代方法。想要使用
Jolokia,只需添加 org.jolokia:jolokia-core的依赖。例如,使用Maven需要
添加以下配置:
<dependency>
<groupId>org.jolokia</groupId>
<artifactId>jolokia-core</artifactId>
</dependency>
然后在你的管理HTTP服务器上可以通过 /jolokia访问Jolokia。
48.3使用Jolokia通过HTTP实现JMX远程管理
378

48.3.1自定义Jolokia
Jolokia有很多配置,通常使用servlet参数进行设置,跟SpringBoot一块使用时可以
在application.properties中添加 jolokia.config.前缀的属性进行配置:
jolokia.config.debug=true
48.3使用Jolokia通过HTTP实现JMX远程管理
379

48.3.2禁用Jolokia
如果正在使用Jolokia,又不想让SpringBoot配置它,你只需要简单的
将endpoints.jolokia.enabled属性设置为 false:
endpoints.jolokia.enabled=false
48.3使用Jolokia通过HTTP实现JMX远程管理
380

49.使用远程shell进行监控和管理
SpringBoot支持集成一个称为'CRaSH'的Javashell,你可以在CRaSH中使用ssh或
telnet命令连接到运行的应用,项目中添加以下依赖可以启用远程shell支持:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-remote-shell</artifactId>
</dependency>
注如果想使用telnet访问,你还需添加对 org.crsh:crsh.shell.telnet的依
赖。
注CRaSH运行时需要JDK,因为它要动态编译命令。如果一个基本的 help命令
都运行失败,你很可能使用的是JRE。
49.使用远程shell进行监控和管理
381

49.1连接远程shell
远程shell默认监听端口为 2000,默认用户名为 user,密码为随机生成的,并
且在输出日志中会显示。如果应用使用SpringSecurity,该shell默认使用相同的配
置。如果不是,将使用一个简单的认证策略,你可能会看到类似这样的信息:
Usingdefaultpasswordforshellaccess:ec03e16c-4cf4-49ee-b745-
7c8255c1dd7e
Linux和OSX用户可以使用 ssh连接远程shell,Windows用户可以下载并安装
PuTTY。
$ssh-p2000user@localhost
user@localhost'spassword:
._________
/\\/___'_____(_)______\\\\
(()\___|'_|'_||'_\/_`|\\\\
\\/___)||_)|||||||(_||))))
'|____|.__|_||_|_||_\__,|////
=========|_|==============|___/=/_/_/_/
::SpringBoot::(v1.4.1.RELEASE)onmyhost
输入 help可以获取命令列表,SpringBoot提
供metrics,beans,autoconfig和endpoint命令。
49.1连接远程shell
382

49.2扩展远程shell
有很多有趣的方式可以用来扩展远程shell。
49.2扩展远程shell
384

49.2.1远程shell命令
你可以使用Groovy或Java编写其他的shell命令(具体参考CRaSH文档),Spring
Boot默认会搜索以下路径的命令:
classpath*:/commands/**
classpath*:/crash/commands/**
注设置 shell.command-path-patterns属性可以改变搜索路径。注如果使用可
执行存档(archive),shell依赖的所有类都必须打包进一个内嵌的jar,而不是直接
打包进可执行jar或war。
下面是一个从 src/main/resources/commands/hello.groovy加载的'hello'命
令:
packagecommands
importorg.crsh.cli.Usage
importorg.crsh.cli.Command
classhello{
@Usage("SayHello")
@Command
defmain(InvocationContextcontext){
return"Hello"
}
}
SpringBoot为InvocationContext添加一些其他属性,你可以在命令中访问它
们:
49.2扩展远程shell
385

属性名称 描述
spring.boot.version SpringBoot的版本
spring.version Spring核心框架的版本
spring.beanfactory 获取Spring的BeanFactory
spring.environment 获取Spring的Environment
49.2扩展远程shell
386

50.度量指标(Metrics)
SpringBoot执行器包含一个支持'gauge'和'counter'级别的度量指标服务,'gauge'记
录一个单一值,'counter'记录一个增量(增加或减少)。同时,SpringBoot提供一
个PublicMetrics接口,你可以实现它,从而暴露以上两种机制不能记录的指标,具
体参考SystemPublicMetrics。
所有HTTP请求的指标都被自动记录,所以如果点击 metrics端点,你可能会看
到类似以下的响应:
{
"counter.status.200.root":20,
"counter.status.200.metrics":3,
"counter.status.200.star-star":5,
"counter.status.401.root":4,
"gauge.response.star-star":6,
"gauge.response.root":2,
"gauge.response.metrics":3,
"classes":5808,
"classes.loaded":5808,
"classes.unloaded":0,
"heap":3728384,
"heap.committed":986624,
"heap.init":262144,
"heap.used":52765,
"mem":986624,
"mem.free":933858,
"processors":8,
"threads":15,
"threads.daemon":11,
"threads.peak":15,
"uptime":494836,
"instance.uptime":489782,
"datasource.primary.active":5,
"datasource.primary.usage":0.25
}
50.度量指标
388

此处,我们可以看到基本的 memory,heap,class
loading,processor和threadpool信息,连同一些HTTP指标。在该实例
中, root('/'),/metricsURLs分别返回 20次, 3次HTTP200响应,同
时可以看到 rootURL返回了 4次HTTP401(unauthorized)响应。双星号
(star-star)来自于被SpringMVC /**匹配到的请求(通常为静态资源)。
gauge展示了一个请求的最后响应时间,所以 root的最后请求响应耗时 2毫
秒,/metrics耗时 3毫秒。
注在该示例中,我们实际是通过HTTP的/metrics路径访问该端点的,这也就是
响应中出现 metrics的原因。
50.度量指标
389

50.1系统指标
SpringBoot会暴露以下系统指标:
系统内存总量( mem),单位:KB
空闲内存数量( mem.free),单位:KB
处理器数量( processors)
系统正常运行时间( uptime),单位:毫秒
应用上下文(应用实例)正常运行时间( instance.uptime),单位:毫秒
系统平均负载( systemload.average)
堆信息( heap,heap.committed,heap.init,heap.used),单
位:KB
线程信息( threads,thread.peak,thead.daemon)
类加载信息( classes,classes.loaded,classes.unloaded)
垃圾收集信息( gc.xxx.count, gc.xxx.time)
50.1系统指标
390

50.2数据源指标
SpringBoot会为应用中定义的每个支持的 DataSource暴露以下指标:
活动连接数( datasource.xxx.active)
连接池当前使用情况( datasource.xxx.usage)
所有数据源指标共用 datasoure.前缀,该前缀适用于每个数据源:
如果是主数据源(唯一可用的数据源或注解 @Primary的数据源)前缀
为datasource.primary。
如果数据源bean名称以 DataSource结尾,前缀就是bean的名称去
掉DataSource的部分(比如, batchDataSource的前缀
是datasource.batch)。
其他情况使用bean的名称作为前缀。
通过注册自定义版本的 DataSourcePublicMetricsbean,你可以覆盖部分或全
部的默认行为。SpringBoot默认提供支持所有数据源的元数据,如果喜欢的数据源
恰好不被支持,你可以添加其他的 DataSourcePoolMetadataProviderbeans,
具体参考 DataSourcePoolMetadataProvidersConfiguration。
50.2数据源指标
391

50.3缓存指标
SpringBoot会为应用中定义的每个支持的缓存暴露以下指标:
cache当前大小( cache.xxx.size)
命中率( cache.xxx.hit.ratio)
丢失率( cache.xxx.miss.ratio)
注缓存提供商没有以一致的方式暴露命中/丢失率,有些暴露的是聚合
(aggregated)值(比如,自从统计清理后的命中率),而其他暴露的是时序
(temporal)值(比如,最后一秒的命中率),具体查看缓存提供商的文档。
如果两个不同的缓存管理器恰巧定义了相同的缓存,缓存name将
以CacheManagerbean的name作为前缀。
注册自定义版本的 CachePublicMetrics可以部分或全部覆盖这些默认值,
SpringBoot默认为EhCache,Hazelcast,Infinispan,JCache和Guava提供统计。
如果喜欢的缓存库没被支持,你可以添加其他 CacheStatisticsProvider
beans,具体可参考 CacheStatisticsAutoConfiguration。
50.3缓存指标
392

50.4Tomcatsession指标
如果你使用Tomcat作为内嵌的servlet容器,SpringBoot将自动暴露session指标,
httpsessions.active和httpsessions.max分别提供活动的和最大的session
数量。
50.4Tomcatsession指标
393

50.5记录自己的指标
将CounterService或GaugeService注入到你的bean中可以记录自己的度量指
标: CounterService暴露 increment,decrement和reset方
法; GaugeService提供一个 submit方法。
下面是一个简单的示例,它记录了方法调用的次数:
importorg.springframework.beans.factory.annotation.Autowired;
importorg.springframework.boot.actuate.metrics.CounterService;
importorg.springframework.stereotype.Service;
@Service
publicclassMyService{
privatefinalCounterServicecounterService;
@Autowired
publicMyService(CounterServicecounterService){
this.counterService=counterService;
}
publicvoidexampleMethod(){
this.counterService.increment("services.system.myservice
.invoked");
}
}
注你可以将任何字符串用作度量指标的名称,但最好遵循所选存储/图形技术的指
南,MattAimonetti’sBlog中有一些好的关于Graphite的指南。
50.5记录自己的指标
394

50.6添加自己的公共指标
只要注册其他的 PublicMetrics实现beans,你就可以添加其他的度量指标,比
如计算metrics端点每次调用的次数。默认情况下,端点会聚合所有这样的beans,
通过定义自己的 MetricsEndpoint可以轻易改变这种情况。
50.6添加自己的公共指标
395

50.7使用Java8的特性
SpringBoot提供的 GaugeService和CounterService默认实现依赖于你使用的
Java版本。如果使用Java8(或更高版本),SpringBoot将实现切换为一个高性能
版本,该版本优化了写速度,底层使用原子内存buffers,而不是通过不可变但相对
昂贵的 Metric<?>类型(跟基于仓库的实现相比,counters大概快5倍,gauges
大概快2倍)。对于Java7,Dropwizard指标服务也是很有效的(使用了某些Java8
并发库),但它不记录指标值的时间戳。如果需要关注指标采集的性能,建议你使
用高性能的选项,并不要频繁读取指标信息,这样写入会本地缓存,只有在需要时
读取。
注如果使用Java8或Dropwizard,SpringBoot默认不会使用老
的MetricRepository和它的 InMemoryMetricRepository实现。
50.7使用Java8的特性
396

50.8指标写入,导出和聚合
SpringBoot提供几个标记接口 Exporter的实现,可用于将从内存buffers读取的
指标复制到一个分析和展示它们的地方。实际上,如果提供一个实
现MetricWriter接口(或 GaugeWriter用于简单场景)且注
解@ExportMetricWriter的@Bean,它将自动挂钩一个 Exporter并每5秒反
馈下指标更新(通过 spring.metrics.export.delay-millis配置)。此外,你
定义的所有注解 @ExportMetricReader的MetricReader,它们的值将被默认
exporter导出。
默认exporter是一个 MetricCopyExporter,它会优化自己不去复制那些从上次调
用以来没有变化的值(设置 spring.metrics.export.send-latest标识可以关
闭该优化)。注意Dropwizard MetricRegistry不支持时间戳,所以如果你使用
Dropwizard指标服务,该优化是不起作用的(每次都会复制全部指标)。
通过 spring.metrics.export.*属性可以设置导出的触发器( delay-
millis,includes,excludes和send-latest),特
殊MetricWriters的值可以通过 spring.metrics.export.triggers.
<name>.*设置,此处 <name>是bean的名称(或匹配bean名称的表达式)。
注如果关闭默认的 MetricRepository(比如使用Dropwizard指标服务),指标
的自动导出将禁用。你可以通过声明自定义类型的 MetricReader并注
解@ExportMetricReader来获取相同功能。
50.8指标写入,导出和聚合
397

50.8.1示例:导出到Redis
如果提供一个 RedisMetricRepository类型的 @Bean并注
解@ExportMetricWriter,指标将导出到Redis缓存完成聚
合。 RedisMetricRepository有两个重要参数用于配置实现这样的目
的: prefix和key(传递给构造器)。最好使用应用实例唯一的前缀(比如,
使用一个随机值及应用的逻辑name,这样可以关联相同应用的其他实
例)。“key”用来保持所有指标name的全局索引,所以它应该全局唯一,不管这对
于你的应用意味着什么(比如,相同系统的两个实例可以共享一个Redis缓存,如
果它们有不同的keys)。
示例:
@Bean
@ExportMetricWriter
MetricWritermetricWriter(MetricExportPropertiesexport){
returnnewRedisMetricRepository(connectionFactory,
export.getRedis().getPrefix(),export.getRedis().getKey())
;
}
application.properties:
spring.metrics.export.redis.prefix:metrics.mysystem.${spring.ap
plication.name:application}.${random.value:0000}
spring.metrics.export.redis.key:keys.metrics.mysystem
前缀最后由应用名和id组成,所以它可以用来标识具有相同逻辑名的processes分
组。
注设置 key和prefix都是非常重要的。key用于所有的仓库操作,并可以被多
个仓库共享。如果多个仓库共享一个key(比如你需要聚合它们的时候),你通常
有一个只读“master”仓库,它有一个简短的但可辨识的前缀(比
如metrics.mysystem),还有很多只写的仓库,这些仓库以master前缀开头
50.8指标写入,导出和聚合
398

(比如以上示例中为 metrics.mysystem.*)。这样从一个"master"仓库读取所
有keys是相当高效的,但使用较长的前缀读取一个子集就比较低效了(比如使用一
个写仓库)。
注以上示例使用 MetricExportProperties去注入和提取key和前缀,这是
SpringBoot提供的便利设施,用于配置合适的默认值,你也可以自己设值。
50.8指标写入,导出和聚合
399

50.8.2示例:导出到OpenTSDB
如果提供一个 OpenTsdbGaugeWriter类型的 @Bean并注
解@ExportMetricWriter,指标将导出到OpenTSDB完成聚
合。 OpenTsdbGaugeWriter有一个 url属性,你需要将它设置为OpenTSDB
的“/put”端点,比如 localhost:4242/api/put。它还有个 namingStrategy,
你可以自定义或配置以使指标匹配服务器上你需要的数据结构。默认它只传递指标
名作为OpenTSDB指标名,添加 domain标签(值
为org.springframework.metrics)和 process(值为命名策略的对象hash
值)。因此,在运行应用并产生一些指标后,你可以在TSDUI查看这些指标(默认
路径为 localhost:4242)。
示例:
curllocalhost:4242/api/query?start=1h-ago&m=max:counter.status.
200.root
[
{
"metric":"counter.status.200.root",
"tags":{
"domain":"org.springframework.metrics",
"process":"b968a76"
},
"aggregateTags":[],
"dps":{
"1430492872":2,
"1430492875":6
}
}
]
50.8指标写入,导出和聚合
400

50.8.3示例:导出到Statsd
想要将指标导出到Statsd,首先你需要确定添加了 com.timgroup:java-statsd-
client依赖(SpringBoot为它提供了依赖管理),然后
将spring.metrics.export.statsd.host属性添加
到application.properties文件中,连接将在 8125端口建立,除非设
置spring.metrics.export.statsd.port对默认值进行覆盖。使
用spring.metrics.export.statsd.prefix可以设置自定义前缀,此外,你可
以提供一个 StatsdMetricWriter类型的 @Bean并注
解@ExportMetricWriter:
@Value("${spring.application.name:application}.${random.value:00
00}")
privateStringprefix="metrics";
@Bean
@ExportMetricWriter
MetricWritermetricWriter(){
returnnewStatsdMetricWriter(prefix,"localhost",8125);
}
50.8指标写入,导出和聚合
401

50.8.4示例:导出到JMX
如果提供一个 JmxMetricWriter类型并注
解@ExportMetricWriter的@Bean,指标将作为MBeans暴露到本地服务器
(只要开启,SpringBootJMX自动配置会提供 MBeanExporter)。
示例:
@Bean
@ExportMetricWriter
MetricWritermetricWriter(MBeanExporterexporter){
returnnewJmxMetricWriter(exporter);
}
每个指标都暴露为单独的MBean,你可以将 ObjectNamingStrategy注
入JmxMetricWriter来指定 ObjectNames的格式。
50.8指标写入,导出和聚合
402

50.9聚合多个来源的指标
SpringBoot提供一个 AggregateMetricReader,用于合并来自不同物理来源的
指标。具有相同逻辑指标的来源只需将指标加上以句号分隔的前缀发布出去,
reader会聚合它们(通过截取指标名并丢掉前缀),计数器被求和,所有东西(比
如gauges)都采用最近的值。
这非常有用,特别是当有多个应用实例反馈数据到中央仓库(比如Redis),并且
你想展示结果。推荐将 MetricReaderPublicMetrics结果连接到 /metrics端
点。
示例:
@Autowired
privateMetricExportPropertiesexport;
@Bean
publicPublicMetricsmetricsAggregate(){
returnnewMetricReaderPublicMetrics(aggregatesMetricReader())
;
}
privateMetricReaderglobalMetricsForAggregation(){
returnnewRedisMetricRepository(this.connectionFactory,
this.export.getRedis().getAggregatePrefix(),this.export.g
etRedis().getKey());
}
privateMetricReaderaggregatesMetricReader(){
AggregateMetricReaderrepository=newAggregateMetricReader(
globalMetricsForAggregation());
returnrepository;
}
注上面的示例使用 MetricExportProperties注入和提取key和前缀,这是
SpringBoot提供的便利设施,并且默认值是合适的,它们是
在MetricExportAutoConfiguration中设置的。
50.9聚合多个来源的指标
403

注上面的 MetricReaders不是 @Beans,也没注解 @ExportMetricReader,
因为它们只收集和分析来自其他仓库的数据,不需要暴露自己的值。
50.9聚合多个来源的指标
404

50.10Dropwizard指标
当你声明对 io.dropwizard.metrics:metrics-core的依赖时,SpringBoot会
创建一个默认的 MetricRegistrybean。如果需要自定义,你可以注册自己
的@Bean实例。使用Dropwizard‘Metrics’library的用户会发现SpringBoot指标自
动发布到 com.codahale.metrics.MetricRegistry,来自 MetricRegistry的
指标也自动暴露到 /metrics端点。
使用Dropwizard指标时,默认
的CounterService和GaugeService被DropwizardMetricServices替换,
它是一个 MetricRegistry的包装器(所以你可以 @Autowired其中任意
services,并像平常那么使用它)。通过使用恰当的前缀类型标记你的指标名可以
创建特殊的Dropwizard指标服务(比如,gauges使
用timer.*,histogram.*,counters使用 meter.*)。
50.10Dropwizard指标
405

50.11消息渠道集成
如果存在名为 metricsChannel的MessageChannelbean,SpringBoot将创建
一个 MetricWriter将指标写入该渠道(channel)。writer自动挂钩一个
exporter,所以全部指标值都会出现在渠道上,订阅者就可以进行其他分析或动作
(提供渠道和订阅者取决于你)。
50.11消息渠道集成
406

51.审计
SpringBoot执行器有一个灵活的审计框架,一旦SpringSecurity处于活动状态(默
认抛出'authenticationsuccess','failure'和'accessdenied'异常),它就会发布事
件。这对于报告非常有用,同时可以基于认证失败实现一个锁定策略。为了自定义
发布的安全事件,你可以提供自己
的AbstractAuthenticationAuditListener,AbstractAuthorizationAudit
Listener实现。你也可以使用审计服务处理自己的业务事件。为此,你可以将存
在的 AuditEventRepository注入到自己的组件,并直接使用它,或者只是简单
地通过Spring ApplicationEventPublisher发
布AuditApplicationEvent(使用 ApplicationEventPublisherAware)。
51.审计
407

52.追踪(Tracing)
对于所有的HTTP请求SpringBoot自动启用追踪,你可以查看 trace端点获取最
近100条请求的基本信息:
[{
"timestamp":1394343677415,
"info":{
"method":"GET",
"path":"/trace",
"headers":{
"request":{
"Accept":"text/html,application/xhtml+xml,appli
cation/xml;q=0.9,*/*;q=0.8",
"Connection":"keep-alive",
"Accept-Encoding":"gzip,deflate",
"User-Agent":"Mozilla/5.0Gecko/Firefox",
"Accept-Language":"en-US,en;q=0.5",
"Cookie":"_ga=GA1.1.827067509.1390890128;..."
"Authorization":"Basic...",
"Host":"localhost:8080"
},
"response":{
"Strict-Transport-Security":"max-age=31536000;
includeSubDomains",
"X-Application-Context":"application:8080",
"Content-Type":"application/json;charset=UTF-8"
,
"status":"200"
}
}
}
},{
"timestamp":1394343684465,
...
}]
52.追踪
408

52.追踪
409

53.1扩展配置
在META-INF/spring.factories文件中,你可以激活创建PID文件
的listener(s),示例:
org.springframework.context.ApplicationListener=\
org.springframework.boot.actuate.system.ApplicationPidFileWriter
,
org.springframework.boot.actuate.system.EmbeddedServerPortFileWr
iter
53.1扩展配置
411

53.2以编程方式
你也可以通过调用 SpringApplication.addListeners(…)方法并传递相应
的Writer对象来激活一个监听器,该方法允许你通过 Writer构造器自定义文
件名和路径。
53.2以编程方式
412

55.部署到云端
对于大多数流行云PaaS(平台即服务)提供商,SpringBoot的可执行jars就是为它
们准备的。这些提供商往往要求你自己提供容器,它们只负责管理应用的进程(不
特别针对Java应用程序),所以它们需要一些中间层来将你的应用适配到云概念中
的一个运行进程。
两个流行的云提供商,Heroku和CloudFoundry,采取一个打包('buildpack')方
法。为了启动你的应用程序,不管需要什么,buildpack都会将它们打包到你的部署
代码:它可能是一个JDK和一个java调用,也可能是一个内嵌的webserver,或者是
一个成熟的应用服务器。buildpack是可插拔的,但你最好尽可能少的对它进行自定
义设置。这可以减少不受你控制的功能范围,最小化部署和生产环境的发散。
理想情况下,你的应用就像一个SpringBoot可执行jar,所有运行需要的东西都打包
到它内部。
本章节我们将看到在“GettingStarted”章节开发的简单应用是怎么在云端运行的。
55.部署到云端
414

55.1CloudFoundry
如果不指定其他打包方式,CloudFoundry会启用它提供的默认打包方式。Cloud
Foundry的Javabuildpack对Spring应用有出色的支持,包括SpringBoot。你可以部
署独立的可执行jar应用,也可以部署传统的 .war形式的应用。
一旦你构建应用(比如,使用 mvncleanpackage)并安装 cf命令行工具,你
可以使用下面的 cfpush命令(将路径指向你编译后的 .jar)来部署应用。在
发布应用前,确保你已登陆cf命令行客户端。
$cfpushacloudyspringtime-ptarget/demo-0.0.1-SNAPSHOT.jar
查看 cfpush文档获取更多可选项。如果相同目录下存在manifest.yml,Cloud
Foundry会使用它。
就此, cf将开始上传你的应用:
Uploadingacloudyspringtime...OK
Preparingtostartacloudyspringtime...OK
----->Downloadedapppackage(8.9M)
----->JavaBuildpacksource:system
----->DownloadingOpenJDK1.7.0_51from.../x86_64/openjdk-1.7
.0_51.tar.gz(1.8s)
ExpandingOpenJDKto.java-buildpack/open_jdk(1.2s)
----->DownloadingSpringAutoReconfigurationfrom0.8.7.../a
uto-reconfiguration-0.8.7.jar(0.1s)
----->Uploadingdroplet(44M)
Checkingstatusofapp'acloudyspringtime'...
0of1instancesrunning(1starting)
...
0of1instancesrunning(1down)
...
0of1instancesrunning(1starting)
...
1of1instancesrunning(1running)
Appstarted
55.1CloudFoundry
415

恭喜!应用现在处于运行状态!
检验部署应用的状态是很简单的:
$cfapps
Gettingapplicationsin...
OK
namerequestedstateinstancesmemorydisk
urls
...
acloudyspringtimestarted1/1512M1G
acloudyspringtime.cfapps.io
...
一旦CloudFoundry意识到你的应用已经部署,你就可以点击给定的应用URI,此处
是acloudyspringtime.cfapps.io/。
55.1CloudFoundry
416

55.1.1绑定服务
默认情况下,运行应用的元数据和服务连接信息被暴露为应用的环境变量(比
如$VCAP_SERVICES),采用这种架构的原因是因为CloudFoundry多语言特性
(任何语言和平台都支持作为buildpack),进程级别的环境变量是语言无关
(languageagnostic)的。
环境变量并不总是有利于设计最简单的API,所以SpringBoot自动提取它们,然后
将这些数据导入能够通过Spring Environment抽象访问的属性里:
@Component
classMyBeanimplementsEnvironmentAware{
privateStringinstanceId;
@Override
publicvoidsetEnvironment(Environmentenvironment){
this.instanceId=environment.getProperty("vcap.applicat
ion.instance_id");
}
//...
}
所有的CloudFoundry属性都以 vcap作为前缀,你可以使用vcap属性获取应用信
息(比如应用的公共URL)和服务信息(比如数据库证书),具体参
考CloudFoundryVcapEnvironmentPostProcessorJavadoc。
注:SpringCloudConnectors项目很适合比如配置数据源的任务,SpringBoot为它
提供了自动配置支持和一个 spring-boot-starter-cloud-connectorsstarter。
55.1CloudFoundry
417

55.2Heroku
Heroku是另外一个流行的Paas平台,你可以提供一个 Procfile来定义Heroku的
构建过程,它提供部署应用所需的指令。Heroku为Java应用分配一个端口,确保能
够路由到外部URI。
你必须配置你的应用监听正确的端口,下面是用于我们的starterREST应用
的Procfile:
web:java-Dserver.port=$PORT-jartarget/demo-0.0.1-SNAPSHOT.ja
r
SpringBoot将-D参数作为属性,通过Spring Environment实例访
问。 server.port配置属性适合于内嵌的Tomcat,Jetty或Undertow实例启用时
使用, $PORT环境变量被分配给HerokuPaas使用。
Heroku默认使用Java1.8,只要你的Maven或Gradle构建时使用相同的版本就没问
题(Maven用户可以设置 java.version属性)。如果你想使用JDK1.7,在你
的pom.xml和Procfile临近处创建一个 system.properties文件,在该文件
中添加以下设置:
java.runtime.version=1.7
这就是你需要做的所有内容,对于Heroku部署来说,经常做的工作就是使用 git
push将代码推送到生产环境。
$gitpushherokumaster
Initializingrepository,done.
Countingobjects:95,done.
Deltacompressionusingupto8threads.
Compressingobjects:100%(78/78),done.
Writingobjects:100%(95/95),8.66MiB|606.00KiB/s,done.
Total95(delta31),reused0(delta0)
----->Javaappdetected
55.2Heroku
418

----->InstallingOpenJDK1.8...done
----->InstallingMaven3.3.1...done
----->Installingsettings.xml...done
----->executing/app/tmp/cache/.maven/bin/mvn-B
-Duser.home=/tmp/build_0c35a5d2-a067-4abc-a232-14b1fb7a82
29
-Dmaven.repo.local=/app/tmp/cache/.m2/repository
-s/app/tmp/cache/.m2/settings.xml-DskipTests=trueclean
install
[INFO]Scanningforprojects...
Downloading:http://repo.spring.io/...
Downloaded:http://repo.spring.io/...(818Bat1.8KB/se
c)
....
Downloaded:http://s3pository.heroku.com/jvm/...(152KB
at595.3KB/sec)
[INFO]Installing/tmp/build_0c35a5d2-a067-4abc-a232-14b1
fb7a8229/target/...
[INFO]Installing/tmp/build_0c35a5d2-a067-4abc-a232-14b1
fb7a8229/pom.xml...
[INFO]--------------------------------------------------
----------------------
[INFO]BUILDSUCCESS
[INFO]--------------------------------------------------
----------------------
[INFO]Totaltime:59.358s
[INFO]Finishedat:FriMar0707:28:25UTC2014
[INFO]FinalMemory:20M/493M
[INFO]--------------------------------------------------
----------------------
----->Discoveringprocesstypes
Procfiledeclarestypes->web
----->Compressing...done,70.4MB
----->Launching...done,v6
http://agile-sierra-1405.herokuapp.com/deployedtoHerok
u
55.2Heroku
419

Togit@heroku.com:agile-sierra-1405.git
*[newbranch]master->master
现在你的应用已经启动并运行在Heroku。
55.2Heroku
420

55.3Openshift
Openshift是RedHat公共(和企业)PaaS解决方案。和Heroku相似,它也是通过运
行被git提交触发的脚本来工作的,所以你可以使用任何你喜欢的方式编写Spring
Boot应用启动脚本,只要Java运行时环境可用(这是在Openshift上可以要求的一
个标准特性)。为了实现这样的效果,你可以使用DIYCartridge,并
在.openshift/action_scripts下hooks你的仓库:
基本模式如下:
1.确保Java和构建工具已被远程安装,比如使用一个 pre_buildhook(默认会安
装Java和Maven,不会安装Gradle)。
2.使用一个 buildhook去构建你的jar(使用Maven或Gradle),比如:
#!/bin/bash
cd$OPENSHIFT_REPO_DIR
mvnpackage-s.openshift/settings.xml-DskipTests=true
3.添加一个调用 java-jar…的starthook
#!/bin/bash
cd$OPENSHIFT_REPO_DIR
nohupjava-jartarget/*.jar--server.port=${OPENSHIFT_DIY_PORT}
--server.address=${OPENSHIFT_DIY_IP}&
4.使用一个 stophook
55.3Openshift
421

#!/bin/bash
source$OPENSHIFT_CARTRIDGE_SDK_BASH
PID=$(ps-ef|grepjava.*\.jar|grep-vgrep|awk'{print$2
}')
if[-z"$PID"]
then
client_result"Applicationisalreadystopped"
else
kill$PID
fi
5.将内嵌的服务绑定到平台提供的 application.properties定义的环境变量,
比如:
spring.datasource.url:jdbc:mysql://${OPENSHIFT_MYSQL_DB_HOST}:$
{OPENSHIFT_MYSQL_DB_PORT}/${OPENSHIFT_APP_NAME}
spring.datasource.username:${OPENSHIFT_MYSQL_DB_USERNAME}
spring.datasource.password:${OPENSHIFT_MYSQL_DB_PASSWORD}
在Openshift的网站上有一篇runningGradleinOpenshift博客,如果想使用gradle构
建运行的应用可以参考它。
55.3Openshift
422

55.4Boxfuse和AmazonWebServices
Boxfuse的工作机制是将你的SpringBoot可执行jar或war转换进一个最小化的VM镜
像,该镜像不需改变就能部署到VirtualBox或AWS。Boxfuse深度集成SpringBoot
并使用你的SpringBoot配置文件自动配置端口和健康检查URLs,它将该信息用于
产生的镜像及它提供的所有资源(实例,安全分组,可伸缩的负载均衡等)。
一旦创建一个Boxfuseaccount,并将它连接到你的AWS账号,安装最新版Boxfuse
客户端,你就能按照以下操作将SpringBoot应用部署到AWS(首先要确保应用被
Maven或Gradle构建过,比如 mvncleanpackage):
$boxfuserunmyapp-1.0.jar-env=prod
更多选项可查看 boxfuserun文档,如果当前目录存在一个boxfuse.conf文件,
Boxfuse将使用它。
注如果你的可执行jar或war包含 application-boxfuse.properties文件,
Boxfuse默认在启动时会激活一个名为 boxfuse的Springprofile,然后在该profile
包含的属性基础上构建自己的配置。
此刻 boxfuse将为你的应用创建一个镜像并上传到AWS,然后配置并启动需要的
资源:
55.4Boxfuse和AmazonWebServices
423

FusingImageformyapp-1.0.jar...
Imagefusedin00:06.838s(53937K)->axelfontaine/myapp:1.0
Creatingaxelfontaine/myapp...
Pushingaxelfontaine/myapp:1.0...
Verifyingaxelfontaine/myapp:1.0...
CreatingElasticIP...
Mappingmyapp-axelfontaine.boxfuse.ioto52.28.233.167...
WaitingforAWStocreateanAMIforaxelfontaine/myapp:1.0ine
u-central-1(thismaytakeupto50seconds)...
AMIcreatedin00:23.557s->ami-d23f38cf
Creatingsecuritygroupboxfuse-sg_axelfontaine/myapp:1.0...
Launchingt2.microinstanceofaxelfontaine/myapp:1.0(ami-d23f3
8cf)ineu-central-1...
Instancelaunchedin00:30.306s->i-92ef9f53
WaitingforAWStobootInstancei-92ef9f53andPayloadtostart
athttp://52.28.235.61/...
Payloadstartedin00:29.266s->http://52.28.235.61/
RemappingElasticIP52.28.233.167toi-92ef9f53...
Waiting15sforAWStocompleteElasticIPZeroDowntimetransit
ion...
Deploymentcompletedsuccessfully.axelfontaine/myapp:1.0isup
andrunningathttp://myapp-axelfontaine.boxfuse.io/
你的应用现在应该已经在AWS上启动并运行了。
这里有篇在EC2部署SpringBoot应用的博客,Boxfuse官网也有Boxfuse集成Spring
Boot文档,你可以拿来作为参考。
55.4Boxfuse和AmazonWebServices
424

55.5GoogleAppEngine
GoogleAppEngine关联了Servlet2.5API,如果不做一些修改你是不能在其上部署
Spring应用的,具体查看本指南的Servlet2.5章节Container.md)。
55.5GoogleAppEngine
425

56.安装SpringBoot应用
除了使用 java-jar运行SpringBoot应用,制作在Unix系统完全可执行的应用也
是可能的,这会简化常见生产环境SpringBoot应用的安装和管理。在Maven中添加
以下plugin配置可以创建一个"完全可执行"jar:
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<executable>true</executable>
</configuration>
</plugin>
对于Gradle等价的配置如下:
applyplugin:'spring-boot'
springBoot{
executable=true
}
然后输入 ./my-application.jar运行应用( my-application是你的artifact
name)。
注完全可执行jars在文件前内嵌了一个额外脚本,目前不是所有工具都能接受这种
形式,所以你有时可能不能使用该技术。
注默认脚本支持大多数Linux分发版本,并在CentOS和Ubuntu上测试过。其他平
台,比如OSX和FreeBSD,可能需要使用自定义 embeddedLaunchScript。
注当一个完全可执行jar运行时,它会将jar的目录作为工作目录。
56.安装SpringBoot应用
426

56.1Unix/Linux服务
你可以使用 init.d或systemd启动SpringBoot应用,就像其他Unix/Linux服务
那样。
56.1Unix/Linux服务
427

56.1.2安装为Systemd服务
Systemd是SystemVinit系统的继任者,很多现代Linux分发版本都在使用,尽管你
可以继续使用 init.d脚本,但使用 systemd‘service’脚本启动SpringBoot应用
是有可能的。
假设你在 /var/myapp目录下安装一个SpringBoot应用,为了将它安装为一
个systemd服务,你需要按照以下示例创建一个脚本,比如命名
为myapp.service,然后将它放到 /etc/systemd/system目录下:
[Unit]
Description=myapp
After=syslog.target
[Service]
User=myapp
ExecStart=/var/myapp/myapp.jar
SuccessExitStatus=143
[Install]
WantedBy=multi-user.target
注记得根据你的应用改变 Description,User和ExecStart字段。
注意跟作为 init.d服务运行不同,使用 systemd这种方式运行应用,PID文件
和控制台日志文件表现是不同的,必须在‘service’脚本配置正确的字段,具体参
考serviceunitconfigurationmanpage。
使用以下命令标识应用自动在系统boot上启动:
$systemctlenablemyapp.service
具体详情可参考 mansystemctl。
56.1Unix/Linux服务
428

56.1.3自定义启动脚本
Maven或Gradle插件生成的默认内嵌启动脚本可以通过很多方法自定义,对于大多
数开发者,使用默认脚本和一些自定义通常就足够了。如果发现不能自定义需要的
东西,你可以使用 embeddedLaunchScript选项生成自己的文件。
在脚本生成时自定义
自定义写入jar文件的启动脚本元素是有意义的,例如,为 init.d脚本提
供description,既然知道这会展示到前端,你可能会在生成jar时提供它。
为了自定义写入的元素,你需要为SpringBootMaven或Gradle插件指
定embeddedLaunchScriptProperties选项。
以下是默认脚本支持的可代替属性:
56.1Unix/Linux服务
429

名称 描述
mode 脚本模式,默认为 auto
initInfoProvides
'INITINFO'部分的 Provides,对于Gradle
默认为 spring-boot-application,对于
Maven默认为 ${project.artifactId}
initInfoShortDescription
‘INITINFO’部分的 Short-Description,
对于Gradle默认为 SpringBoot
Application,对于Maven默认
为${project.name}
initInfoDescription
“INITINFO”部分的 Description,对于
Gradle默认为 SpringBoot
Application,对于Maven默认
为${project.description}(失败会回
退到 ${project.name})
initInfoChkconfig “INITINFO”部分的 chkconfig,默认
为23459901
confFolder CONF_FOLDER的默认值,默认为包含jar的
文件夹
logFolder LOG_FOLDER的默认值,只对 init.d服
务有效
pidFolder PID_FOLDER的默认值,只对 init.d服
务有效
useStartStopDaemon 如果 start-stop-daemon命令可用,它会
控制该实例,默认为 true
在脚本运行时自定义
对于需要在jar文件生成后自定义的项目,你可以使用环境变量或配置文件。
默认脚本支持以下环境变量:
56.1Unix/Linux服务
430

变量 描述
MODE
操作的模式,默认值依赖于jar
构建方式,通常为 auto(意
味着它会尝试通过检查它是否
为init.d目录的软连接来
推断这是不是一个init脚
本)。你可以显式将它设置
为service,这样`stop
start status
USE_START_STOP_DAEMON
如果 start-stop-daemon命
令可用,它将被用来控制该实
例,默认为 true
PID_FOLDER pid文件夹的根目录(默认
为/var/run)
LOG_FOLDER 存放日志文件的文件夹(默认
为/var/log)
CONF_FOLDER 读取 .conf文件的文件夹
LOG_FILENAME
存放于 LOG_FOLDER的日志
文件名(默认
为<appname>.log)
APP_NAME
应用名,如果jar运行自一个软
连接,脚本会猜测它的应用
名。如果不是软连接,或你想
显式设置应用名,这就很有用
了
RUN_ARGS 传递给程序的参数(Spring
Boot应用)
JAVA_HOME
默认使用 PATH指
定java的位置,但如果
在$JAVA_HOME/bin/java有
可执行文件,你可以通过该属
性显式设置
JAVA_OPTS JVM启动时传递的配置项
JARFILE 在脚本启动没内嵌其内的jar文
件时显式设置jar位置
DEBUG
如果shell实例的 -x标识有设
值,则你能轻松看到脚本的处
理逻辑
56.1Unix/Linux服务
431

注PID_FOLDER,LOG_FOLDER和LOG_FILENAME变量只对 init.d服务有
效。对于 systemd等价的自定义方式是使用‘service’脚本。
如果 JARFILE和APP_NAME出现异常,上面的设置可以使用一个 .conf文件进
行配置。该文件预期是放到跟jar文件临近的地方,并且名字相同,但后缀
为.conf而不是 .jar。例如,一个命名为 /var/myapp/myapp.jar的jar将使
用名为 /var/myapp/myapp.conf的配置文件:
myapp.conf
JAVA_OPTS=-Xmx1024M
LOG_FOLDER=/custom/log/folder
注如果不喜欢配置文件放到jar附近,你可以使用 CONF_FOLDER环境变量指定文件
的位置。
想要学习如何正确的保护文件可以参考theguidelinesforsecuringaninit.d
service.。
56.1Unix/Linux服务
432

SpringBootCLI
SpringBootCLI是一个命令行工具,如果想使用Spring进行快速开发可以使用它。
它允许你运行Groovy脚本,这意味着你可以使用熟悉的类Java语法,并且没有那么
多的模板代码。你可以通过SpringBootCLI启动新项目,或为它编写命令。
VII.SpringBootCLI
435

58.安装CLI
你可以手动安装SpringBootCLI,也可以使用SDKMAN!(SDK管理器)或
Homebrew,MacPorts(如果你是一个OSX用户),具体安装指令参考"Getting
started"的Section10.2,“InstallingtheSpringBootCLI”章节。
58.安装CLI
436

59.使用CLI
一旦安装好CLI,你可以输入 spring来运行它。如果不使用任何参数运
行spring,将会展现一个简单的帮助界面:
$spring
usage:spring[--help][--version]
<command>[<args>]
Availablecommandsare:
run[options]<files>[--][args]
Runaspringgroovyscript
...morecommandhelpisshownhere
你可以使用 help获取任何支持命令的详细信息,例如:
$springhelprun
springrun-Runaspringgroovyscript
usage:springrun[options]<files>[--][args]
OptionDescription
-----------------
--autoconfigure[Boolean]Addautoconfigurecompiler
transformations(default:true)
--classpath,-cpAdditionalclasspathentries
-e,--editOpenthefilewiththedefaultsystem
editor
--no-guess-dependenciesDonotattempttoguessdependencies
--no-guess-importsDonotattempttoguessimports
-q,--quietQuietlogging
-v,--verboseVerboseloggingofdependency
resolution
--watchWatchthespecifiedfileforchanges
59.使用CLI
437

version命令提供一个检查你正在使用的SpringBoot版本的快速方式:
$springversion
SpringCLIv1.4.1.RELEASE
59.使用CLI
438

59.1使用CLI运行应用
你可以使用 run命令编译和运行Groovy源代码。SpringBootCLI完全自包含,以
致于你不需要安装任何外部的Groovy。
下面是一个使用Groovy编写的"helloworld"web应用:
hello.grooy
@RestController
classWebApplication{
@RequestMapping("/")
Stringhome(){
"HelloWorld!"
}
}
编译和运行应用可以输入:
$springrunhello.groovy
你可以使用 --将命令行参数和"spring"命令参数区分开来,例如:
$springrunhello.groovy----server.port=9000
你可以使用 JAVA_OPTS环境变量设置JVM命令行参数,例如:
$JAVA_OPTS=-Xmx1024mspringrunhello.groovy
59.1使用CLI运行应用
439

59.1.1推断"grab"依赖
标准的Groovy包含一个 @Grab注解,它允许你声明对第三方库的依赖。这项有用
的技术允许Groovy以和Maven或Gradle相同的方式下载jars,但不需要使用构建工
具。
SpringBoot进一步延伸了该技术,它会基于你的代码尝试推导你"grab"哪个库。例
如,由于 WebApplication代码上使用了 @RestController注
解,"Tomcat"和"SpringMVC"将被获取(grabbed)。
下面items被用作"grabhints":
items Grabs
JdbcTemplate,NamedParameterJdbcTemplate,DataSource JDBC应用
@EnableJms JMS应用
@EnableCaching 缓存抽象
@Test JUnit
@EnableRabbit RabbitMQ
@EnableReactor 项目重构
extends Specification Spocktest
@EnableBatchProcessing SpringBatch
@MessageEndpoint,@EnableIntegrationPatterns Spring集成
@EnableDeviceResolver Spring
Mobile
@Controller,@RestController,@EnableWebMvc
SpringMVC
+内嵌
Tomcat
@EnableWebSecurity Spring
Security
@EnableTransactionManagement
Spring
Transaction
Management
注想要理解自定义是如何生效的,可以查看SpringBootCLI源码中的
CompilerAutoConfiguration子类。
59.1使用CLI运行应用
440

59.1使用CLI运行应用
441

59.1.3默认import语句
为了帮助你减少Groovy代码量,一些 import语句被自动包含进来了。注意上面
的示例中引用 @Component,@RestController和@RequestMapping而没有
使用全限定名或 import语句。
注:很多Spring注解在不使用 import语句的情况下可以正常工作。尝试运行你的
应用,看一下在添加imports之前哪些会失败。
59.1使用CLI运行应用
443

59.1.4自动创建main方法
跟等效的Java应用不同,你不需要在Groovy脚本中添加一个 publicstatic
voidmain(String[]args)方法。SpringBoot会使用你编译后的代码自动创建
一个 SpringApplication。
59.1使用CLI运行应用
444

59.1.5自定义依赖管理
默认情况下,CLI使用在解析 @Grab依赖时 spring-boot-dependencies声明的
依赖管理,其他的依赖管理会覆盖默认的依赖管理,并可以通
过@DependencyManagementBom注解进行配置。该注解的值必须是一个或多个
MavenBOMs的候选( groupId:artifactId:version)。
例如,以下声明:
@DependencyManagementBom("com.example.custom-bom:1.0.0")
将选择Maven仓库中 com/example/custom-versions/1.0.0/下的 custom-
bom-1.0.0.pom。
当指定多个BOMs时,它们会以声明次序进行应用,例如:
@DependencyManagementBom(["com.example.custom-bom:1.0.0",
"com.example.another-bom:1.0.0"])
意味着 another-bom的依赖将覆盖 custom-bom依赖。
能够使用 @Grab的地方,你同样可以使用 @DependencyManagementBom。然
而,为了确保依赖管理的一致次序,你在应用中至多使用一
次@DependencyManagementBom。SpringIOPlatform是一个非常有用的依赖元数
据源(SpringBoot的超集),例如:
@DependencyManagementBom('io.spring.platform:platform-
bom:1.1.2.RELEASE')。
59.1使用CLI运行应用
445

59.2测试你的代码
test命令允许你编译和运行应用程序的测试用例,常规使用方式如下:
$springtestapp.groovytests.groovy
Total:1,Success:1,:Failures:0
Passed?true
在这个示例中, test.groovy包含JUnit @Test方法或Spock
Specification类。所有的普通框架注解和静态方法在不使用 import导入的情
况下,仍旧可以使用。
下面是我们使用的 test.groovy文件(含有一个JUnit测试):
classApplicationTests{
@Test
voidhomeSaysHello(){
assertEquals("HelloWorld!",newWebApplication().home()
)
}
}
注如果有多个测试源文件,你可能倾向于将它们放到 test目录下。
59.2测试你的代码
446

59.3多源文件应用
你可以在所有接收文件输入的命令中使用shell通配符。这允许你轻松处理来自一个
目录下的多个文件,例如:
$springrun*.groovy
如果想将 test或spec代码从主应用代码中分离,这项技术就十分有用了:
$springtestapp/*.groovytest/*.groovy
59.3多源文件应用
447

59.4应用打包
你可以使用 jar命令打包应用程序为一个可执行的jar文件,例如:
$springjarmy-app.jar*.groovy
最终的jar包括编译应用产生的类和所有依赖,这样你就可以使用 java-jar来执
行它了。该jar文件也包含了来自应用classpath的实体。你可以使用 --
include和--exclude添加明确的路径(两者都是用逗号分割,同样都接收值
为'+'和'-'的前缀,'-'意味着它们将从默认设置中移除),默认包含(includes):
public/**,resources/**,static/**,templates/**,META-INF/**,*
默认排除(excludes):
.*,repository/**,build/**,target/**,**/*.jar,**/*.groovy
查看 springhelpjar可以获得更多信息。
59.4应用打包
448

59.5初始化新工程
init命令允许你使用start.spring.io在不离开shell的情况下创建一个新的项目,例
如:
$springinit--dependencies=web,data-jpamy-project
Usingserviceathttps://start.spring.io
Projectextractedto'/Users/developer/example/my-project'
这创建了一个 my-project目录,它是一个基于Maven且依赖 spring-boot-
starter-web和spring-boot-starter-data-jpa的项目。你可以使用 --
list参数列出该服务的能力。
$springinit--list
=======================================
Capabilitiesofhttps://start.spring.io
=======================================
Availabledependencies:
-----------------------
actuator-Actuator:Productionreadyfeaturestohelpyoumonit
orandmanageyourapplication
...
web-Web:Supportforfull-stackwebdevelopment,includingTom
catandspring-webmvc
websocket-Websocket:SupportforWebSocketdevelopment
ws-WS:SupportforSpringWebServices
Availableprojecttypes:
------------------------
gradle-build-GradleConfig[format:build,build:gradle]
gradle-project-GradleProject[format:project,build:gradle]
maven-build-MavenPOM[format:build,build:maven]
maven-project-MavenProject[format:project,build:maven](de
fault)
...
59.5初始化新工程
449

init命令支持很多选项,查看 help输出可以获得更多详情。例如,下面的命
令创建一个使用Java8和打包为 war的gradle项目:
$springinit--build=gradle--java-version=1.8--dependencies=w
ebsocket--packaging=warsample-app.zip
Usingserviceathttps://start.spring.io
Contentsavedto'sample-app.zip'
59.5初始化新工程
450

59.6使用内嵌shell
SpringBoot包括完整的BASH和zshshells的命令行脚本,如果这两种你都不使用
(可能你是一个Window用户),那你可以使用 shell命令启用一个集成shell。
$springshell
SpringBoot(v1.4.1.RELEASE)
HitTABtocomplete.Type\'help'andhitRETURNforhelp,and\
'exit'toquit.
从内嵌shell中可以直接运行其他命令:
$version
SpringCLIv1.4.1.RELEASE
内嵌shell支持ANSI彩色输出和tab补全,如果需要运行一个原生命令,你可以使
用!前缀,点击 ctrl-c将退出内嵌shell。
59.6使用内嵌shell
451

59.7为CLI添加扩展
使用 install命令可以为CLI添加扩展,该命令接收一个或多个格式
为group:artifact:version的artifact坐标集,例如:
$springinstallcom.example:spring-boot-cli-extension:1.0.0.REL
EASE
除安装你提供坐标的artifacts标识外,该artifacts的所有依赖也会被安装。
使用 uninstall可以卸载一个依赖,和 install命令一样,它也接收一个或多
个格式为 group:artifact:version的artifact坐标集,例如:
$springuninstallcom.example:spring-boot-cli-extension:1.0.0.R
ELEASE
它会通过你提供的坐标卸载相应的artifacts标识及它们的依赖。
为了卸载所有附加依赖,你可以使用 --all选项,例如:
$springuninstall--all
59.7为CLI添加扩展
452

60.使用GroovybeansDSL开发应用
Spring框架4.0版本对 beans{}"DSL"(借鉴自Grails)提供原生支持,你可以使用
相同格式在Groovy应用程序脚本中嵌入bean定义。有时这是引入外部特性的很好
方式,比如中间件声明,例如:
@Configuration
classApplicationimplementsCommandLineRunner{
@Autowired
SharedServiceservice
@Override
voidrun(String...args){
printlnservice.message
}
}
importmy.company.SharedService
beans{
service(SharedService){
message="HelloWorld"
}
}
你可以使用 beans{}混合位于相同文件的类声明,只要它们都处于顶级,或如果
喜欢的话,你可以将beansDSL放到一个单独的文件中。
60.使用GroovybeansDSL开发应用
453

构建工具插件
SpringBoot为Maven和Gradle提供构建工具插件,该插件提供各种各样的特性,包
括打包可执行jars。本章节提供关于插件的更多详情及用于扩展一个不支持的构建
系统所需的帮助信息。如果你是刚刚开始,那可能需要先阅读PartIII,“Using
SpringBoot”章节的“Chapter13,Buildsystems”。
VIII.构建工具插件
456

63.1包含该插件
想要使用SpringBootMaven插件只需简单地在你的pom.xml的plugins部分包含
相应的XML:
<?xmlversion="1.0"encoding="UTF-8"?>
<projectxmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="ht
tp://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0http:/
/maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<!--...-->
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>1.4.1.RELEASE</version>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
该配置会在Maven生命周期的 package阶段重新打包一个jar或war。下面的示例
展示在 target目录下既有重新打包后的jar,也有原始的jar:
63.1包含该插件
458

$mvnpackage
$lstarget/*.jar
target/myproject-1.0.0.jartarget/myproject-1.0.0.jar.original
如果不包含像上面那样的 <execution/>,你可以自己运行该插件(但只有在
package目标也被使用的情况),例如:
$mvnpackagespring-boot:repackage
$lstarget/*.jar
target/myproject-1.0.0.jartarget/myproject-1.0.0.jar.original
如果使用一个里程碑或快照版本,你还需要添加正确的 pluginRepository元
素:
<pluginRepositories>
<pluginRepository>
<id>spring-snapshots</id>
<url>http://repo.spring.io/snapshot</url>
</pluginRepository>
<pluginRepository>
<id>spring-milestones</id>
<url>http://repo.spring.io/milestone</url>
</pluginRepository>
</pluginRepositories>
63.1包含该插件
459

63.2打包可执行jar和war文件
一旦 spring-boot-maven-plugin被包含到你的 pom.xml中,SpringBoot就会
自动尝试使用 spring-boot:repackage目标重写存档以使它们能够执行。为了构
建一个jar或war,你应该使用常规的 packaging元素配置你的项目:
<?xmlversion="1.0"encoding="UTF-8"?>
<projectxmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="ht
tp://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0http:/
/maven.apache.org/xsd/maven-4.0.0.xsd">
<!--...-->
<packaging>jar</packaging>
<!--...-->
</project>
生成的存档在 package阶段会被SpringBoot增强。你想启动的main类即可以通过
指定一个配置选项,也可以通过为manifest添加一个 Main-Class属性这种常规的
方式实现。如果你没有指定一个main类,该插件会搜索带有 publicstaticvoid
main(String[]args)方法的类。
为了构建和运行一个项目的artifact,你可以输入以下命令:
$mvnpackage
$java-jartarget/mymodule-0.0.1-SNAPSHOT.jar
为了构建一个即可执行,又能部署到外部容器的war文件,你需要标记内嵌容器依
赖为"provided",例如:
63.2打包可执行jar和war文件
460

<?xmlversion="1.0"encoding="UTF-8"?>
<projectxmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="ht
tp://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0http:/
/maven.apache.org/xsd/maven-4.0.0.xsd">
<!--...-->
<packaging>war</packaging>
<!--...-->
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>
<!--...-->
</dependencies>
</project>
注具体参考“Section81.1,“Createadeployablewarfile””章节。
高级配置选项和示例可在插件信息页面获取。
63.2打包可执行jar和war文件
461

64.SpringBootGradle插件
SpringBootGradle插件为Gradle提供SpringBoot支持,它允许你打包可执行jar或
war存档,运行SpringBoot应用,使用 spring-boot-dependencies提供的依赖
管理。
64.SpringBootGradle插件
462

64.1包含该插件
想要使用SpringBootGradle插件,你只需简单的包含一个 buildscript依赖,
并应用 spring-boot插件:
buildscript{
dependencies{
classpath("org.springframework.boot:spring-boot-gradle-p
lugin:1.4.1.RELEASE")
}
}
applyplugin:'spring-boot'
如果使用的是一个里程碑或快照版本,你需要添加相应的 repositories引用:
buildscript{
repositories{
maven.url"http://repo.spring.io/snapshot"
maven.url"http://repo.spring.io/milestone"
}
//...
}
64.1包含该插件
463

64.2Gradle依赖管理
spring-boot插件自动应用DependencyManagementPlugin,并配置它导
入spring-boot-starter-parentbom。这提供了跟Maven用户喜欢的相似依赖
管理体验,例如,如果声明的依赖在bom中被管理的话,你就可以省略版本。为了
充分使用该功能,只需要想通常那样声明依赖,但将版本号设置为空:
dependencies{
compile("org.springframework.boot:spring-boot-starter-web")
compile("org.thymeleaf:thymeleaf-spring4")
compile("nz.net.ultraq.thymeleaf:thymeleaf-layout-dialect")
}
注你声明的 spring-bootGradle插件的版本决定了 spring-boot-starter-
parentbom导入的版本(确保可以重复构建)。你最好将 spring-bootgradle
插件版本跟SpringBoot版本保持一致,版本详细信息可以在附录中查看。
spring-boot插件对于没有指定版本的依赖只会提供一个版本。如果不想使用插
件提供的版本,你可以像平常那样在声明依赖的时候指定版本。例如:
dependencies{
compile("org.thymeleaf:thymeleaf-spring4:2.1.1.RELEASE")
}
64.2Gradle依赖管理
464

64.3打包可执行jar和war文件
一旦 spring-boot插件被应用到你的项目,它将使用 bootRepackage任务自动
尝试重写存档以使它们能够执行。为了构建一个jar或war,你需要按通常的方式配
置项目。
你想启动的main类既可以通过一个配置选项指定,也可以通过向manifest添加一
个Main-Class属性。如果你没有指定main类,该插件会搜索带有 public
staticvoidmain(String[]args)方法的类。
为了构建和运行一个项目artifact,你可以输入以下内容:
$gradlebuild
$java-jarbuild/libs/mymodule-0.0.1-SNAPSHOT.jar
为了构建一个即能执行也可以部署到外部容器的war包,你需要将内嵌容器依赖标
记为 providedRuntime,比如:
64.3打包可执行jar和war文件
465

...
applyplugin:'war'
war{
baseName='myapp'
version='0.5.0'
}
repositories{
jcenter()
maven{url"http://repo.spring.io/libs-snapshot"}
}
configurations{
providedRuntime
}
dependencies{
compile("org.springframework.boot:spring-boot-starter-web")
providedRuntime("org.springframework.boot:spring-boot-starte
r-tomcat")
...
}
注具体参考“Section81.1,“Createadeployablewarfile””。
64.3打包可执行jar和war文件
466

64.4就地(in-place)运行项目
为了在不先构建jar的情况下运行项目,你可以使用 bootRun任务:
$gradlebootRun
如果项目中添加了devtools,它将自动监控你的应用变动。此外,你可以运行应
用,这样静态classpath资源(比如,默认位于 src/main/resources下)在应用
运行期间将能够重新加载,这在开发期间是非常有用的:
bootRun{
addResources=true
}
让静态classpath资源可加载意味着 bootRun不使用 processResources任务的
输出,例如,当使用 bootRun调用时,你的应用将以未经处理的形式使用资源。
64.4就地(in-place)运行项目
467

64.5SpringBoot插件配置
Gradle插件自动扩展你的构建脚本DSL,它为脚本添加一个 springBoot元素以此
作为Boot插件的全局配置。你可以像配置其他Gradle扩展那样为 springBoot设
置相应的属性(下面有配置选项列表)。
springBoot{
backupSource=false
}
64.5SpringBoot插件配置
468

64.6Repackage配置
该插件添加了一个 bootRepackage任务,你可以直接配置它,比如:
bootRepackage{
mainClass='demo.Application'
}
下面是可用的配置选项:
64.6Repackage配置
469

名称 描述
enabled
布尔值,用于控制repackager的开关
(如果你只想要Boot的其他特性而不
是这个,那它就派上用场了)
mainClass
要运行的main类。如果没有指定,则
使用project属性 mainClassName。
如果该应用插件没有使用或没有定
义mainClassName,则搜索存档以
寻找一个合适的类。"合适"意味着一个
唯一的,具有良好格式的 main()方
法的类(如果找到多个则构建会失
败)。你也可以通过 run任务
(main属性)指定 main类的名
称,和/或
将"startScripts"(mainClassName属
性)作为"springBoot"配置的替代。
classifier
添加到存档的一个文件名字段(在扩
展之前),这样最初保存的存档仍旧
存放在最初的位置。在存档被重新打
包(repackage)的情况下,该属性默
认为 null。默认值适用于多数情
况,但如果你想在另一个项目中使用
原jar作为依赖,最好使用一个扩展来
定义该可执行jar
withJarTask Jar任务的名称或值,用于定位要被
repackage的存档
customConfiguration
自定义配置的名称,用于填充内嵌的
lib目录(不指定该属性,你将获取所
有编译和运行时依赖)
executable 布尔值标识,表示jar文件在类Unix系
统上是否完整可执行,默认为 false
embeddedLaunchScript
如果jar是完整可执行的,该内嵌启动
脚本将添加到jar。如果没有指定,将
使用SpringBoot默认的脚本
embeddedLaunchScriptProperties
启动脚本暴露的其他属性,默认脚本
支持 mode属性,值可以
是auto,service或run
excludeDevtools
布尔值标识,表示devtoolsjar是否应
该从重新打包的存档中排除出去,默
认为 false
64.6Repackage配置
470

64.6Repackage配置
471

64.7使用Gradle自定义配置进行Repackage
有时候不打包解析自 compile,runtime和provided作用域的默认依赖可能
更合适些。如果创建的可执行jar被原样运行,你需要将所有的依赖内嵌进该jar中;
然而,如果目的是explode一个jar文件,并手动运行main类,你可能
在CLASSPATH下已经有一些可用的库了。在这种情况下,你可以使用不同的依赖
集重新打包(repackage)你的jar。
使用自定义的配置将自动禁用来自 compile,runtime和provided作用域的
依赖解析。自定义配置即可以定义为全局的(处于 springBoot部分内),也可
以定义为任务级的。
taskclientJar(type:Jar){
appendix='client'
fromsourceSets.main.output
exclude('**/*Something*')
}
taskclientBoot(type:BootRepackage,dependsOn:clientJar){
withJarTask=clientJar
customConfiguration="mycustomconfiguration"
}
在以上示例中,我们创建了一个新的 clientJarJar任务从你编译后的源中打包
一个自定义文件集。然后我们创建一个新的 clientBootBootRepackage任务,
并让它使用 clientJar任务和 mycustomconfiguration。
configurations{
mycustomconfiguration.excludegroup:'log4j'
}
dependencies{
mycustomconfigurationconfigurations.runtime
}
64.7使用Gradle自定义配置进行Repackage
472

64.7.1配置选项
可用的配置选项如下:
名称 描述
mainClass 可执行jar运行的main类
providedConfiguration provided配置的名称(默认
为providedRuntime)
backupSource 在重新打包之前,原先的存档是否备份(默认
为true)
customConfiguration 自定义配置的名称
layout
存档类型,对应于内部依赖是如何制定的(默认
基于存档类型进行推测),具体查看available
layouts
requiresUnpack
一个依赖列表(格式为"groupId:artifactId",为
了运行,它们需要从fatjars中解压出来。)所有
节点被打包进胖jar,但运行的时候它们将被自
动解压
64.7使用Gradle自定义配置进行Repackage
474

64.7.2可用的layouts
layout属性用于配置存档格式及启动加载器是否包含,以下为可用的layouts:
名称 描述
可
执
行
JAR 常规的可执行JARlayout 是
WAR
可执行WARlayout,provided依赖放置到 WEB-
INF/lib-provided,以免 war部署到servlet容器时造成
冲突
是
ZIP(别
名DIR)跟JARlayout类似,使用PropertiesLauncher 是
MODULE 捆绑(Bundle)依赖(排除那些 provided作用域的依赖)和
项目资源 否
NONE 捆绑(Bundle)所有依赖和项目资源 否
64.7使用Gradle自定义配置进行Repackage
475

64.8理解Gradle插件是如何工作的
当spring-boot应用到你的Gradle项目,一个默认的名叫 bootRepackage的任
务被自动创建。 bootRepackage任务依赖于Gradle assemble任务,当执行
时,它会尝试找到所有限定符为空的jarartifacts(也就是说,tests和sourcesjars被
自动跳过)。
由于 bootRepackage会查找'所有'创建的jarartifacts,Gradle任务执行的顺序就非
常重要了。多数项目只创建一个单一的jar文件,所以通常这不是一个问题。然而,
如果你正打算创建一个更复杂的,使用自定义 jar和BootRepackage任务的项
目setup,有几个方面需要考虑。
如果'仅仅'从项目创建自定义jar文件,你可以简单地禁用默认
的jar和bootRepackage任务:
jar.enabled=false
bootRepackage.enabled=false
另一个选项是指示默认的 bootRepackage任务只能使用一个默认的 jar任务:
bootRepackage.withJarTask=jar
如果你有一个默认的项目setup,在该项目中,主(main)jar文件被创建和重新打
包。并且,你仍旧想创建额外的自定义jars,你可以将自定义的repackage任务结合
起来,然后使用 dependsOn,这样 bootJars任务就会在默认
的bootRepackage任务执行以后运行:
taskbootJars
bootJars.dependsOn=[clientBoot1,clientBoot2,clientBoot3]
build.dependsOn(bootJars)
上面所有方面经常用于避免一个已经创建的bootjar又被重新打包的情况。重新打包
一个存在的bootjar不是什么大问题,但你可能会发现它包含不必要的依赖。
64.8理解Gradle插件是如何工作的
476

64.8理解Gradle插件是如何工作的
477

64.9使用Gradle将artifacts发布到Maven仓库
如果声明依赖但没有指定版本,且想要将artifacts发布到一个Maven仓库,那你需
要使用详细的SpringBoot依赖管理来配置Maven发布。通过配置它发布继承
自spring-boot-starter-parent的poms或引入来自 spring-boot-
dependencies的依赖管理可以实现该需求。这种配置的具体细节取决于你如何使
用Gradle及如何发布该artifacts。
64.9使用Gradle将artifacts发布到Maven仓库
478

64.9.1自定义Gradle,用于产生一个继承依赖管理的
pom
下面示例展示了如何配置Gradle去产生一个继承自 spring-boot-starter-
parent的pom,更多信息请参考Gradle用户指南。
uploadArchives{
repositories{
mavenDeployer{
pom{
project{
parent{
groupId"org.springframework.boot"
artifactId"spring-boot-starter-parent"
version"1.4.1.RELEASE"
}
}
}
}
}
}
64.9使用Gradle将artifacts发布到Maven仓库
479

64.9.2自定义Gradle,用于产生一个导入依赖管理的
pom
以下示例展示了如何配置Gradle产生一个导入 spring-boot-dependencies提供
的依赖管理的pom,更多信息请参考Gradle用户指南。
uploadArchives{
repositories{
mavenDeployer{
pom{
project{
dependencyManagement{
dependencies{
dependency{
groupId"org.springframework.boo
t"
artifactId"spring-boot-dependen
cies"
version"1.4.1.RELEASE"
type"pom"
scope"import"
}
}
}
}
}
}
}
}
64.9使用Gradle将artifacts发布到Maven仓库
480

65.SpringBootAntLib模块
SpringBootAntLib模块为ApacheAnt提供基本的SpringBoot支持,你可以使用该
模块创建可执行的jars。在 build.xml添加额外的 spring-boot命名空间就可
以使用该模块了:
<projectxmlns:ivy="antlib:org.apache.ivy.ant"
xmlns:spring-boot="antlib:org.springframework.boot.ant"
name="myapp"default="build">
...
</project>
你需要记得在启动Ant时使用 -lib选项,例如:
$ant-lib<foldercontainingspring-boot-antlib-1.4.1.RELEASE.j
ar>
注详细示例可参考usingApacheAntwith spring-boot-antlib。
65.SpringBootAntLib模块
481

65.1.SpringBootAnt任务
一旦声明 spring-boot-antlib命名空间,以下任务就可用了。
65.SpringBootAntLib模块
482

65.1.1.spring-boot:exejar
exejar任务可用于创建SpringBoot可执行jar,该任务支持以下属性:
属性 描述 是否必须
destfile 将要创建的目的jar
文件 是
classes Java类文件的根目
录是
start-
class 运行的main类否(默认为找到的第一个声明 main方
法的类)
以下元素可以跟任务一块使用:
元素 描述
resources 一个或多个ResourceCollections,描述将添加到创建的jar文
件中的资源集合
lib 一个或多个ResourceCollections,表示需要添加进jar库的集
合,组成了应用运行时的classpath依赖
65.SpringBootAntLib模块
483

65.1.2.示例
指定start-class
<spring-boot:exejardestfile="target/my-application.jar"
classes="target/classes"start-class="com.foo.MyApplicat
ion">
<resources>
<filesetdir="src/main/resources"/>
</resources>
<lib>
<filesetdir="lib"/>
</lib>
</spring-boot:exejar>
探测start-class
<exejardestfile="target/my-application.jar"classes="target/cla
sses">
<lib>
<filesetdir="lib"/>
</lib>
</exejar>
65.SpringBootAntLib模块
484

65.2.spring-boot:findmainclass
findmainclass任务是 exejar内部用于定位声明 main方法类的,如果构建
需要,你可以直接使用该任务,支持属性如下:
属性 描述 是否必需
classesroot Java类文件的根目录 是(除非指定 mainclass)
mainclass 可用于缩减 main类的
查找 否
property Ant属性必须使用result
设值
否(没有指定则result会记录日
志中)
65.SpringBootAntLib模块
485

65.2.1.示例
查找并记录
<findmainclassclassesroot="target/classes"/>
查找并设置
<findmainclassclassesroot="target/classes"property="main-class"
/>
覆盖并设置
<findmainclassmainclass="com.foo.MainClass"property="main-clas
s"/>
65.SpringBootAntLib模块
486

66.1.重新打包存档
使用 org.springframework.boot.loader.tools.Repackager可以将一个存在
的存档重新打包,这样它就变成一个自包含的可执行存档。 Repackager类需要
提供单一的构造器参数,该参数指向一个存在的jar或war包。你可以使用两个可用
的repackage()方法中的一个来替换原始的文件或写入新的目标,在repackager
运行前还可以指定各种配置。
66.1.重新打包存档
488

66.2.内嵌库
当重新打包一个存档时,你可以使
用org.springframework.boot.loader.tools.Libraries接口来包含对依赖文
件的引用。在这里我们不提供任何该 Libraries接口的具体实现,因为它们通常
跟具体的构建系统相关。
如果存档已经包含libraries,你可以使用 Libraries.NONE。
66.2.内嵌库
489

66.4.repackage实现示例
这是一个典型的repackage示例:
Repackagerrepackager=newRepackager(sourceJarFile);
repackager.setBackupSource(false);
repackager.repackage(newLibraries(){
@Override
publicvoiddoWithLibraries(LibraryCallbackcallback)
throwsIOException{
//Buildsystemspecificimplementation,callbac
kforeachdependency
//callback.library(newLibrary(nestedFile,Libr
aryScope.COMPILE));
}
});
66.4.repackage实现示例
491

68.SpringBoot应用
68.SpringBoot应用
494

68.1创建自己的FailureAnalyzer
FailureAnalyzer是拦截启动时的异常并将它转换为可读消息的很好方式,Spring
Boot为应用上下文相关异常,JSR-303校验等提供分析器,实际上创建你自己的分
析器也相当简单。
AbstractFailureAnalyzer是FailureAnalyzer的一个方便扩展,根据指定类
型的异常是否出现来进行处理。你可以继承它,这样就可以处理实际出现的异常。
如果出于某些原因,不能处理该异常,那就返回 null让其他实现处理。
FailureAnalyzer的实现需要注册到 META-INF/spring.factories,以下注
册了 ProjectConstraintViolationFailureAnalyzer:
org.springframework.boot.diagnostics.FailureAnalyzer=\
com.example.ProjectConstraintViolationFailureAnalyzer
68.1创建自己的FailureAnalyzer
495

68.2解决自动配置问题
SpringBoot自动配置总是尝试尽最大努力去做正确的事,但有时候会失败并且很难
说出失败原因。
在每个SpringBoot ApplicationContext中都存在一个相当有用
的ConditionEvaluationReport。如果开启 DEBUG日志输出,你将会看到它。
如果你使用 spring-boot-actuator,则会有一个 autoconfig的端点,它将以
JSON形式渲染该报告。你还可以使用它调试应用程序,并能查看SpringBoot运行
时都添加了哪些特性(及哪些没添加)。
通过查看源码和javadoc可以获取更多问题的答案,以下是一些经验:
查找名为 *AutoConfiguration的类并阅读源码,特别
是@Conditional*注解,这可以帮你找出它们启用哪些特性及何时启用。
将--debug添加到命令行或添加系统属性 -Ddebug可以在控制台查看日
志,该日志会记录你的应用中所有自动配置的决策。在运行Actuator的app中,
通过查看 autoconfig端点( /autoconfig或等效的JMX)可以获取相同信
息。
查找 @ConfigurationProperties的类(比如ServerProperties)并看下有哪
些可用的外部配置选项。 @ConfigurationProperties类有一个用于充当外
部配置前缀的 name属性,因
此ServerProperties的prefix="server",它的配置属性
有server.port,server.address等。在运行Actuator的应用中可以查
看configprops端点。
查看 RelaxedPropertyResolver明确地将配置从 Environment暴露出去,
它经常会使用前缀。
查看 @Value注解,它直接绑定到 Environment。相
比RelaxedPropertyResolver,这种方式稍微缺乏灵活性,但它也允许松散
的绑定,特别是OS环境变量(所
以CAPITALS_AND_UNDERSCORES是period.separated的同义词)。
查看 @ConditionalOnExpression注解,它根据SpEL表达式的结果来开启或
关闭特性,通常使用解析自 Environment的占位符进行计算。
68.2解决自动配置问题
496

68.3启动前自定义Environment或
ApplicationContext
每个 SpringApplication都
有ApplicationListeners和ApplicationContextInitializers,用于自定
义上下文(context)或环境(environment)。SpringBoot从META-
INF/spring.factories下加载很多这样的内部使用的自定义,有很多方法可以注
册其他的自定义:
以编程方式为每个应用注册自定义,通过在 SpringApplication运行前调用
它的 addListeners和addInitializers方法来实现。
以声明方式为每个应用注册自定义,通过设
置context.initializer.classes或context.listener.classes来实
现。
以声明方式为所有应用注册自定义,通过添加一个 META-
INF/spring.factories并打包成一个jar文件(该应用将它作为一个库)来实
现。
SpringApplication会给监听器(即使是在上下文被创建之前就存在的)发送一
些特定的 ApplicationEvents,然后也会注册监听 ApplicationContext发布
的事件的监听器,查看SpringBoot特性章节中的Section23.5,“Applicationevents
andlisteners”可以获取完整列表。
在应用上下文刷新前使用 EnvironmentPostProcessor自定义 Environment是
可能的,每个实现都需要注册到 META-INF/spring.factories:
org.springframework.boot.env.EnvironmentPostProcessor=com.exampl
e.YourEnvironmentPostProcessor
68.3启动前自定义Environment或ApplicationContext
497

68.5创建no-web应用
不是所有的Spring应用都必须是web应用(或web服务)。如果你想在 main方法
中执行一些代码,但需要启动一个Spring应用去设置需要的底层设施,那使用
SpringBoot的SpringApplication特性可以很容易实
现。 SpringApplication会根据它是否需要一个web应用来改变它
的ApplicationContext类,首先你需要做的是去掉servletAPI依赖,如果不能
这样做(比如基于相同的代码运行两个应用),那你可以明确地调
用SpringApplication.setWebEnvironment(false)或设
置applicationContextClass属性(通过JavaAPI或使用外部配置)。你想运行
的,作为业务逻辑的应用代码可以实现为一个 CommandLineRunner,并将上下文
降级为一个 @Bean定义。
68.5创建no-web应用
498

69.1.运行时暴露属性
相对于在项目构建配置中硬编码某些配置,你可以使用已存在的构建配置自动暴露
它们,Maven和Gradle都支持。
69.1.运行时暴露属性
499

69.1.1.使用Maven自动暴露属性
你可以使用Maven的资源过滤(resourcefilter)自动暴露来自Maven项目的属性,
如果使用 spring-boot-starter-parent,你可以通过 @..@占位符引用Maven
项目的属性,例如:
app.encoding=@project.build.sourceEncoding@
app.java.version=@java.version@
注如果启用 addResources标识, spring-boot:run可以
将src/main/resources直接添加到classpath(出于热加载目的),这就绕过了
资源过滤和本特性。你可以使用 exec:java目标进行替代,或自定义该插件的配
置,具体查看插件使用页面。
如果不使用starterparent,你需要将以下片段添加到 pom.xml中( <build/>元
素内):
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
和( <plugins/>元素内):
69.1.运行时暴露属性
500

<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>2.7</version>
<configuration>
<delimiters>
<delimiter>@</delimiter>
</delimiters>
<useDefaultDelimiters>false</useDefaultDelimiters>
</configuration>
</plugin>
注如果你在配置中使用标准的Spring占位符(比如 ${foo})且没有
将useDefaultDelimiters属性设置为 false,那构建时这些属性将被暴露出
去。
69.1.运行时暴露属性
501

69.1.2.使用Gradle自动暴露属性
你可以通过配置Java插件的 processResources任务自动暴露来自Gradle项目的
属性:
processResources{
expand(project.properties)
}
然后你可以通过占位符引用Gradle项目的属性:
app.name=${name}
app.description=${description}
注Gradle的expand方法使用Groovy的SimpleTemplateEngine转换 ${..}占
位符, ${..}这种格式跟Spring自身的属性占位符机制冲突,想要自动暴露
Spring属性占位符,你需要将其进行编码,比如 \${..}。
69.1.运行时暴露属性
502

69.2.外部化SpringApplication配置
SpringApplication已经被属性化(主要是setters),所以你可以在创建应用时使用
它的JavaAPI修改其行为,或者使用以 spring.main.*为key的属性来外部化这
些配置。比如,在 application.properties中可能会有以下内容:
spring.main.web-environment=false
spring.main.banner-mode=off
这样,SpringBoot在启动时将不会显示banner,并且该应用也不是一个web应用。
注以上示例也展示在属性名中使用下划线( _)和中划线( -)的灵活绑定。
外部配置定义的属性会覆盖创建 ApplicationContext时通过JavaAPI指定的
值,让我们看如下应用:
newSpringApplicationBuilder()
.bannerMode(Banner.Mode.OFF)
.sources(demo.MyApp.class)
.run(args);
并使用以下配置:
spring.main.sources=com.acme.Config,com.acme.ExtraConfig
spring.main.banner-mode=console
实际的应用将显示banner(被配置覆盖),并为 ApplicationContext指定3个
sources,依次
为: demo.MyApp,com.acme.Config,com.acme.ExtraConfig。
69.2.外部化SpringApplication配置
503

69.3改变应用程序外部配置文件的位置
默认情况下,来自不同源的属性以一个定义好的顺序添加到Spring
的Environment中(精确顺序可查看'SprinBoot特性'章节的Chapter24,
ExternalizedConfiguration)。
为应用程序源添加 @PropertySource注解是一种很好的添加和修改源顺序的方
法。传递给 SpringApplication静态便利设施(convenience)方法的类和使
用setSources()添加的类都会被检查,以查看它们是否
有@PropertySources,如果有,这些属性会被尽可能早的添加
到Environment里,以确保 ApplicationContext生命周期的所有阶段都能使
用。以这种方式添加的属性优先级低于任何使用默认位置(比
如application.properties)添加的属性,系统属性,环境变量或命令行参
数。
你也可以提供系统属性(或环境变量)来改变该行为:
spring.config.name(SPRING_CONFIG_NAME)是根文件名,默认
为application。
spring.config.location(SPRING_CONFIG_LOCATION)是要加载的文
件(例如,一个classpath资源或URL)。SpringBoot为该文档设置一个单独
的Environment属性,它可以被系统属性,环境变量或命令行参数覆盖。
不管你在environment设置什么,SpringBoot都将加载上面讨论过
的application.properties。如果使用YAML,那具有 .yml扩展的文件默认
也会被添加到该列表,详情参考ConfigFileApplicationListener
69.3改变应用程序外部配置文件的位置
504

69.4使用'short'命令行参数
有些人喜欢使用(例如) --port=9000代替 --server.port=9000来设置命令
行配置属性。你可以通过在 application.properties中使用占位符来启用该功
能,比如:
server.port=${port:8080}
注如果你继承自 spring-boot-starter-parentPOM,为了防止和Spring格式
的占位符产生冲突, maven-resources-plugins默认的过滤令牌(filtertoken)
已经从 ${*}变为 @(即 @maven.token@代替 ${maven.token})。如果直接
启用maven对application.properties的过滤,你可能想使用其他的分隔符替
换默认的过滤令牌。
注在这种特殊的情况下,端口绑定能够在一个PaaS环境下工作,比如Heroku和
CloudFoundry,因为在这两个平台中 PORT环境变量是自动设置的,并且Spring
能够绑定 Environment属性的大写同义词。
69.4使用'short'命令行参数
505

69.5使用YAML配置外部属性
YAML是JSON的一个超集,可以非常方便的将外部配置以层次结构形式存储起来,
比如:
spring:
application:
name:cruncher
datasource:
driverClassName:com.mysql.jdbc.Driver
url:jdbc:mysql://localhost/test
server:
port:9000
创建一个 application.yml文件,将它放到classpath的根目录下,并添
加snakeyaml依赖(Maven坐标为 org.yaml:snakeyaml,如果你使
用spring-boot-starter那就已经包含了)。一个YAML文件会被解析为一个
Java Map<String,Object>(和一个JSON对象类似),SpringBoot会平伸该
map,这样它就只有1级深度,并且有period-separated的keys,跟人们在Java中经
常使用的 Properties文件非常类似。上面的YAML示例对应于下面
的application.properties文件:
spring.application.name=cruncher
spring.datasource.driverClassName=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost/test
server.port=9000
查看'SpringBoot特性'章节的Section24.6,“UsingYAMLinsteadofProperties”可以
获取更多关于YAML的信息。
69.5使用YAML配置外部属性
506

69.6设置生效的Springprofiles
Spring Environment有一个API可以设置生效的profiles,但通常你会通过系统属
性( spring.profiles.active)或OS环境变量
(SPRING_PROFILES_ACTIVE)设置。比如,使用一个 -D参数启动应用程序
(记着把它放到 main类或jar文件之前):
$java-jar-Dspring.profiles.active=productiondemo-0.0.1-SNAPS
HOT.jar
在SpringBoot中,你也可以在 application.properties里设置生效的profile,
例如:
spring.profiles.active=production
通过这种方式设置的值会被系统属性或环境变量替换,但不会
被SpringApplicationBuilder.profiles()方法替换。因此,后面的JavaAPI
可用来在不改变默认设置的情况下增加profiles。
想要获取更多信息可查看'SpringBoot特性'章节的Chapter25,Profiles。
69.6设置生效的Springprofiles
507

69.7根据环境改变配置
一个YAML文件实际上是一系列以 ---线分割的文档,每个文档都被单独解析为一
个平坦的(flattened)map。
如果一个YAML文档包含一个 spring.profiles关键字,那profiles的值(以逗号
分割的profiles列表)将被传入Spring的Environment.acceptsProfiles()方
法,并且如果这些profiles的任何一个被激活,对应的文档被包含到最终的合并中
(否则不会)。
示例:
server:
port:9000
---
spring:
profiles:development
server:
port:9001
---
spring:
profiles:production
server:
port:0
在这个示例中,默认的端口是 9000,但如果Springprofile development生效则
该端口是 9001,如果 production生效则它是 0。
YAML文档以它们出现的顺序合并,所以后面的值会覆盖前面的值。
想要使用profiles文件完成同样的操作,你可以使用 application-
${profile}.properties指定特殊的,profile相关的值。
69.7根据环境改变配置
508

69.8发现外部属性的内置选项
SpringBoot在运行时会将来自 application.properties(或 .yml)的外部属
性绑定到应用,因为不可能将所有支持的属性放到一个地方,classpath下的其他jar
也有支持的属性。
每个运行中且有Actuator特性的应用都会有一个 configprops端点,它能够展示
所有边界和可通过 @ConfigurationProperties绑定的属性。
附录中包含一个application.properties示例,它列举了SpringBoot支持的大多数常
用属性,查看 @ConfigurationProperties,@Value,还有不经常使用
的RelaxedEnvironment的源码可获取最权威的属性列表。
69.8发现外部属性的内置选项
509

70.内嵌servlet容器
70.内嵌servlet容器
510

70.1为应用添加Servlet,Filter或Listener
这里有两种方式可以为应用添
加Servlet,Filter,ServletContextListener和其他Servlet支持的特定
listeners。你既可以为它们提供Springbeans,也可以为Servlet组件启用扫描
(packagescan)。
70.1为应用添加Servlet,Filter或Listener
511

70.1.1使用Springbean添加Servlet,Filter或Listener
想要添加 Servlet,Filter或Servlet *Listener,你只需要为它提供一
个@Bean定义,这种方式很适合注入配置或依赖。不过,需要注意的是它们不会
导致其他很多beans的热初始化,因为它们需要在应用生命周期的早期进行安装
(让它依赖 DataSource或JPA配置不是好主意),你可以通过懒加载突破该限制
(在第一次使用时才初始化)。
对于 Filters或Servlets,你可以通
过FilterRegistrationBean或ServletRegistrationBean添加映射和初始化
参数。
注在一个filter注册时,如果没指定 dispatcherType,它将匹
配FORWARD,INCLUDE和REQUEST。如果启用异步,它也将匹配 ASYNC。如
果迁移 web.xml中没有 dispatcher元素的filter,你需要自己指定一
个dispatcherType:
@Bean
publicFilterRegistrationBeanmyFilterRegistration(){
FilterRegistrationBeanregistration=newFilterRegistration
Bean();
registration.setDispatcherTypes(DispatcherType.REQUEST);
....
returnregistration;
}
禁止Servlet或Filter的注册
如上所述,任何 Servlet或Filterbeans都将自动注册到servlet容器。不过,
为特定的 Filter或Servletbean创建一个registration,并将它标记为
disabled,可以禁用该filter或servlet。例如:
70.1为应用添加Servlet,Filter或Listener
512

@Bean
publicFilterRegistrationBeanregistration(MyFilterfilter){
FilterRegistrationBeanregistration=newFilterRegistration
Bean(filter);
registration.setEnabled(false);
returnregistration;
}
70.1为应用添加Servlet,Filter或Listener
513

70.1.2使用classpath扫描添加Servlets,Filters和
Listeners
通过把 @ServletComponentScan注解到一个 @Configuration类并指定包含要
注册组件的package(s),可以
将@WebServlet,@WebFilter和@WebListener注解的类自动注册到内嵌
servlet容器。默认情况下, @ServletComponentScan将从被注解类的package开
始扫描。
70.1为应用添加Servlet,Filter或Listener
514

70.2改变HTTP端口
在一个单独的应用中,主HTTP端口默认为 8080,不过可以使
用server.port设置(比如,在 application.properties中或作为系统属
性)。由于 Environment值的宽松绑定,你也可以使用 SERVER_PORT(比如,
作为OS环境变量)。
想要创建 WebApplicationContext但完全关闭HTTP端点,你可以设
置server.port=-1(测试时可能有用)。具体详情可查看'SpringBoot特性'章节
的Section27.3.4,“Customizingembeddedservletcontainers”,
或ServerProperties源码。
70.2改变HTTP端口
515

70.3使用随机未分配的HTTP端口
想扫描获取一个未使用的端口(使用操作系统本地端口以防冲突)可以设
置server.port=0。
70.3使用随机未分配的HTTP端口
516

70.4发现运行时的HTTP端口
你可以通过日志输出或它
的EmbeddedServletContainer的EmbeddedWebApplicationContext获取服务
器正在运行的端口。获取和确认服务器已经初始化的最好方式是添加一
个ApplicationListener<EmbeddedServletContainerInitializedEvent>类
型的 @Bean,然后当事件发布时将容器pull出来。
使用 @SpringBootTest(webEnvironment=WebEnvironment.RANDOM_PORT)进行
测试时,你可以通过 @LocalServerPort注解将实际端口注入到字段中,例如:
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(webEnvironment=WebEnvironment.RANDOM_PORT)
publicclassMyWebIntegrationTests{
@Autowired
EmbeddedWebApplicationContextserver;
@LocalServerPort
intport;
//...
}
注@LocalServerPort是@Value("${local.server.port}")的元数据,在常
规的应用中不要尝试注入端口。正如我们看到的,该值只会在容器初始化后设置。
相对于测试,应用代码回调处理的会更早(例如在该值实际可用之前)。
70.4发现运行时的HTTP端口
517

70.5配置SSL
你可以以声明方式配置SSL,一般通过
在application.properties或application.yml设置各种各样
的server.ssl.*属性,例如:
server.port=8443
server.ssl.key-store=classpath:keystore.jks
server.ssl.key-store-password=secret
server.ssl.key-password=another-secret
查看Ssl获取所有支持的配置。
使用类似于以上示例的配置意味着该应用将不支持端口为8080的普通HTTP连接。
SpringBoot不支持通过 application.properties同时配置HTTP连接器和
HTTPS连接器。如果你两个都想要,那就需要以编程的方式配置它们中的一个。推
荐使用 application.properties配置HTTPS,因为HTTP连接器是两个中最容
易以编程方式进行配置的,查看spring-boot-sample-tomcat-multi-connectors可获
取示例项目。
70.5配置SSL
518

70.6配置访问日志
通过相应的命令空间可以为Tomcat和Undertow配置访问日志,例如下面是为
Tomcat配置的一个自定义模式的访问日志:
server.tomcat.basedir=my-tomcat
server.tomcat.accesslog.enabled=true
server.tomcat.accesslog.pattern=%t%a"%r"%s(%Dms)
注日志默认路径为tomcat基础路径下的 logs目录,该dir默认是个临时目录,所
以你可能想改变Tomcat的base目录或为日志指定绝对路径。上述示例中,你可以在
相对于应用工作目录的 my-tomcat/logs访问到日志。
Undertow的访问日志配置方式类似:
server.undertow.accesslog.enabled=true
server.undertow.accesslog.pattern=%t%a"%r"%s(%Dms)
日志存储在相对于应用工作目录的 logs目录下,可以通
过server.undertow.accesslog.directory自定义。
70.6配置访问日志
519

70.7在前端代理服务器后使用
你的应用可能需要发送 302跳转或使用指向自己的绝对路径渲染内容。当在代理
服务器后面运行时,调用者需要的是代理服务器链接而不是部署应用的实际物理机
器地址,通常的解决方式是代理服务器将前端地址放到headers并告诉后端服务器
如何拼装链接。
如果代理添加约定的 X-Forwarded-For和X-Forwarded-Protoheaders(大多
数都是开箱即用的),只要将 application.properties中的 server.use-
forward-headers设置为 true,绝对链接就能正确的渲染。
注如果应用运行在CloudFoundry或Heroku,server.use-forward-headers属
性没指定的话默认为 true,其他实例默认为 false。
70.7在前端代理服务器后使用
520

70.7.1自定义Tomcat代理配置
如果使用的是Tomcat,你可以配置用于传输"forwarded"信息的headers名:
server.tomcat.remote-ip-header=x-your-remote-ip-header
server.tomcat.protocol-header=x-your-protocol-header
你也可以为Tomcat配置一个默认的正则表达式,用来匹配内部信任的代理。默认情
况下,IP地址 10/8,192.168/16,169.254/16和127/8是被信任的。通
过设置 server.tomcat.internal-proxies属性可以自定义,比如:
server.tomcat.internal-proxies=192\\.168\\.\\d{1,3}\\.\\d{1,3}
注只有在使用配置文件时才需要双反斜线,如果使用YAML,只需要单个反斜线,
比如 192\.168\.\d{1,3}\.\d{1,3}。
注将internal-proxies设置为空表示信任所有代理,不要在生产环境使用。
你可以完全控制Tomcat的RemoteIpValve配置,只要关掉自动配置(比如设
置server.use-forward-headers=false)并
在TomcatEmbeddedServletContainerFactorybean添加一个新value实例。
70.7在前端代理服务器后使用
521

70.8配置Tomcat
通常你可以遵循Section69.8,“Discoverbuilt-inoptionsforexternalproperties”关
于@ConfigurationProperties(这里主要的是 ServerProperties)的建
议,但也看下 EmbeddedServletContainerCustomizer和各种你可以添加的
Tomcat-specific的*Customizers。
TomcatAPIs相当丰富,一旦获取
到TomcatEmbeddedServletContainerFactory,你就能够以多种方式修改它,
或更彻底地就是添加你自己的 TomcatEmbeddedServletContainerFactory。
70.8配置Tomcat
522

70.9启用Tomcat的多连接器
你可以将 org.apache.catalina.connector.Connector添加
到TomcatEmbeddedServletContainerFactory,这就能够允许多连接器,比如
HTTP和HTTPS连接器:
70.9启用Tomcat的多连接器
523

@Bean
publicEmbeddedServletContainerFactoryservletContainer(){
TomcatEmbeddedServletContainerFactorytomcat=newTomcatEmb
eddedServletContainerFactory();
tomcat.addAdditionalTomcatConnectors(createSslConnector());
returntomcat;
}
privateConnectorcreateSslConnector(){
Connectorconnector=newConnector("org.apache.coyote.http1
1.Http11NioProtocol");
Http11NioProtocolprotocol=(Http11NioProtocol)connector.g
etProtocolHandler();
try{
Filekeystore=newClassPathResource("keystore").getFil
e();
Filetruststore=newClassPathResource("keystore").getF
ile();
connector.setScheme("https");
connector.setSecure(true);
connector.setPort(8443);
protocol.setSSLEnabled(true);
protocol.setKeystoreFile(keystore.getAbsolutePath());
protocol.setKeystorePass("changeit");
protocol.setTruststoreFile(truststore.getAbsolutePath())
;
protocol.setTruststorePass("changeit");
protocol.setKeyAlias("apitester");
returnconnector;
}
catch(IOExceptionex){
thrownewIllegalStateException("can'taccesskeystore:
["+"keystore"
+"]ortruststore:["+"keystore"+"]",ex);
}
}
70.9启用Tomcat的多连接器
524

70.9启用Tomcat的多连接器
525

70.10使用Tomcat的LegacyCookieProcessor
SpringBoot使用的内嵌Tomcat不能开箱即用的支持 Version0的Cookie格式,
你可能会看到以下错误:
java.lang.IllegalArgumentException:Aninvalidcharacter[32]wa
spresentintheCookievalue
可以的话,你需要考虑将代码升级到只存储遵从最新版Cookie定义的值。如果不能
改变写入的cookie,你可以配置Tomcat使用 LegacyCookieProcessor。通过
向EmbeddedServletContainerCustomizerbean添加一
个TomcatContextCustomizer可以开启 LegacyCookieProcessor:
70.10使用Tomcat的LegacyCookieProcessor
526

@Bean
publicEmbeddedServletContainerCustomizercookieProcessorCustomi
zer(){
returnnewEmbeddedServletContainerCustomizer(){
@Override
publicvoidcustomize(ConfigurableEmbeddedServletContain
ercontainer){
if(containerinstanceofTomcatEmbeddedServletContai
nerFactory){
((TomcatEmbeddedServletContainerFactory)contain
er)
.addContextCustomizers(newTomcatContext
Customizer(){
@Override
publicvoidcustomize(Contextcontext){
context.setCookieProcessor(newLegacyCoo
kieProcessor());
}
});
}
}
};
}
70.10使用Tomcat的LegacyCookieProcessor
527

70.11使用Jetty替代Tomcat
SpringBootstarters(特别是 spring-boot-starter-web)默认都使用Tomcat作
为内嵌容器。想使用Jetty替代Tomcat,你需要排除那些Tomcat的依赖并包含Jetty
的依赖。为了简化这种事情的处理,SpringBoot将Tomcat和Jetty的依赖捆绑在一
起,然后提供了单独的starters。
Maven示例:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jetty</artifactId>
</dependency>
Gradle示例:
configurations{
compile.excludemodule:"spring-boot-starter-tomcat"
}
dependencies{
compile("org.springframework.boot:spring-boot-starter-web:1.
4.1.RELEASE")
compile("org.springframework.boot:spring-boot-starter-jetty:
1.4.1.RELEASE")
//...
}
70.11使用Jetty替代Tomcat
528

70.11使用Jetty替代Tomcat
529

70.12配置Jetty
通常你可以遵循Section69.8,“Discoverbuilt-inoptionsforexternalproperties”关
于@ConfigurationProperties(此处主要是 ServerProperties)的建议,
但也要看下 EmbeddedServletContainerCustomizer。
JettyAPI相当丰富,一旦获取到 JettyEmbeddedServletContainerFactory,你
就可以使用很多方式修改它,或更彻底地就是添加你自己
的JettyEmbeddedServletContainerFactory。
70.12配置Jetty
530

70.13使用Undertow替代Tomcat
使用Undertow替代Tomcat和使用Jetty替代Tomcat非常类似。你需要排除Tomat依
赖,并包含Undertowstarter。
Maven示例:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-undertow</artifactId>
</dependency>
Gradle示例:
configurations{
compile.excludemodule:"spring-boot-starter-tomcat"
}
dependencies{
compile'org.springframework.boot:spring-boot-starter-web:1.
3.0.BUILD-SNAPSHOT")
compile'org.springframework.boot:spring-boot-starter-undert
ow:1.3.0.BUILD-SNAPSHOT")
//...
}
70.13使用Undertow替代Tomcat
531

70.13使用Undertow替代Tomcat
532

70.14配置Undertow
通常你可以遵循Section69.8,“Discoverbuilt-inoptionsforexternalproperties”关
于@ConfigurationProperties(此处主要
是ServerProperties和ServerProperties.Undertow),但也要看
下EmbeddedServletContainerCustomizer。
一旦获取到 UndertowEmbeddedServletContainerFactory,你就可以使
用UndertowBuilderCustomizer修改Undertow的配置以满足你的需求,或更彻
底地就是添加你自己的 UndertowEmbeddedServletContainerFactory。
70.14配置Undertow
533

70.15启用Undertow的多监听器
将UndertowBuilderCustomizer添加
到UndertowEmbeddedServletContainerFactory,然后使用 Builder添加一
个listener:
@Bean
publicUndertowEmbeddedServletContainerFactoryembeddedServletCo
ntainerFactory(){
UndertowEmbeddedServletContainerFactoryfactory=newUndert
owEmbeddedServletContainerFactory();
factory.addBuilderCustomizers(newUndertowBuilderCustomizer(
){
@Override
publicvoidcustomize(Builderbuilder){
builder.addHttpListener(8080,"0.0.0.0");
}
});
returnfactory;
}
70.15启用Undertow的多监听器
534

70.16使用Tomcat7.x或8.0
SpringBoot可以使用Tomcat7&8.0,但默认使用的是Tomcat8.5。如果不能使用
Tomcat8.5(例如,因为你使用的是Java1.6),你需要改变classpath去引用一个不
同版本。
70.16使用Tomcat7.x或8.0
535

70.16.1通过Maven使用Tomcat7.x或8.0
如果正在使用starters和parent,你只需要改变Tomcat的version属性,并添
加tomcat-juli依赖。比如,对于一个简单的webapp或service:
<properties>
<tomcat.version>7.0.59</tomcat.version>
</properties>
<dependencies>
...
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.apache.tomcat</groupId>
<artifactId>tomcat-juli</artifactId>
<version>${tomcat.version}</version>
</dependency>
...
</dependencies>
70.16使用Tomcat7.x或8.0
536

70.16.2通过Gradle使用Tomcat7.x或8.0
对于Gradle,你可以通过设置 tomcat.version属性改变Tomcat的版本,然后添
加tomcat-juli依赖:
ext['tomcat.version']='7.0.59'
dependencies{
compile'org.springframework.boot:spring-boot-starter-web'
compilegroup:'org.apache.tomcat',name:'tomcat-juli',versi
on:property('tomcat.version')
}
70.16使用Tomcat7.x或8.0
537

70.17使用Jetty9.2
SpringBoot可以使用Jetty9.2,但默认使用的是Jetty9.3。如果不能使用
Jetty9.3(例如,因为你使用的是Java7),你需要改变classpath去引用Jetty9.2。
70.17使用Jetty9.2
538

70.17.1通过Maven使用Jetty9.2
如果正在使用starters和parent,你只需添加Jettystarter并覆盖 jetty.version属
性:
<properties>
<jetty.version>9.2.17.v20160517</jetty.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifact
Id>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jetty</artifactId>
</dependency>
</dependencies>
70.17使用Jetty9.2
539

70.17.2通过Gradle使用Jetty9.2
对于Gradle,你需要设置 jetty.version属性,例如对于一个简单的webapp或
service:
ext['jetty.version']='9.2.17.v20160517'
dependencies{
compile('org.springframework.boot:spring-boot-starter-web')
{
excludegroup:'org.springframework.boot',module:'spri
ng-boot-starter-tomcat'
}
compile('org.springframework.boot:spring-boot-starter-jetty'
)
}
70.17使用Jetty9.2
540

70.18使用Jetty8
SpringBoot支持Jetty8,但默认使用的是Jetty9.3。如果不能使用Jetty9.3(比如
因为你使用的是Java1.6),你需要改变classpath去引用Jetty8,还需要排除Jetty
的WebSocket相关依赖。
70.18使用Jetty8
541

70.18.1通过Maven使用Jetty8
如果正在使用starters和parent,你只需要添加Jettystarter,排除那些需要的
WebSocket,并改变version属性。比如,对于一个简单的webapp或service:
<properties>
<jetty.version>8.1.15.v20140411</jetty.version>
<jetty-jsp.version>2.2.0.v201112011158</jetty-jsp.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifact
Id>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jetty</artifactId>
<exclusions>
<exclusion>
<groupId>org.eclipse.jetty.websocket</groupId>
<artifactId>*</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
70.18使用Jetty8
542

70.18.2通过Gradle使用Jetty8
你可以设置 jetty.version属性并排除相关的WebSocket依赖,比如对于一个简
单的webapp或service:
ext['jetty.version']='8.1.15.v20140411'
dependencies{
compile('org.springframework.boot:spring-boot-starter-web')
{
excludegroup:'org.springframework.boot',module:'spri
ng-boot-starter-tomcat'
}
compile('org.springframework.boot:spring-boot-starter-jetty'
){
excludegroup:'org.eclipse.jetty.websocket'
}
}
70.18使用Jetty8
543

70.19使用@ServerEndpoint创建WebSocket端点
如果想在使用内嵌容器的SpringBoot应用中使用 @ServerEndpoint,你需要声明
一个单独的 ServerEndpointExporter@Bean:
@Bean
publicServerEndpointExporterserverEndpointExporter(){
returnnewServerEndpointExporter();
}
该bean将使用底层的WebSocket容器注册任何被 @ServerEndpoint注解的
beans。当部署到一个单独的servlet容器时,该角色将被一个servlet容器初始化方
法执行, ServerEndpointExporterbean也就不需要了。
70.19使用@ServerEndpoint创建WebSocket端点
544

71.SpringMVC
71.SpringMVC
545

71.1编写JSONREST服务
只要添加的有Jackson2依赖,SpringBoot应用中的任何 @RestController默认
都会渲染为JSON响应,例如:
@RestController
publicclassMyController{
@RequestMapping("/thing")
publicMyThingthing(){
returnnewMyThing();
}
}
只要 MyThing能够通过Jackson2序列化(比如,一个标准的POJO或Groovy对
象),默认localhost:8080/thing将响应一个JSON数据。有时在浏览器中你可能看
到XML响应,因为浏览器倾向于发送XMLacceptheaders。
71.1编写JSONREST服务
546

71.2编写XMLREST服务
如果classpath下存在JacksonXML扩展( jackson-dataformat-xml),它会被
用来渲染XML响应,示例和JSON的非常相似。想要使用它,只需为你的项目添加
以下依赖:
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-xml</artifactId>
</dependency>
你可能还需要添加Woodstox的依赖,它比JDK提供的默认StAX实现快很多,并且
支持良好的格式化输出,提高了namespace处理能力:
<dependency>
<groupId>org.codehaus.woodstox</groupId>
<artifactId>woodstox-core-asl</artifactId>
</dependency>
如果Jackson的XML扩展不可用,SpringBoot将使用JAXB(JDK默认提供),不
过MyThing需要注解 @XmlRootElement:
@XmlRootElement
publicclassMyThing{
privateStringname;
//..gettersandsetters
}
想要服务器渲染XML而不是JSON,你可能需要发送一个 Accept:text/xml头部
(或使用浏览器)。
71.2编写XMLREST服务
547

71.3自定义JacksonObjectMapper
在一个HTTP交互中,SpringMVC(客户端和服务端)使
用HttpMessageConverters协商内容转换。如果classpath下存在Jackson,你就
获取到 Jackson2ObjectMapperBuilder提供的默认转换器,这是SpringBoot为
你自动配置的实例。
创建的 ObjectMapper(或用于JacksonXML转换的 XmlMapper)实例默认有以
下自定义属性:
MapperFeature.DEFAULT_VIEW_INCLUSION,默认是禁用的
DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES,默认是禁用的
SpringBoot也有一些用于简化自定义该行为的特性。
你可以使用当前的environment配置 ObjectMapper和XmlMapper实例。
Jackson提供一个扩展套件,可以用来关闭或开启一些特性,你可以用它们配置
Jackson以处理不同方面。这些特性在Jackson中是使用6个枚举进行描述的,并被
映射到environment的属性上:
Jackson枚举 Environment属性
com.fasterxml.jackson.databind.DeserializationFeature `spring.jackson.deserialization.
com.fasterxml.jackson.core.JsonGenerator.Feature `spring.jackson.generator.
com.fasterxml.jackson.databind.MapperFeature `spring.jackson.mapper.
com.fasterxml.jackson.core.JsonParser.Feature `spring.jackson.parser.
com.fasterxml.jackson.databind.SerializationFeature `spring.jackson.serialization.
com.fasterxml.jackson.annotation.JsonInclude.Include `spring.jackson.serialization-
inclusion=always
例如,设置 spring.jackson.serialization.indent_output=true可以美化打
印输出(prettyprint)。注意,由于松散绑定的使用, indent_output不必匹配
对应的枚举常量 INDENT_OUTPUT。
基于environment的配置会应用到自动配置的 Jackson2ObjectMapperBuilder
bean,然后应用到通过该builder创建的mappers,包括自动配置
的ObjectMapperbean。
71.3自定义JacksonObjectMapper
548

ApplicationContext中的 Jackson2ObjectMapperBuilder可以通
过Jackson2ObjectMapperBuilderCustomizerbean自定义。这些customizer
beans可以排序,SpringBoot自己的customizer序号为0,其他自定义可以应用到
SpringBoot自定义之前或之后。
所有类型为 com.fasterxml.jackson.databind.Module的beans都会自动注册
到自动配置的 Jackson2ObjectMapperBuilder,并应用到它创建的任
何ObjectMapper实例。这提供了一种全局机制,用于在为应用添加新特性时贡
献自定义模块。
如果想完全替换默认的 ObjectMapper,你既可以定义该类型的 @Bean并注
解@Primary,也可以定义 Jackson2ObjectMapperBuilder@Bean,通过
builder构建。注意不管哪种方式都会禁用所有的自动配置 ObjectMapper。
如果你提供 MappingJackson2HttpMessageConverter类型的 @Bean,它们将
替换MVC配置中的默认值。SpringBoot也提供了一
个HttpMessageConverters类型的便利bean(如果你使用MVC默认配置,那它
就总是可用的),它提供了一些有用的方法来获取默认和用户增强的消息转换器
(messageconverters)。具体详情可参考Section71.4,“Customizethe
@ResponseBodyrendering”及WebMvcAutoConfiguration源码。
71.3自定义JacksonObjectMapper
549

71.4自定义@ResponseBody渲染
Spring使用 HttpMessageConverters渲染 @ResponseBody(或来
自@RestController的响应),你可以通过在SpringBoot上下文中添加该类型的
beans来贡献其他的转换器。如果你添加的bean类型默认已经包含了(像用于
JSON转换的 MappingJackson2HttpMessageConverter),那它将替换默认的。
SpringBoot提供一个方便的 HttpMessageConverters类型的bean,它有一些有
用的方法可以访问默认的和用户增强的message转换器(比如你想要手动将它们注
入到一个自定义的 RestTemplate时就很有用)。
在通常的MVC用例中,任何你提供的 WebMvcConfigurerAdapterbeans通过覆
盖configureMessageConverters方法也能贡献转换器,但不同于通常的MVC,
你可以只提供你需要的转换器(因为SpringBoot使用相同的机制来贡献它默认的转
换器)。最终,如果你通过提供自己的 @EnableWebMvc注解覆盖SpringBoot默认
的MVC配置,那你就可以完全控制,并使用来
自WebMvcConfigurationSupport的getMessageConverters手动做任何事。
更多详情可参考WebMvcAutoConfiguration源码。
71.4自定义@ResponseBody渲染
550

71.5处理Multipart文件上传
SpringBoot采用Servlet3 javax.servlet.http.PartAPI来支持文件上传。默
认情况下,SpringBoot配置SpringMVC在单个请求中只处理每个文件最大1Mb,
最多10Mb的文件数据。你可以覆盖那些值,也可以设置临时文件存储的位置(比
如,存储到 /tmp文件夹下)及传递数据刷新到磁盘的阀值(通过使
用MultipartProperties类暴露的属性)。如果你需要设置文件不受限制,可以
设置 spring.http.multipart.max-file-size属性值为 -1。
当你想要接收multipart编码文件数据作为SpringMVC控制器(controller)处理方法
中被 @RequestParam注解的 MultipartFile类型的参数时,multipart支持就非
常有用了。
更多详情可参考MultipartAutoConfiguration源码。
71.5处理Multipart文件上传
551

71.6关闭SpringMVCDispatcherServlet
SpringBoot想要服务来自应用程序root /下的所有内容。如果你想将自己的
servlet映射到该目录下也是可以的,但当然你可能失去一些SpringBootMVC特
性。为了添加你自己的servlet,并将它映射到root资源,你只需声明一
个Servlet类型的 @Bean,并给它特定的bean名称 dispatcherServlet(如
果只想关闭但不替换它,你可以使用该名称创建不同类型的bean)。
71.6关闭SpringMVCDispatcherServlet
552

71.7关闭默认的MVC配置
完全控制MVC配置的最简单方式是提供你自己的被 @EnableWebMvc注解
的@Configuration,这样所有的MVC配置都逃不出你的掌心。
71.7关闭默认的MVC配置
553

71.8自定义ViewResolvers
ViewResolver是SpringMVC的核心组件,它负责转换 @Controller中的视图
名称到实际的 View实现。注意 ViewResolvers主要用在UI应用中,而不是
REST风格的服务( View不是用来渲染 @ResponseBody的)。Spring有很多你
可以选择的 ViewResolver实现,并且Spring自己对如何选择相应实现也没发表意
见。另一方面,SpringBoot会根据classpath上的依赖和应用上下文为你安装一或
两个 ViewResolver实现。 DispatcherServlet使用所有在应用上下文中找到
的解析器(resolvers),并依次尝试每一个直到它获取到结果,所以如果你正在添
加自己的解析器,那就要小心顺序和你的解析器添加的位置。
WebMvcAutoConfiguration将会为你的上下文添加以下 ViewResolvers:
beanid为defaultViewResolver的InternalResourceViewResolver,
它会定位可以使用 DefaultServlet渲染的物理资源(比如静态资源和JSP页
面)。它在视图名上应用了一个前缀和后缀(默认都为空,但你可以通
过spring.view.prefix和spring.view.suffix设置),然后查找在
servlet上下文中具有该路径的物理资源,可以通过提供相同类型的bean覆盖
它。
id为beanNameViewResolver的BeanNameViewResolver,它是视图解析器
链的一个非常有用的成员,可以在 View解析时收集任何具有相同名称的
beans,没必要覆盖或替换它。
id为viewResolver的ContentNegotiatingViewResolver,它只会在实
际View类型的beans出现时添加。这是一个'master'解析器,它的职责会代理
给其他解析器,它会尝试找到客户端发送的一个匹配'Accept'的HTTP头部。这
有一篇关于ContentNegotiatingViewResolver的博客,你也可以也查看下源
码。通过定义一个名叫'viewResolver'的bean,你可以关闭自动配置
的ContentNegotiatingViewResolver。
如果使用Thymeleaf,你将有一个id
为thymeleafViewResolver的ThymeleafViewResolver,它会通过加前
缀和后缀的视图名来查找资源(外部配置
为spring.thymeleaf.prefix和spring.thymeleaf.suffix,对应的默
认为'classpath:/templates/'和'.html')。你可以通过提供相同名称的bean来覆
盖它。
如果使用FreeMarker,你将有一个id
为freeMarkerViewResolver的FreeMarkerViewResolver,它会使用加
71.8自定义ViewResolvers
554

前缀和后缀(外部配置
为spring.freemarker.prefix和spring.freemarker.suffix,对应的
默认值为空和'.ftl')的视图名从加载路径(外部配置
为spring.freemarker.templateLoaderPath,默认
为'classpath:/templates/')下查找资源。你可以通过提供相同名称的bean来覆
盖它。
如果使用Groovy模板(实际上只要你把groovy-templates添加到classpath
下),你将有一个id为groovyTemplateViewResolver的Groovy
TemplateViewResolver,它会使用加前缀和后缀(外部属性
为spring.groovy.template.prefix和spring.groovy.template.suffix
,对应的默认值为'classpath:/templates/'和'.tpl')的视图名从加载路径下查找
资源。你可以通过提供相同名称的bean来覆盖它。
如果使用Velocity,你将有一个id
为velocityViewResolver的VelocityViewResolver,它会使用加前缀
和后缀(外部属性
为spring.velocity.prefix和spring.velocity.suffix,对应的默认
值为空和'.vm')的视图名从加载路径(外部属性
为spring.velocity.resourceLoaderPath,默认
为'classpath:/templates/')下查找资源。你可以通过提供相同名称的bean来覆
盖它。
更多详情可查看源码:
WebMvcAutoConfiguration,ThymeleafAutoConfiguration,FreeMarkerAutoConfi
guration,GroovyTemplateAutoConfiguration,VelocityAutoConfiguration。
71.8自定义ViewResolvers
555

71.9Velocity
默认情况下,SpringBoot会配置一个 VelocityViewResolver,如果需要的
是VelocityLayoutViewResolver,你可以自己创建一个名
为velocityViewResolver的bean。你也可以将 VelocityProperties实例注
入到自定义视图解析器以获取基本的默认设置。
以下示例使用 VelocityLayoutViewResolver替换自动配置的velocity视图解析
器,并自定义 layoutUrl及应用所有自动配置的属性:
@Bean(name="velocityViewResolver")
publicVelocityLayoutViewResolvervelocityViewResolver(VelocityP
ropertiesproperties){
VelocityLayoutViewResolverresolver=newVelocityLayoutView
Resolver();
properties.applyToViewResolver(resolver);
resolver.setLayoutUrl("layout/default.vm");
returnresolver;
}
71.9Velocity
556

71.10使用Thymeleaf3
默认情况下, spring-boot-starter-thymeleaf使用的是Thymeleaf2.1,你可
以通过覆盖 thymeleaf.version和thymeleaf-layout-dialect.version属性
使用Thymeleaf3,例如:
<properties>
<thymeleaf.version>3.0.0.RELEASE</thymeleaf.version>
<thymeleaf-layout-dialect.version>2.0.0</thymeleaf-layout-di
alect.version>
</dependency>
为了避免关于HTML5模板模式过期,将使用HTML模板模式的警告提醒,你需要显
式配置 spring.thymeleaf.mode为HTML,例如:
spring.thymeleaf.mode:HTML
具体操作可查看Thymeleaf3示例。
如果正在使用其他自动配置的Thymeleaf附加组件(SpringSecurity,Data
Attribute或Java8Time),你需要使用兼容Thymeleaf3.0的版本覆盖它们现在的
版本。
71.10使用Thymeleaf3
557

73.日志
SpringBoot除了 commons-loggingAPI外没有其他强制性的日志依赖,你有很多
可选的日志实现。想要使用Logback,你需要包含它及 jcl-over-slf4j(它实现
了CommonsLoggingAPI)。最简单的方式是通过依赖 spring-boot-starter-
logging的starters。对于一个web应用程序,你只需添加 spring-boot-
starter-web依赖,因为它依赖于loggingstarter。例如,使用Maven:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
SpringBoot有一个 LoggingSystem抽象,用于尝试通过classpath上下文配置日
志系统。如果Logback可用,则首选它。如果你唯一需要做的就是设置不同日志级
别,那可以通过在 application.properties中使用 logging.level前缀实
现,比如:
logging.level.org.springframework.web=DEBUG
logging.level.org.hibernate=ERROR
你也可以使用 logging.file设置日志文件的位置(除控制台之外,默认会输出
到控制台)。
想要对日志系统进行更细粒度的配置,你需要使用 LoggingSystem支持的原生配
置格式。默认情况下,SpringBoot从系统的默认位置加载原生配置(比如对于
Logback为classpath:logback.xml),但你可以使用 logging.config属性
设置配置文件的位置。
73.日志
558

73.1配置Logback
如果你将 logback.xml放到classpath根目录下,那它将会被从这加载
(或 logback-spring.xml充分利用Boot提供的模板特性)。SpringBoot提供一
个默认的基本配置,如果你只是设置日志级别,那你可以包含它,比如:
<?xmlversion="1.0"encoding="UTF-8"?>
<configuration>
<includeresource="org/springframework/boot/logging/logback/
base.xml"/>
<loggername="org.springframework.web"level="DEBUG"/>
</configuration>
如果查看spring-bootjar中的 base.xml,你将会看到 LoggingSystem为你创建
的很多有用的系统属性,比如:
${PID},当前进程id。
${LOG_FILE},如果在Boot外部配置中设置了 logging.file。
${LOG_PATH},如果设置了 logging.path(表示日志文件产生的目录)。
${LOG_EXCEPTION_CONVERSION_WORD},如果在Boot外部配置中设置
了logging.exception-conversion-word。
SpringBoot也提供使用自定义的Logback转换器在控制台上输出一些漂亮的彩色
ANSI日志信息(不是日志文件),具体参考默认的 base.xml配置。
如果Groovy在classpath下,你也可以使用 logback.groovy配置Logback。
73.1配置Logback
559

73.1.1配置logback只输出到文件
如果想禁用控制台日志记录,只将输出写入文件中,你需要一个只导入 file-
appender.xml而不是 console-appender.xml的自定义 logback-
spring.xml:
<?xmlversion="1.0"encoding="UTF-8"?>
<configuration>
<includeresource="org/springframework/boot/logging/logback/
defaults.xml"/>
<propertyname="LOG_FILE"value="${LOG_FILE:-${LOG_PATH:-${L
OG_TEMP:-${java.io.tmpdir:-/tmp}}/}spring.log}"/>
<includeresource="org/springframework/boot/logging/logback/
file-appender.xml"/>
<rootlevel="INFO">
<appender-refref="FILE"/>
</root>
</configuration>
你还需要将 logging.file添加到 application.properties:
logging.file=myapplication.log
73.1配置Logback
560

73.2配置Log4j
如果Log4j2出现在classpath下,SpringBoot会将其作为日志配置。如果你正在使
用starters进行依赖装配,这意味着你需要排除Logback,然后包含log4j2。如果不
使用starters,除了添加Log4j2,你还需要提供 jcl-over-slf4j依赖(至少)。
最简单的方式可能就是通过starters,尽管它需要排除一些依赖,比如,在Maven
中:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>
注Log4jstarters会收集好依赖以满足普通日志记录的需求(比如,Tomcat中使
用java.util.logging,但使用Log4j2作为输出),具体查看ActuatorLog4j2
的示例,了解如何将它用于实战。
73.2配置Log4j
561

73.2.1使用YAML或JSON配置Log4j2
除了它的默认XML配置格式,Log4j2也支持YAML和JSON配置文件。想使用其他
配置文件格式配置Log4j2,你需要添加合适的依赖到classpath,并以匹配所选格
式的方式命名配置文件:
格式 依赖 文件名
YAML
com.fasterxml.jackson.core:jackson-
databind
com.fasterxml.jackson.dataformat:jackson-
dataformat-yaml
log4j2.yaml
log4j2.yml
JSON com.fasterxml.jackson.core:jackson-
databind
log4j2.json
log4j2.jsn
73.2配置Log4j
562

74.数据访问
74.数据访问
563

74.1配置数据源
自定义 DataSource类型的 @Bean可以覆盖默认设置,正如Section24.7.1,
“Third-partyconfiguration”解释的那样,你可以很轻松的将它跟一系
列Environment属性绑定:
@Bean
@ConfigurationProperties(prefix="datasource.fancy")
publicDataSourcedataSource(){
returnnewFancyDataSource();
}
datasource.fancy.jdbcUrl=jdbc:h2:mem:mydb
datasource.fancy.username=sa
datasource.fancy.poolSize=30
SpringBoot也提供了一个工具类 DataSourceBuilder用来创建标准的数据源。如
果需要重用 DataSourceProperties的配置,你可以从它初始化一
个DataSourceBuilder:
@Bean
@ConfigurationProperties(prefix="datasource.mine")
publicDataSourcedataSource(DataSourcePropertiesproperties){
returnproperties.initializeDataSourceBuilder()
//additionalcustomizations
.build();
}
在此场景中,你保留了通过SpringBoot暴露的标准属性,通过添
加@ConfigurationProperties,你可以暴露在相应的命命名空间暴露其他特定
实现的配置,具体详情可参考'SpringBoot特性'章节中的Section29.1,“Configure
aDataSource”和DataSourceAutoConfiguration类源码。
74.1配置数据源
564

74.1配置数据源
565

74.2配置两个数据源
创建多个数据源和创建一个工作都是一样的,如果使用JDBC或JPA的默认自动配
置,你需要将其中一个设置为 @Primary(然后它就能被任何 @Autowired注入
获取)。
@Bean
@Primary
@ConfigurationProperties(prefix="datasource.primary")
publicDataSourceprimaryDataSource(){
returnDataSourceBuilder.create().build();
}
@Bean
@ConfigurationProperties(prefix="datasource.secondary")
publicDataSourcesecondaryDataSource(){
returnDataSourceBuilder.create().build();
}
74.2配置两个数据源
566

74.3使用SpringData仓库
SpringData可以为你的 @Repository接口创建各种风格的实现。SpringBoot会
为你处理所有事情,只要那些 @Repositories接口跟你
的@EnableAutoConfiguration类处于相同的包(或子包)。
对于很多应用来说,你需要做的就是将正确的SpringData依赖添加到classpath下
(JPA对应 spring-boot-starter-data-jpa,Mongodb对应 spring-boot-
starter-data-mongodb),创建一些repository接口来处理 @Entity对象,相应
示例可参考JPAsample或Mongodbsample。
SpringBoot会基于它找到的 @EnableAutoConfiguration来尝试猜测你
的@Repository定义的位置。想要获取更多控制,可以使
用@EnableJpaRepositories注解(来自SpringDataJPA)。
74.3使用SpringData仓库
567

74.4从Spring配置分离 @Entity定义
SpringBoot会基于它找到的 @EnableAutoConfiguration来尝试猜
测@Entity定义的位置,想要获取更多控制可以使用 @EntityScan注解,比
如:
@Configuration
@EnableAutoConfiguration
@EntityScan(basePackageClasses=City.class)
publicclassApplication{
//...
}
74.4从Spring配置分离@Entity定义
568

74.5配置JPA属性
SpringDataJPA已经提供了一些独立的配置选项(比如,针对SQL日志),并且
SpringBoot会暴露它们,针对hibernate的外部配置属性也更多些,最常见的选项如
下:
spring.jpa.hibernate.ddl-auto=create-drop
spring.jpa.hibernate.naming.physical-strategy=com.example.MyPhys
icalNamingStrategy
spring.jpa.database=H2
spring.jpa.show-sql=true
ddl-auto配置是个特殊情况,它的默认设置取决于是否使用内嵌数据库(是则默
认值为 create-drop,否则为 none)。当本地 EntityManagerFactory被创
建时,所有 spring.jpa.properties.*属性都被作为正常的JPA属性(去掉前
缀)传递进去了。
SpringBoot提供一致的命名策略,不管你使用什么Hibernate版本。如果使用
Hibernate4,你可以使用 spring.jpa.hibernate.naming.strategy进行自定
义;Hibernate5定义一个 Physical和Implicit命名策略:SpringBoot默认配
置SpringPhysicalNamingStrategy,该实现提供跟Hibernate4相同的表结构。
如果你情愿使用Hibernate5默认的,可以设置以下属性:
spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot
.model.naming.PhysicalNamingStrategyStandardImpl
具体详情可参考HibernateJpaAutoConfiguration和JpaBaseConfiguration。
74.5配置JPA属性
569

74.6使用自定义EntityManagerFactory
为了完全控制 EntityManagerFactory的配置,你需要添加一个名
为entityManagerFactory的@Bean,SpringBoot自动配置会根据是否存在该
类型的bean来关闭它的实体管理器(entitymanager)。
74.6使用自定义EntityManagerFactory
570

74.7使用两个EntityManagers
即使默认的 EntityManagerFactory工作的很好,你也需要定义一个新
的EntityManagerFactory,因为一旦出现第二个该类型的bean,默认的将会被
关闭。为了轻松的实现该操作,你可以使用SpringBoot提供
的EntityManagerBuilder,或者如果你喜欢的话可以直接使用来自SpringORM
的LocalContainerEntityManagerFactoryBean。
示例:
//addtwodatasourcesconfiguredasabove
@Bean
publicLocalContainerEntityManagerFactoryBeancustomerEntityMana
gerFactory(
EntityManagerFactoryBuilderbuilder){
returnbuilder
.dataSource(customerDataSource())
.packages(Customer.class)
.persistenceUnit("customers")
.build();
}
@Bean
publicLocalContainerEntityManagerFactoryBeanorderEntityManager
Factory(
EntityManagerFactoryBuilderbuilder){
returnbuilder
.dataSource(orderDataSource())
.packages(Order.class)
.persistenceUnit("orders")
.build();
}
上面的配置靠自己基本可以运行,想要完成作品你还需要为两
个EntityManagers配置 TransactionManagers。其中的一个会被SpringBoot
默认的 JpaTransactionManager获取,如果你将它标记为 @Primary。另一个
74.7使用两个EntityManagers
571

需要显式注入到一个新实例。或你可以使用一个JTA事物管理器生成它两个。
如果使用SpringData,你需要相应地需要配置 @EnableJpaRepositories:
@Configuration
@EnableJpaRepositories(basePackageClasses=Customer.class,
entityManagerFactoryRef="customerEntityManagerFactory"
)
publicclassCustomerConfiguration{
...
}
@Configuration
@EnableJpaRepositories(basePackageClasses=Order.class,
entityManagerFactoryRef="orderEntityManagerFactory")
publicclassOrderConfiguration{
...
}
74.7使用两个EntityManagers
572

74.9使用SpringDataJPA和Mongo仓库
SpringDataJPA和SpringDataMongo都能自动为你创建 Repository实现。如果
它们同时出现在classpath下,你可能需要添加额外的配置来告诉SpringBoot你想
要哪个(或两个)为你创建仓库。最明确地方式是使用标准的SpringData
@Enable*Repositories,然后告诉它你的 Repository接口的位置(此
处*即可以是Jpa,也可以是Mongo,或者两者都是)。
这里也有 spring.data.*.repositories.enabled标志,可用来在外部配置中开
启或关闭仓库的自动配置,这在你想关闭Mongo仓库但仍使用自动配置
的MongoTemplate时非常有用。
相同的障碍和特性也存在于其他自动配置的SpringData仓库类型(Elasticsearch,
Solr),只需要改变对应注解的名称和标志。
74.9使用SpringDataJPA和Mongo仓库
574

74.11配置JPA使用的组件
如果想配置一个JPA使用的组件,你需要确保该组件在JPA之前初始化。组件如果
是SpringBoot自动配置的,SpringBoot会为你处理。例如,Flyway是自动配置
的,Hibernate依赖于Flyway,这样Hibernate有机会在使用数据库前对其进行初始
化。
如果自己配置组件,你可以使
用EntityManagerFactoryDependsOnPostProcessor子类设置必要的依赖,例
如,如果你正使用Hibernate搜索,并将Elasticsearch作为它的索引管理器,这样任
何EntityManagerFactorybeans必须设置为依赖 elasticsearchClient
bean:
/**
*{@linkEntityManagerFactoryDependsOnPostProcessor}thatensur
esthat
*{@linkEntityManagerFactory}beansdependonthe{@codeelast
icsearchClient}bean.
*/
@Configuration
staticclassElasticsearchJpaDependencyConfiguration
extendsEntityManagerFactoryDependsOnPostProcessor{
ElasticsearchJpaDependencyConfiguration(){
super("elasticsearchClient");
}
}
74.11配置JPA使用的组件
576

75.数据库初始化
一个数据库可以使用不同的方式进行初始化,这取决于你的技术栈。或者你可以手
动完成该任务,只要数据库是单独的过程。
75.数据库初始化
577

75.1使用JPA初始化数据库
JPA有个生成DDL的特性,并且可以设置为在数据库启动时运行,这可以通过两个
外部属性进行控制:
spring.jpa.generate-ddl(boolean)控制该特性的关闭和开启,跟实
现者没关系。
spring.jpa.hibernate.ddl-auto(enum)是一个Hibernate特性,用于
更细力度的控制该行为,更多详情参考以下内容。
75.1使用JPA初始化数据库
578

75.2使用Hibernate初始化数据库
你可以显式设置 spring.jpa.hibernate.ddl-auto,标准的Hibernate属性值
有none,validate,update,create,create-drop。SpringBoot根
据你的数据库是否为内嵌数据库来选择相应的默认值,如果是内嵌型的则默认值
为create-drop,否则为 none。通过查看 Connection类型可以检查是否为
内嵌型数据库,hsqldb,h2和derby是内嵌的,其他都不是。当从内存数据库迁移
到一个真正的数据库时,你需要当心,在新的平台中不能对数据库表和数据是否存
在进行臆断,你也需要显式设置 ddl-auto,或使用其他机制初始化数据库。
此外,启动时处于classpath根目录下的 import.sql文件会被执行。这在demos
或测试时很有用,但在生产环境中你可能不期望这样。这是Hibernate的特性,和
Spring没有一点关系。
75.2使用Hibernate初始化数据库
579

75.3使用SpringJDBC初始化数据库
SpringJDBC有一个初始化 DataSource特性,SpringBoot默认启用该特性,并
从标准的位置 schema.sql和data.sql(位于classpath根目录)加载SQL。此
外,SpringBoot将加载 schema-${platform}.sql和data-
${platform}.sql文件(如果存在),在这
里platform是spring.datasource.platform的值,比如,你可以将它设置为
数据库的供应商名称( hsqldb, h2, oracle, mysql, postgresql等)。
SpringBoot默认启用SpringJDBC初始化快速失败特性,所以如果脚本导致异常产
生,那应用程序将启动失败。脚本的位置可以通过设
置spring.datasource.schema和spring.datasource.data来改变,如果设
置spring.datasource.initialize=false则哪个位置都不会被处理。
你可以设置 spring.datasource.continue-on-error=true禁用快速失败特性。
一旦应用程序成熟并被部署了很多次,那该设置就很有用,因为脚本可以充当"可怜
人的迁移"-例如,插入失败时意味着数据已经存在,也就没必要阻止应用继续运
行。
如果你想要在一个JPA应用中使用 schema.sql,那如果Hibernate试图创建相同
的表, ddl-auto=create-drop将导致错误产生。为了避免那些错误,可以
将ddl-auto设置为“”(推荐)或 none。不管是否使用 ddl-auto=create-
drop,你总可以使用 data.sql初始化新数据。
75.3使用SpringJDBC初始化数据库
580

75.4初始化SpringBatch数据库
如果你正在使用SpringBatch,那么它会为大多数的流行数据库平台预装SQL初始
化脚本。SpringBoot会检测你的数据库类型,并默认执行那些脚本,在这种情况下
将关闭快速失败特性(错误被记录但不会阻止应用启动)。这是因为那些脚本是可
信任的,通常不会包含bugs,所以错误会被忽略掉,并且对错误的忽略可以让脚本
具有幂等性。你可以使用 spring.batch.initializer.enabled=false显式关闭
初始化功能。
75.4初始化SpringBatch数据库
581

75.5.1启动时执行Flyway数据库迁移
想要在启动时自动运行Flyway数据库迁移,需要将 org.flywaydb:flyway-
core添加到你的classpath下。
迁移是一些 V<VERSION>__<NAME>.sql格式的脚本( <VERSION>是一个下划线
分割的版本号,比如'1'或'2_1')。默认情况下,它们存放
在classpath:db/migration文件夹中,但你可以使用 flyway.locations(一
个列表)改变它。详情可参考flyway-core中的 Flyway类,查看一些可用的配置,
比如schemas。SpringBoot在FlywayProperties中提供了一个小的属性集,可用于
禁止迁移,或关闭位置检测。SpringBoot将调用 Flyway.migrate()执行数据库
迁移,如果想要更多控制可提供一个实现FlywayMigrationStrategy的@Bean。
默认情况下,Flyway将自动注入( @Primary)DataSource到你的上下文,并
用它进行数据迁移。如果想使用不同的 DataSource,你可以创建一个,并将它
标记为 @FlywayDataSource的@Bean-如果你这样做了,且想要两个数据源,记
得创建另一个并将它标记为 @Primary,或者你可以通过在外部配置文件中设
置flyway.[url,user,password]来使用Flyway的原生 DataSource。
这是一个Flyway示例,你可以作为参考。
75.5使用高级数据迁移工具
583

75.5.2启动时执行Liquibase数据库迁移
想要在启动时自动运行Liquibase数据库迁移,你需要
将org.liquibase:liquibase-core添加到classpath下。
你可以使用 liquibase.change-log设置master变化日志位置,默认
从db/changelog/db.changelog-master.yaml读取。除了YAML,Liquibase还
支持JSON,XML和SQL改变日志格式。查看LiquibaseProperties获取可用配置,比
如上下文,默认schema等。
这里有个Liquibase示例可作为参考。
75.5使用高级数据迁移工具
584

76.批处理应用
76.批处理应用
585

76.1在启动时执行SpringBatch作业
你可以在上下文的某个地方添加 @EnableBatchProcessing来启用SpringBatch
的自动配置功能。
默认情况下,在启动时它会执行应用的所有作业(Jobs),具体查
看JobLauncherCommandLineRunner。你可以通过指
定spring.batch.job.names(多个作业名以逗号分割)来缩小到一个特定的作
业或多个作业。
如果应用上下文包含一个 JobRegistry,那么处
于spring.batch.job.names中的作业将会从registry中查找,而不是从上下文中
自动装配。这是复杂系统中常见的一个模式,在这些系统中多个作业被定义在子上
下文和注册中心。
详情可参考BatchAutoConfiguration和@EnableBatchProcessing。
76.1在启动时执行SpringBatch作业
586

77.执行器(Actuator)
77.执行器
587

77.1改变HTTP端口或执行器端点的地址
在一个单独的应用中,执行器的HTTP端口默认和主HTTP端口相同。想要让应用监
听不同的端口,你可以设置外部属性 management.port。为了监听一个完全不同
的网络地址(比如,你有一个用于管理的内部网络和一个用于用户应用程序的外部
网络),你可以将 management.address设置为一个可用的IP地址,然后将服务
器绑定到该地址。
更多详情可查看ManagementServerProperties源码和'Production-ready特性'章节中
的Section47.3,“Customizingthemanagementserverport”。
77.1改变HTTP端口或执行器端点的地址
588

77.2自定义WhiteLabel错误页面
SpringBoot安装了一个'whitelabel'错误页面,如果你遇到一个服务器错误(机器客
户端消费的是JSON,其他媒体类型则会看到一个具有正确错误码的合乎情理的响
应),那就能在客户端浏览器中看到该页面。你可以设
置error.whitelabel.enabled=false来关闭该功能,但通常你想要添加自己的
错误页面来取代whitelabel。确切地说,如何实现取决于你使用的模板技术。例
如,你正在使用Thymeleaf,你将添加一个 error.html模板。如果你正在使用
FreeMarker,那你将添加一个 error.ftl模板。通常,你需要的只是一个名称
为error的View,或一个处理 /error路径的 @Controller。除非你替换了
一些默认配置,否则你将在你的 ApplicationContext中找到一
个BeanNameViewResolver,所以一个id为error的@Bean可能是完成该操作
的一个简单方式,详情可参考ErrorMvcAutoConfiguration。
查看ErrorHandling章节,了解如何将处理器(handlers)注册到servlet容器中。
77.2自定义WhiteLabel错误页面
589

77.3Actuator和Jersey
执行器HTTP端点只有在基于SpringMVC的应用才可用,如果想使用Jersey和执行
器,你需要启用SpringMVC(添加 spring-boot-starter-web依赖)。默认情
况下,Jersey和SpringMVC分发器servlet被映射到相同路径( /)。你需要改变
它们中的某个路径(SpringMVC可以配置 server.servlet-path,Jersey可以
配置 spring.jersey.application-path)。例如,如果你
在application.properties中添加 server.servlet-path=/system,你将
在/system访问执行器HTTP端点。
77.3Actuator和Jersey
590

78.安全
78.安全
591

78.2改变AuthenticationManager并添加用户账号
如果你提供了一个 AuthenticationManager类型的 @Bean,那么默认的就不会
被创建了,所以你可以获得SpringSecurity可用的全部特性(比如,不同的认证选
项)。
SpringSecurity也提供了一个方便的 AuthenticationManagerBuilder,用于构
建具有常见选项的 AuthenticationManager。在一个webapp中,推荐将它注入
到WebSecurityConfigurerAdapter的一个void方法中,比如:
@Configuration
publicclassSecurityConfigurationextendsWebSecurityConfigurer
Adapter{
@Autowired
publicvoidconfigureGlobal(AuthenticationManagerBuilderaut
h)throwsException{
auth.inMemoryAuthentication()
.withUser("barry").password("password").roles("U
SER");//...etc.
}
//...otherstuffforapplicationsecurity
}
如果把它放到一个内部类或一个单独的类中,你将得到最好的结果(也就是不跟很
多其他 @Beans混合在一起将允许你改变实例化的顺序)。securewebsample是
一个有用的参考模板。
如果你遇到了实例化问题(比如,使用JDBC或JPA进行用户详细信息的存储),那
将AuthenticationManagerBuilder回调提取到一
个GlobalAuthenticationConfigurerAdapter(放到 init()方法内以防其他
地方也需要authenticationmanager)可能是个不错的选择,比如:
78.2改变AuthenticationManager并添加用户账号
593

@Configuration
publicclassAuthenticationManagerConfigurationextends
GlobalAuthenticationConfigurerAdapter{
@Override
publicvoidinit(AuthenticationManagerBuilderauth){
auth.inMemoryAuthentication()//...etc.
}
}
78.2改变AuthenticationManager并添加用户账号
594

78.3当前端使用代理服务器时启用HTTPS
对于任何应用来说,确保所有的主端点(URL)都只在HTTPS下可用是个重要的苦
差事。如果你使用Tomcat作为servlet容器,那SpringBoot如果发现一些环境设置的
话,它将自动添加Tomcat自己的 RemoteIpValve,你也可以依赖
于HttpServletRequest来报告是否请求是安全的(即使代理服务器的
downstream处理真实的SSL终端)。这个标准行为取决于某些请求头是否出现
(x-forwarded-for和x-forwarded-proto),这些请求头的名称都是约定好
的,所以对于大多数前端和代理都是有效的。
你可以向 application.properties添加以下设置开启该功能,比如:
server.tomcat.remote_ip_header=x-forwarded-for
server.tomcat.protocol_header=x-forwarded-proto
(这些属性出现一个就会开启该功能,或者你可以通过添加一
个TomcatEmbeddedServletContainerFactorybean自己添
加RemoteIpValve)。
SpringSecurity也可以配置成针对所有或某些请求需要一个安全渠道(channel)。
想要在一个SpringBoot应用中开启它,你只需将 application.properties中
的security.require_ssl设置为 true即可。
78.3当前端使用代理服务器时启用HTTPS
595

79.热交换
79.热交换
596

79.1重新加载静态内容
SpringBoot有很多用于热加载的选项,不过推荐使用spring-boot-devtools,因为它
提供了其他开发时特性,比如快速应用重启和LiveReload,还有开发时敏感的配置
加载(比如,模板缓存)。
此外,使用IDE开发也是一个不错的方式,特别是需要调试的时候(所有的现代
IDEs都允许重新加载静态资源,通常也支持对变更的Java类进行热交换)。
最后,Maven和Gradle插件也支持命令行下的静态文件热加载。如果你使用其他高
级工具编写css/js,并使用外部的css/js编译器,那你就可以充分利用该功能。
79.1重新加载静态内容
597

79.2.在不重启容器的情况下重新加载模板
SpringBoot支持的大多数模板技术包含一个禁用缓存的配置选项,如果你正在使
用spring-boot-devtools模块,SpringBoot在开发期间会自动为你配置那些属
性。
79.2.在不重启容器的情况下重新加载模板
598

79.4.1使用Maven配置SpringLoaded
为了在Maven命令行下使用SpringLoaded,你只需将它作为依赖添加到Spring
Boot插件声明中即可,比如:
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>springloaded</artifactId>
<version>1.2.0.RELEASE</version>
</dependency>
</dependencies>
</plugin>
正常情况下,这在Eclipse和IntelliJIDEA中工作的相当漂亮,只要它们有相应的,
和Maven默认一致的构建配置(Eclipsem2e对此支持的更好,开箱即用)。
79.4在不重启容器的情况下重新加载Java类
605

79.4.2使用Gradle和IntelliJIDEA配置SpringLoaded
如果想将SpringLoaded和Gradle,IntelliJIDEA结合起来,那你需要付出代价。默
认情况下,IntelliJIDEA将类编译到一个跟Gradle不同的位置,这会导致Spring
Loaded监控失败。
为了正确配置IntelliJIDEA,你可以使用 ideaGradle插件:
buildscript{
repositories{jcenter()}
dependencies{
classpath"org.springframework.boot:spring-boot-gradle-p
lugin:1.4.1.RELEASE"
classpath'org.springframework:springloaded:1.2.0.RELEAS
E'
}
}
applyplugin:'idea'
idea{
module{
inheritOutputDirs=false
outputDir=file("$buildDir/classes/main/")
}
}
//...
注IntelliJIDEA必须配置跟命令行Gradle任务相同的Java版本,并
且springloaded必须作为一个 buildscript依赖被包含进去。
此外,你也可以启用IntellijIDEA内部的 MakeProjectAutomatically,这样不
管什么时候只要文件被保存都会自动编译。
79.4在不重启容器的情况下重新加载Java类
606

80.构建
80.构建
607

80.1生成构建信息
Maven和Gradle都支持产生包含项目版本,坐标,名称的构建信息,该插件可以通
过配置添加其他属性。当这些文件出现时,SpringBoot自动配置一
个BuildPropertiesbean。
为了让Maven生成构建信息,你需要为 build-infogoal添加一个execution:
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>1.4.1.RELEASE</version>
<executions>
<execution>
<goals>
<goal>build-info</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
注更多详情查看SpringBootMaven插件文档。
使用Gradle实现同样效果:
springBoot{
buildInfo()
}
可以使用DSL添加其他属性:
80.1生成构建信息
608

springBoot{
buildInfo{
additionalProperties=[
'foo':'bar'
]
}
}
80.1生成构建信息
609

80.2生成Git信息
Maven和Gradle都支持生成一个 git.properties文件,该文件包含项目构建
时git源码的仓库状态。对于Maven用户来说, spring-boot-starter-
parentPOM包含一个预配置的插件去产生一个 git.properties文件,只需简
单的将以下声明添加到POM中:
<build>
<plugins>
<plugin>
<groupId>pl.project13.maven</groupId>
<artifactId>git-commit-id-plugin</artifactId>
</plugin>
</plugins>
</build>
Gradle用户可以使用gradle-git-properties插件实现相同效果:
plugins{
id"com.gorylenko.gradle-git-properties"version"1.4.6"
}
80.2生成Git信息
610

80.3自定义依赖版本
如果你使用Maven进行一个直接或间接继承 spring-boot-dependencies(比
如spring-boot-starter-parent)的构建,并想覆盖一个特定的第三方依赖,
那你可以添加合适的 <properties>元素。浏览spring-boot-dependenciesPOM
可以获取一个全面的属性列表。例如,想要选择一个不同的 slf4j版本,你可以
添加以下内容:
<properties>
<slf4j.version>1.7.5<slf4j.version>
</properties>
注这只在你的Maven项目继承(直接或间接)自 spring-boot-dependencies才
有用。如果你使用 <scope>import</scope>,将 spring-boot-
dependencies添加到自己的 dependencyManagement片段,那你必须自己重新
定义artifact而不是覆盖属性。
注每个SpringBoot发布都是基于一些特定的第三方依赖集进行设计和测试的,覆
盖版本可能导致兼容性问题。
Gradle中为了覆盖依赖版本,你需要指定如下所示的version:
ext['slf4j.version']='1.7.5'
更多详情查看GradleDependencyManagement插件文档。
80.3自定义依赖版本
611

80.4使用Maven创建可执行JAR
spring-boot-maven-plugin能够用来创建可执行的'胖'JAR。如果正在使
用spring-boot-starter-parentPOM,你可以简单地声明该插件,然后你的
jar将被重新打包:
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
如果没有使用parentPOM,你仍旧可以使用该插件。不过,你需要另外添加一
个<executions>片段:
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>1.4.1.RELEASE</version>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
查看插件文档获取详细的用例。
80.4使用Maven创建可执行JAR
612

80.4使用Maven创建可执行JAR
613

80.5将SpringBoot应用作为依赖
跟war包一样,SpringBoot应用不是用来作为依赖的。如果你的应用包含需要跟其
他项目共享的类,最好的方式是将代码放到单独的模块,然后其他项目及你的应用
都可以依赖该模块。
如果不能按照上述推荐的方式重新组织代码,你需要配置SpringBoot的Maven和
Gradle插件去产生一个单独的artifact,以适合于作为依赖。可执行存档不能用于依
赖,因为可执行jar格式将应用class打包到 BOOT-INF/classes,也就意味着可执
行jar用于依赖时会找不到。
为了产生两个artifacts(一个用于依赖,一个用于可执行jar),你需要指定
classifier。classifier用于可执行存档的name,默认存档用于依赖。
可以使用以下配置Maven中classifier的exec:
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<classifier>exec</classifier>
</configuration>
</plugin>
</plugins>
</build>
使用Gradle可以添加以下配置:
bootRepackage{
classifier='exec'
}
80.5将SpringBoot应用作为依赖
614

80.6在可执行jar运行时提取特定的版本
在一个可执行jar中,为了运行,多数内嵌的库不需要拆包(unpacked),然而有
一些库可能会遇到问题。例如,JRuby包含它自己的内嵌jar,它假定 jruby-
complete.jar本身总是能够直接作为文件访问的。
为了处理任何有问题的库,你可以标记那些特定的内嵌jars,让它们在可执行jar第
一次运行时自动解压到一个临时文件夹中。例如,为了将JRuby标记为使用Maven
插件拆包,你需要添加如下的配置:
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<requiresUnpack>
<dependency>
<groupId>org.jruby</groupId>
<artifactId>jruby-complete</artifactId>
</dependency>
</requiresUnpack>
</configuration>
</plugin>
</plugins>
</build>
使用Gradle完全上述操作:
springBoot{
requiresUnpack=['org.jruby:jruby-complete']
}
80.6在可执行jar运行时提取特定的版本
615

80.7使用排除创建不可执行的JAR
如果你构建的产物既有可执行的jar和非可执行的jar,那你常常需要为可执行的版本
添加额外的配置文件,而这些文件在一个libraryjar中是不需要的。比
如, application.yml配置文件可能需要从非可执行的JAR中排除。
下面是如何在Maven中实现:
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<classifier>exec</classifier>
</configuration>
</plugin>
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<executions>
<execution>
<id>exec</id>
<phase>package</phase>
<goals>
<goal>jar</goal>
</goals>
<configuration>
<classifier>exec</classifier>
</configuration>
</execution>
<execution>
<phase>package</phase>
<goals>
<goal>jar</goal>
</goals>
<configuration>
<!--Needthistoensureapplication.yml
isexcluded-->
80.7使用排除创建不可执行的JAR
616

<forceCreation>true</forceCreation>
<excludes>
<exclude>application.yml</exclude>
</excludes>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
在Gradle中,你可以使用标准任务的DSL(领域特定语言)特性创建一个新的JAR
存档,然后在 bootRepackage任务中使用 withJarTask属性添加对它的依赖:
jar{
baseName='spring-boot-sample-profile'
version='0.0.0'
excludes=['**/application.yml']
}
task('execJar',type:Jar,dependsOn:'jar'){
baseName='spring-boot-sample-profile'
version='0.0.0'
classifier='exec'
fromsourceSets.main.output
}
bootRepackage{
withJarTask=tasks['execJar']
}
80.7使用排除创建不可执行的JAR
617

80.9远程调试使用Gradle启动的SpringBoot项目
想要为使用Gradle启动的SpringBoot应用添加一个远程调试器,你可以使
用build.gradle的applicationDefaultJvmArgs属性或 --debug-jvm命令
行选项。
build.gradle:
applicationDefaultJvmArgs=[
"-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,addre
ss=5005"
]
命令行:
$gradlerun--debug-jvm
详情查看Gradle应用插件。
80.9远程调试使用Gradle启动的SpringBoot项目
619

80.10使用Ant构建可执行存档(不使用spring-boot-
antlib)
想要使用Ant进行构建,你需要抓取依赖,编译,然后像通常那样创建一个jar或war
存档。为了让它可以执行,你可以使用 spring-boot-antlib,也可以使用以下
指令:
1. 如果构建jar,你需要将应用的类和资源打包进内嵌的 BOOT-INF/classes目
录。如果构建war,你需要将应用的类打包进内嵌的 WEB-INF/classes目
录。
2. 对于jar,添加运行时依赖到内嵌的 BOOT-INF/lib目录。对于war,则添加
到WEB-INF/lib目录。注意不能压缩存档中的实体。
3. 对于jar,添加 provided依赖到内嵌的 BOOT-INF/lib目录。对于war,则
添加到 WEB-INF/lib-provided目录。注意不能压缩存档中的实体。
4. 在存档的根目录添加 spring-boot-loader类(这样 Main-Class就可用
了)。
5. 使用恰当的启动器,比如对于jar使用 JarLauncher作为manifest的Main-
Class属性,指定manifest的其他属性,特别是 Start-Class。
示例:
80.10使用Ant构建可执行存档
620

<targetname="build"depends="compile">
<jardestfile="target/${ant.project.name}-${spring-boot.vers
ion}.jar"compress="false">
<mappedresources>
<filesetdir="target/classes"/>
<globmapperfrom="*"to="BOOT-INF/classes/*"/>
</mappedresources>
<mappedresources>
<filesetdir="src/main/resources"erroronmissingdir=
"false"/>
<globmapperfrom="*"to="BOOT-INF/classes/*"/>
</mappedresources>
<mappedresources>
<filesetdir="${lib.dir}/runtime"/>
<globmapperfrom="*"to="BOOT-INF/lib/*"/>
</mappedresources>
<zipfilesetsrc="${lib.dir}/loader/spring-boot-loader-ja
r-${spring-boot.version}.jar"/>
<manifest>
<attributename="Main-Class"value="org.springframew
ork.boot.loader.JarLauncher"/>
<attributename="Start-Class"value="${start-class}"
/>
</manifest>
</jar>
</target>
该Ant示例中有一个 build.xml文件及 manual任务,可以使用以下命令来运
行:
$ant-lib<foldercontainingivy-2.2.jar>cleanmanual
在上述操作之后,你可以使用以下命令运行该应用:
$java-jartarget/*.jar
80.10使用Ant构建可执行存档
621

80.10使用Ant构建可执行存档
622

80.11如何使用Java6
如果想在Java6环境中使用SpringBoot,你需要改变一些配置,具体的改变取决于
你应用的功能。
80.11如何使用Java6
623

80.11.1内嵌Servlet容器兼容性
如果你在使用Boot的内嵌Servlet容器,你需要使用一个兼容Java6的容器。Tomcat
7和Jetty8都是Java6兼容的。具体参考Section70.16使用Tomcat7.x或8.0和
Section70.18使用Jetty8。
80.11如何使用Java6
624

80.11.2Jackson
Jackson2.7及以后版本需要Java7,如果想要在Java6环境使用Jackson,你需要
降级使用Jackson2.6。
80.11如何使用Java6
625

80.11.3JTAAPI兼容性
虽然JavaTransactionAPI自身不要求Java7,但官方APIjar包含的已构建类需要
Java7。如果正在使用JTA,你需要使用能够在Java6环境工作的jar替换官方的JTA
1.2APIjar。想要实现这样的效果,你需要排除任
何javax.transaction:javax.transaction-api依赖,并使
用org.jboss.spec.javax.transaction:jboss-transaction-
api_1.2_spec:1.0.0.Final替换它。
80.11如何使用Java6
626

81.传统部署
81.传统部署
627

81.1创建可部署的war文件
产生一个可部署war包的第一步是提供一个 SpringBootServletInitializer子
类,并覆盖它的 configure方法,这充分利用了Spring框架对Servlet3.0的支
持,并允许你在应用通过servlet容器启动时配置它。通常,你只需把应用的主类改
为继承 SpringBootServletInitializer即可:
@SpringBootApplication
publicclassApplicationextendsSpringBootServletInitializer{
@Override
protectedSpringApplicationBuilderconfigure(SpringApplicati
onBuilderapplication){
returnapplication.sources(Application.class);
}
publicstaticvoidmain(String[]args)throwsException{
SpringApplication.run(Application.class,args);
}
}
下一步是更新你的构建配置,这样你的项目将产生一个war包而不是jar包。如果你
使用Maven,并使用 spring-boot-starter-parent(为了配置Maven的war插
件),所有你需要做的就是更改 pom.xml的打包方式为 war:
<packaging>war</packaging>
如果你使用Gradle,你需要修改 build.gradle来将war插件应用到项目上:
applyplugin:'war'
该过程最后的一步是确保内嵌的servlet容器不能干扰war包将部署的servlet容器。
为了达到这个目的,你需要将内嵌容器的依赖标记为 provided。
如果使用Maven:
81.1创建可部署的war文件
628

<dependencies>
<!--…-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>
<!--…-->
</dependencies>
如果使用Gradle:
dependencies{
//…
providedRuntime'org.springframework.boot:spring-boot-starte
r-tomcat'
//…
}
如果你使用SpringBoot构建工具,将内嵌容器依赖标记为 provided将产生一个
可执行war包,在 lib-provided目录有该war包的 provided依赖。这意味着,
除了部署到servlet容器,你还可以通过使用命令行 java-jar命令来运行应用。
注查看SpringBoot基于以上配置的一个Maven示例应用。
81.1创建可部署的war文件
629

81.2为老的servlet容器创建可部署的war文件
老的Servlet容器不支持在Servlet3.0中使用的 ServletContextInitializer启动
处理。你仍旧可以在这些容器使用Spring和SpringBoot,但你需要为应用添加一
个web.xml,并将它配置为通过一个 DispatcherServlet加载一
个ApplicationContext。
81.2为老的servlet容器创建可部署的war文件
630

81.3将现有的应用转换为SpringBoot
对于一个非web项目,转换为SpringBoot应用很容易(抛弃创
建ApplicationContext的代码,取而代之的是调
用SpringApplication或SpringApplicationBuilder)。SpringMVCweb
应用通常先创建一个可部署的war应用,然后将它迁移为一个可执行的war或jar,建
议阅读GettingStartedGuideonConvertingajartoawar.。
通过继承 SpringBootServletInitializer创建一个可执行war(比如,在一个
名为 Application的类中),然后添加SpringBoot
的@EnableAutoConfiguration注解,示例:
@Configuration
@EnableAutoConfiguration
@ComponentScan
publicclassApplicationextendsSpringBootServletInitializer{
@Override
protectedSpringApplicationBuilderconfigure(SpringApplicati
onBuilderapplication){
//Customizetheapplicationorcallapplication.sources
(...)toaddsources
//Sinceourexampleisitselfa@Configurationclasswe
actuallydon't
//needtooverridethismethod.
returnapplication;
}
}
记住不管你往 sources放什么东西,它仅是一个Spring
ApplicationContext,正常情况下,任何生效的在这里也会起作用。有一些
beans你可以先移除,然后让SpringBoot提供它的默认实现,不过有可能需要先完
成一些事情。
81.3将现有的应用转换为SpringBoot
631

静态资源可以移到classpath根目录下
的/public(或 /static,/resources,/META-INF/resources)。同样
的方式也适合于 messages.properties(SpringBoot在classpath根目录下自动
发现这些配置)。
美妙的(Vanillausageof)Spring DispatcherServlet和SpringSecurity不需要
改变。如果你的应用有其他特性,比如使用其他servlets或filters,那你可能需要添
加一些配置到你的 Application上下文中,按以下操作替换 web.xml的那些元
素:
在容器中安装一个 Servlet或ServletRegistrationBean类型
的@Bean,就好像 web.xml中的 <servlet/>和<servlet-
mapping/>。
同样的添加一个 Filter或FilterRegistrationBean类型的 @Bean(类
似于 <filter/>和<filter-mapping/>)。
在XML文件中的 ApplicationContext可以通过 @Import添加到你
的Application中。简单的情况下,大量使用注解配置可以在几行内定
义@Bean定义。
一旦war可以使用,我们就通过添加一个main方法到 Application来让它可以执
行,比如:
publicstaticvoidmain(String[]args){
SpringApplication.run(Application.class,args);
}
应用可以划分为多个类别:
没有web.xml的Servlet3.0+应用
有web.xml的应用
有上下文层次的应用
没有上下文层次的应用
所有这些都可以进行适当的转化,但每个可能需要稍微不同的技巧。
Servlet3.0+的应用转化的相当简单,如果它们已经使用SpringServlet3.0+初始化
器辅助类。通常所有来自一个存在的 WebApplicationInitializer的代码可以
移到一个 SpringBootServletInitializer中。如果一个存在的应用有多
个ApplicationContext(比如,如果它使
81.3将现有的应用转换为SpringBoot
632

81.4部署WAR到Weblogic
想要将SpringBoot应用部署到Weblogic,你需要确保你的servlet初始化器直接实
现WebApplicationInitializer(即使你继承的基类已经实现了它)。
一个传统的Weblogic初始化器可能如下所示:
importorg.springframework.boot.autoconfigure.SpringBootApplicat
ion;
importorg.springframework.boot.context.web.SpringBootServletIni
tializer;
importorg.springframework.web.WebApplicationInitializer;
@SpringBootApplication
publicclassMyApplicationextendsSpringBootServletInitializer
implementsWebApplicationInitializer{
}
如果使用logback,你需要告诉Weblogic你倾向使用的打包版本而不是服务器预装
的版本。你可以通过添加一个具有如下内容的 WEB-INF/weblogic.xml实现该操
作:
81.4部署WAR到Weblogic
634

<?xmlversion="1.0"encoding="UTF-8"?>
<wls:weblogic-web-app
xmlns:wls="http://xmlns.oracle.com/weblogic/weblogic-web-app"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/ejb-jar_3_0.xsd
http://xmlns.oracle.com/weblogic/weblogic-web-app
http://xmlns.oracle.com/weblogic/weblogic-web-app/1.4/we
blogic-web-app.xsd">
<wls:container-descriptor>
<wls:prefer-application-packages>
<wls:package-name>org.slf4j</wls:package-name>
</wls:prefer-application-packages>
</wls:container-descriptor>
</wls:weblogic-web-app>
81.4部署WAR到Weblogic
635

X.附录
X.附录
636

附录A.常见应用属性
你可以在 application.properties/application.yml文件内部或通过命令行开
关来指定各种属性。本章节提供了一个常见SpringBoot属性的列表及使用这些属性
的底层类的引用。
注属性可以来自classpath下的其他jar文件中,所以你不应该把它当成详尽的列
表。定义你自己的属性也是相当合法的。
注示例文件只是一个指导。不要拷贝/粘贴整个内容到你的应用,而是只提取你需
要的属性。
#==============================================================
=====
#COMMONSPRINGBOOTPROPERTIES
#
#Thissamplefileisprovidedasaguideline.DoNOTcopyitin
its
#entiretytoyourownapplication.^^^
#==============================================================
=====
#----------------------------------------
#COREPROPERTIES
#----------------------------------------
#BANNER
banner.charset=UTF-8#Bannerfileencoding.
banner.location=classpath:banner.txt#Bannerfilelocation.
banner.image.location=classpath:banner.gif#Bannerimagefilel
ocation(jpg/pngcanalsobeused).
banner.image.width=#Widthofthebannerimageinchars(defaul
t76)
banner.image.height=#Heightofthebannerimageinchars(defa
ultbasedonimageheight)
banner.image.margin=#Lefthandimagemargininchars(default
2)
banner.image.invert=#Ifimagesshouldbeinvertedfordarkter
附录A.常见应用属性
637

minalthemes(defaultfalse)
#LOGGING
logging.config=#Locationoftheloggingconfigurationfile.Fo
rinstance`classpath:logback.xml`forLogback
logging.exception-conversion-word=%wEx#Conversionwordusedwh
enloggingexceptions.
logging.file=#Logfilename.Forinstance`myapp.log`
logging.level.*=#Loglevelsseveritymapping.Forinstance`lo
gging.level.org.springframework=DEBUG`
logging.path=#Locationofthelogfile.Forinstance`/var/log
`
logging.pattern.console=#Appenderpatternforoutputtotheco
nsole.Onlysupportedwiththedefaultlogbacksetup.
logging.pattern.file=#Appenderpatternforoutputtothefile.
Onlysupportedwiththedefaultlogbacksetup.
logging.pattern.level=#Appenderpatternforloglevel(default
%5p).Onlysupportedwiththedefaultlogbacksetup.
logging.register-shutdown-hook=false#Registerashutdownhook
fortheloggingsystemwhenitisinitialized.
#AOP
spring.aop.auto=true#Add@EnableAspectJAutoProxy.
spring.aop.proxy-target-class=false#Whethersubclass-based(CG
LIB)proxiesaretobecreated(true)asopposedtostandardJav
ainterface-basedproxies(false).
#IDENTITY(ContextIdApplicationContextInitializer)
spring.application.index=#Applicationindex.
spring.application.name=#Applicationname.
#ADMIN(SpringApplicationAdminJmxAutoConfiguration)
spring.application.admin.enabled=false#Enableadminfeaturesf
ortheapplication.
spring.application.admin.jmx-name=org.springframework.boot:type=
Admin,name=SpringApplication#JMXnameoftheapplicationadmin
MBean.
#AUTO-CONFIGURATION
spring.autoconfigure.exclude=#Auto-configurationclassestoex
附录A.常见应用属性
638

clude.
#SPRINGCORE
spring.beaninfo.ignore=true#SkipsearchofBeanInfoclasses.
#SPRINGCACHE(CacheProperties)
spring.cache.cache-names=#Comma-separatedlistofcachenames
tocreateifsupportedbytheunderlyingcachemanager.
spring.cache.caffeine.spec=#Thespectousetocreatecaches.
CheckCaffeineSpecformoredetailsonthespecformat.
spring.cache.couchbase.expiration=0#Entryexpirationinmillis
econds.Bydefaulttheentriesneverexpire.
spring.cache.ehcache.config=#Thelocationoftheconfiguration
filetousetoinitializeEhCache.
spring.cache.guava.spec=#Thespectousetocreatecaches.Che
ckCacheBuilderSpecformoredetailsonthespecformat.
spring.cache.hazelcast.config=#Thelocationoftheconfigurati
onfiletousetoinitializeHazelcast.
spring.cache.infinispan.config=#Thelocationoftheconfigurat
ionfiletousetoinitializeInfinispan.
spring.cache.jcache.config=#Thelocationoftheconfiguration
filetousetoinitializethecachemanager.
spring.cache.jcache.provider=#FullyqualifiednameoftheCach
ingProviderimplementationtousetoretrievetheJSR-107compli
antcachemanager.OnlyneededifmorethanoneJSR-107implemen
tationisavailableontheclasspath.
spring.cache.type=#Cachetype,auto-detectedaccordingtothe
environmentbydefault.
#SPRINGCONFIG-usingenvironmentpropertyonly(ConfigFileApp
licationListener)
spring.config.location=#Configfilelocations.
spring.config.name=application#Configfilename.
#HAZELCAST(HazelcastProperties)
spring.hazelcast.config=#Thelocationoftheconfigurationfil
etousetoinitializeHazelcast.
#PROJECTINFORMATION(ProjectInfoProperties)
spring.info.build.location=classpath:META-INF/build-info.propert
附录A.常见应用属性
639

ies#Locationofthegeneratedbuild-info.propertiesfile.
spring.info.git.location=classpath:git.properties#Locationof
thegeneratedgit.propertiesfile.
#JMX
spring.jmx.default-domain=#JMXdomainname.
spring.jmx.enabled=true#ExposemanagementbeanstotheJMXdom
ain.
spring.jmx.server=mbeanServer#MBeanServerbeanname.
#Email(MailProperties)
spring.mail.default-encoding=UTF-8#DefaultMimeMessageencodin
g.
spring.mail.host=#SMTPserverhost.Forinstance`smtp.example
.com`
spring.mail.jndi-name=#SessionJNDIname.Whenset,takesprec
edencetoothersmailsettings.
spring.mail.password=#LoginpasswordoftheSMTPserver.
spring.mail.port=#SMTPserverport.
spring.mail.properties.*=#AdditionalJavaMailsessionproperti
es.
spring.mail.protocol=smtp#ProtocolusedbytheSMTPserver.
spring.mail.test-connection=false#Testthatthemailserveris
availableonstartup.
spring.mail.username=#LoginuseroftheSMTPserver.
#APPLICATIONSETTINGS(SpringApplication)
spring.main.banner-mode=console#Modeusedtodisplaythebanne
rwhentheapplicationruns.
spring.main.sources=#Sources(classname,packagenameorXML
resourcelocation)toincludeintheApplicationContext.
spring.main.web-environment=#Runtheapplicationinawebenvi
ronment(auto-detectedbydefault).
#FILEENCODING(FileEncodingApplicationListener)
spring.mandatory-file-encoding=#Expectedcharacterencodingth
eapplicationmustuse.
#INTERNATIONALIZATION(MessageSourceAutoConfiguration)
spring.messages.always-use-message-format=false#Setwhetherto
附录A.常见应用属性
640

alwaysapplytheMessageFormatrules,parsingevenmessageswit
houtarguments.
spring.messages.basename=messages#Comma-separatedlistofbase
names,eachfollowingtheResourceBundleconvention.
spring.messages.cache-seconds=-1#Loadedresourcebundlefiles
cacheexpiration,inseconds.Whensetto-1,bundlesarecached
forever.
spring.messages.encoding=UTF-8#Messagebundlesencoding.
spring.messages.fallback-to-system-locale=true#Setwhetherto
fallbacktothesystemLocaleifnofilesforaspecificLocale
havebeenfound.
#OUTPUT
spring.output.ansi.enabled=detect#ConfiguretheANSIoutput.
#PIDFILE(ApplicationPidFileWriter)
spring.pid.fail-on-write-error=#FailifApplicationPidFileWrit
erisusedbutitcannotwritethePIDfile.
spring.pid.file=#LocationofthePIDfiletowrite(ifApplica
tionPidFileWriterisused).
#PROFILES
spring.profiles.active=#Comma-separatedlistofactiveprofile
s.
spring.profiles.include=#Unconditionallyactivatethespecifie
dcommaseparatedprofiles.
#SENDGRID(SendGridAutoConfiguration)
spring.sendgrid.api-key=#SendGridapikey(alternativetouser
name/password)
spring.sendgrid.username=#SendGridaccountusername
spring.sendgrid.password=#SendGridaccountpassword
spring.sendgrid.proxy.host=#SendGridproxyhost
spring.sendgrid.proxy.port=#SendGridproxyport
#----------------------------------------
#WEBPROPERTIES
#----------------------------------------
附录A.常见应用属性
641

#EMBEDDEDSERVERCONFIGURATION(ServerProperties)
server.address=#Networkaddresstowhichtheservershouldbin
dto.
server.compression.enabled=false#Ifresponsecompressionisen
abled.
server.compression.excluded-user-agents=#Listofuser-agentst
oexcludefromcompression.
server.compression.mime-types=#Comma-separatedlistofMIMEty
pesthatshouldbecompressed.Forinstance`text/html,text/css,
application/json`
server.compression.min-response-size=#Minimumresponsesizeth
atisrequiredforcompressiontobeperformed.Forinstance204
8
server.connection-timeout=#Timeinmillisecondsthatconnector
swillwaitforanotherHTTPrequestbeforeclosingtheconnecti
on.Whennotset,theconnector'scontainer-specificdefaultwil
lbeused.Useavalueof-1toindicateno(i.e.infinite)time
out.
server.context-parameters.*=#Servletcontextinitparameters.
Forinstance`server.context-parameters.a=alpha`
server.context-path=#Contextpathoftheapplication.
server.display-name=application#Displaynameoftheapplicatio
n.
server.max-http-header-size=0#MaximumsizeinbytesoftheHTT
Pmessageheader.
server.max-http-post-size=0#MaximumsizeinbytesoftheHTTP
postcontent.
server.error.include-stacktrace=never#Whentoincludea"stack
trace"attribute.
server.error.path=/error#Pathoftheerrorcontroller.
server.error.whitelabel.enabled=true#Enablethedefaulterror
pagedisplayedinbrowsersincaseofaservererror.
server.jetty.acceptors=#Numberofacceptorthreadstouse.
server.jetty.selectors=#Numberofselectorthreadstouse.
server.jsp-servlet.class-name=org.apache.jasper.servlet.JspServl
et#TheclassnameoftheJSPservlet.
server.jsp-servlet.init-parameters.*=#Initparametersusedto
configuretheJSPservlet
server.jsp-servlet.registered=true#WhetherornottheJSPserv
letisregistered
附录A.常见应用属性
642

server.port=8080#ServerHTTPport.
server.server-header=#ValuetousefortheServerresponsehea
der(noheaderissentifempty)
server.servlet-path=/#Pathofthemaindispatcherservlet.
server.use-forward-headers=#IfX-Forwarded-*headersshouldbe
appliedtotheHttpRequest.
server.session.cookie.comment=#Commentforthesessioncookie.
server.session.cookie.domain=#Domainforthesessioncookie.
server.session.cookie.http-only=#"HttpOnly"flagforthesessi
oncookie.
server.session.cookie.max-age=#Maximumageofthesessioncook
ieinseconds.
server.session.cookie.name=#Sessioncookiename.
server.session.cookie.path=#Pathofthesessioncookie.
server.session.cookie.secure=#"Secure"flagforthesessionco
okie.
server.session.persistent=false#Persistsessiondatabetweenr
estarts.
server.session.store-dir=#Directoryusedtostoresessiondata
.
server.session.timeout=#Sessiontimeoutinseconds.
server.session.tracking-modes=#Sessiontrackingmodes(oneor
moreofthefollowing:"cookie","url","ssl").
server.ssl.ciphers=#SupportedSSLciphers.
server.ssl.client-auth=#Whetherclientauthenticationiswante
d("want")orneeded("need").Requiresatruststore.
server.ssl.enabled=#EnableSSLsupport.
server.ssl.enabled-protocols=#EnabledSSLprotocols.
server.ssl.key-alias=#Aliasthatidentifiesthekeyinthekey
store.
server.ssl.key-password=#Passwordusedtoaccessthekeyinth
ekeystore.
server.ssl.key-store=#PathtothekeystorethatholdstheSSL
certificate(typicallyajksfile).
server.ssl.key-store-password=#Passwordusedtoaccessthekey
store.
server.ssl.key-store-provider=#Providerforthekeystore.
server.ssl.key-store-type=#Typeofthekeystore.
server.ssl.protocol=TLS#SSLprotocoltouse.
server.ssl.trust-store=#TruststorethatholdsSSLcertificate
附录A.常见应用属性
643

s.
server.ssl.trust-store-password=#Passwordusedtoaccessthet
ruststore.
server.ssl.trust-store-provider=#Providerforthetruststore.
server.ssl.trust-store-type=#Typeofthetruststore.
server.tomcat.accesslog.directory=logs#Directoryinwhichlog
filesarecreated.Canberelativetothetomcatbasedirorabs
olute.
server.tomcat.accesslog.enabled=false#Enableaccesslog.
server.tomcat.accesslog.pattern=common#Formatpatternforacce
sslogs.
server.tomcat.accesslog.prefix=access_log#Logfilenameprefix
.
server.tomcat.accesslog.rename-on-rotate=false#Deferinclusion
ofthedatestampinthefilenameuntilrotatetime.
server.tomcat.accesslog.suffix=.log#Logfilenamesuffix.
server.tomcat.background-processor-delay=30#Delayinsecondsb
etweentheinvocationofbackgroundProcessmethods.
server.tomcat.basedir=#Tomcatbasedirectory.Ifnotspecified
atemporarydirectorywillbeused.
server.tomcat.internal-proxies=10\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,
3}|\\
192\\.168\\.\\d{1,3}\\.\\d{1,3}|\\
169\\.254\\.\\d{1,3}\\.\\d{1,3}|\\
127\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}|\\
172\\.1[6-9]{1}\\.\\d{1,3}\\.\\d{1,3}|\\
172\\.2[0-9]{1}\\.\\d{1,3}\\.\\d{1,3}|\\
172\\.3[0-1]{1}\\.\\d{1,3}\\.\\d{1,3}#regularexpressi
onmatchingtrustedIPaddresses.
server.tomcat.max-threads=0#Maximumamountofworkerthreads.
server.tomcat.min-spare-threads=0#Minimumamountofworkerthr
eads.
server.tomcat.port-header=X-Forwarded-Port#NameoftheHTTPhe
aderusedtooverridetheoriginalportvalue.
server.tomcat.protocol-header=#Headerthatholdstheincoming
protocol,usuallynamed"X-Forwarded-Proto".
server.tomcat.protocol-header-https-value=https#Valueofthep
rotocolheaderthatindicatesthattheincomingrequestusesSSL
.
server.tomcat.redirect-context-root=#Whetherrequeststothec
附录A.常见应用属性
644

ontextrootshouldberedirectedbyappendinga/tothepath.
server.tomcat.remote-ip-header=#Nameofthehttpheaderfromw
hichtheremoteipisextracted.Forinstance`X-FORWARDED-FOR`
server.tomcat.uri-encoding=UTF-8#Characterencodingtouseto
decodetheURI.
server.undertow.accesslog.dir=#Undertowaccesslogdirectory.
server.undertow.accesslog.enabled=false#Enableaccesslog.
server.undertow.accesslog.pattern=common#Formatpatternforac
cesslogs.
server.undertow.accesslog.prefix=access_log.#Logfilenamepre
fix.
server.undertow.accesslog.suffix=log#Logfilenamesuffix.
server.undertow.buffer-size=#Sizeofeachbufferinbytes.
server.undertow.buffers-per-region=#Numberofbufferperregio
n.
server.undertow.direct-buffers=#AllocatebuffersoutsidetheJ
avaheap.
server.undertow.io-threads=#NumberofI/Othreadstocreatefo
rtheworker.
server.undertow.worker-threads=#Numberofworkerthreads.
#FREEMARKER(FreeMarkerAutoConfiguration)
spring.freemarker.allow-request-override=false#SetwhetherHtt
pServletRequestattributesareallowedtooverride(hide)contro
llergeneratedmodelattributesofthesamename.
spring.freemarker.allow-session-override=false#SetwhetherHtt
pSessionattributesareallowedtooverride(hide)controllerge
neratedmodelattributesofthesamename.
spring.freemarker.cache=false#Enabletemplatecaching.
spring.freemarker.charset=UTF-8#Templateencoding.
spring.freemarker.check-template-location=true#Checkthatthe
templateslocationexists.
spring.freemarker.content-type=text/html#Content-Typevalue.
spring.freemarker.enabled=true#EnableMVCviewresolutionfor
thistechnology.
spring.freemarker.expose-request-attributes=false#Setwhether
allrequestattributesshouldbeaddedtothemodelpriortomer
gingwiththetemplate.
spring.freemarker.expose-session-attributes=false#Setwhether
allHttpSessionattributesshouldbeaddedtothemodelpriorto
附录A.常见应用属性
645

mergingwiththetemplate.
spring.freemarker.expose-spring-macro-helpers=true#Setwhether
toexposeaRequestContextforusebySpring'smacrolibrary,u
nderthename"springMacroRequestContext".
spring.freemarker.prefer-file-system-access=true#Preferfiles
ystemaccessfortemplateloading.Filesystemaccessenablesho
tdetectionoftemplatechanges.
spring.freemarker.prefix=#Prefixthatgetsprependedtoviewn
ameswhenbuildingaURL.
spring.freemarker.request-context-attribute=#NameoftheReque
stContextattributeforallviews.
spring.freemarker.settings.*=#Well-knownFreeMarkerkeyswhich
willbepassedtoFreeMarker'sConfiguration.
spring.freemarker.suffix=#Suffixthatgetsappendedtoviewna
meswhenbuildingaURL.
spring.freemarker.template-loader-path=classpath:/templates/#C
omma-separatedlistoftemplatepaths.
spring.freemarker.view-names=#Whitelistofviewnamesthatca
nberesolved.
#GROOVYTEMPLATES(GroovyTemplateAutoConfiguration)
spring.groovy.template.allow-request-override=false#Setwhethe
rHttpServletRequestattributesareallowedtooverride(hide)c
ontrollergeneratedmodelattributesofthesamename.
spring.groovy.template.allow-session-override=false#Setwhethe
rHttpSessionattributesareallowedtooverride(hide)controll
ergeneratedmodelattributesofthesamename.
spring.groovy.template.cache=#Enabletemplatecaching.
spring.groovy.template.charset=UTF-8#Templateencoding.
spring.groovy.template.check-template-location=true#Checkthat
thetemplateslocationexists.
spring.groovy.template.configuration.*=#SeeGroovyMarkupConfig
urer
spring.groovy.template.content-type=test/html#Content-Typeval
ue.
spring.groovy.template.enabled=true#EnableMVCviewresolution
forthistechnology.
spring.groovy.template.expose-request-attributes=false#Setwhe
therallrequestattributesshouldbeaddedtothemodelpriort
omergingwiththetemplate.
附录A.常见应用属性
646

spring.groovy.template.expose-session-attributes=false#Setwhe
therallHttpSessionattributesshouldbeaddedtothemodelpri
ortomergingwiththetemplate.
spring.groovy.template.expose-spring-macro-helpers=true#Setwh
ethertoexposeaRequestContextforusebySpring'smacrolibra
ry,underthename"springMacroRequestContext".
spring.groovy.template.prefix=#Prefixthatgetsprependedtov
iewnameswhenbuildingaURL.
spring.groovy.template.request-context-attribute=#Nameofthe
RequestContextattributeforallviews.
spring.groovy.template.resource-loader-path=classpath:/templates
/#Templatepath.
spring.groovy.template.suffix=.tpl#Suffixthatgetsappendedt
oviewnameswhenbuildingaURL.
spring.groovy.template.view-names=#Whitelistofviewnamesth
atcanberesolved.
#SPRINGHATEOAS(HateoasProperties)
spring.hateoas.use-hal-as-default-json-media-type=true#Specify
ifapplication/hal+jsonresponsesshouldbesenttorequeststh
atacceptapplication/json.
#HTTPmessageconversion
spring.http.converters.preferred-json-mapper=jackson#Preferred
JSONmappertouseforHTTPmessageconversion.Setto"gson"t
oforcetheuseofGsonwhenbothitandJacksonareontheclas
spath.
#HTTPencoding(HttpEncodingProperties)
spring.http.encoding.charset=UTF-8#CharsetofHTTPrequestsan
dresponses.Addedtothe"Content-Type"headerifnotsetexpli
citly.
spring.http.encoding.enabled=true#Enablehttpencodingsupport
.
spring.http.encoding.force=#Forcetheencodingtotheconfigur
edcharsetonHTTPrequestsandresponses.
spring.http.encoding.force-request=#Forcetheencodingtothe
configuredcharsetonHTTPrequests.Defaultstotruewhen"forc
e"hasnotbeenspecified.
spring.http.encoding.force-response=#Forcetheencodingtothe
附录A.常见应用属性
647

configuredcharsetonHTTPresponses.
#MULTIPART(MultipartProperties)
spring.http.multipart.enabled=true#Enablesupportofmulti-par
tuploads.
spring.http.multipart.file-size-threshold=0#Thresholdafterwh
ichfileswillbewrittentodisk.Valuescanusethesuffixed"
MB"or"KB"toindicateaMegabyteorKilobytesize.
spring.http.multipart.location=#Intermediatelocationofuploa
dedfiles.
spring.http.multipart.max-file-size=1Mb#Maxfilesize.Values
canusethesuffixed"MB"or"KB"toindicateaMegabyteorKilo
bytesize.
spring.http.multipart.max-request-size=10Mb#Maxrequestsize.
Valuescanusethesuffixed"MB"or"KB"toindicateaMegabyte
orKilobytesize.
spring.http.multipart.resolve-lazily=false#Whethertoresolve
themultipartrequestlazilyatthetimeoffileorparameterac
cess.
#JACKSON(JacksonProperties)
spring.jackson.date-format=#Dateformatstringorafully-qual
ifieddateformatclassname.Forinstance`yyyy-MM-ddHH:mm:ss`
.
spring.jackson.default-property-inclusion=#Controlstheinclus
ionofpropertiesduringserialization.
spring.jackson.deserialization.*=#Jacksonon/offfeaturesthat
affectthewayJavaobjectsaredeserialized.
spring.jackson.generator.*=#Jacksonon/offfeaturesforgenera
tors.
spring.jackson.joda-date-time-format=#Jodadatetimeformatst
ring.Ifnotconfigured,"date-format"willbeusedasafallbac
kifitisconfiguredwithaformatstring.
spring.jackson.locale=#Localeusedforformatting.
spring.jackson.mapper.*=#Jacksongeneralpurposeon/offfeatur
es.
spring.jackson.parser.*=#Jacksonon/offfeaturesforparsers.
spring.jackson.property-naming-strategy=#Oneoftheconstants
onJackson'sPropertyNamingStrategy.Canalsobeafully-qualifi
edclassnameofaPropertyNamingStrategysubclass.
附录A.常见应用属性
648

spring.jackson.serialization.*=#Jacksonon/offfeaturesthata
ffectthewayJavaobjectsareserialized.
spring.jackson.serialization-inclusion=#Controlstheinclusion
ofpropertiesduringserialization.Configuredwithoneofthe
valuesinJackson'sJsonInclude.Includeenumeration.
spring.jackson.time-zone=#Timezoneusedwhenformattingdates
.Forinstance`America/Los_Angeles`
#JERSEY(JerseyProperties)
spring.jersey.application-path=#PaththatservesasthebaseU
RIfortheapplication.Overridesthevalueof"@ApplicationPath
"ifspecified.
spring.jersey.filter.order=0#Jerseyfilterchainorder.
spring.jersey.init.*=#InitparameterstopasstoJerseyviath
eservletorfilter.
spring.jersey.servlet.load-on-startup=-1#Loadonstartupprior
ityoftheJerseyservlet.
spring.jersey.type=servlet#Jerseyintegrationtype.
#SPRINGMOBILEDEVICEVIEWS(DeviceDelegatingViewResolverAutoCo
nfiguration)
spring.mobile.devicedelegatingviewresolver.enable-fallback=false
#Enablesupportforfallbackresolution.
spring.mobile.devicedelegatingviewresolver.enabled=false#Enabl
edeviceviewresolver.
spring.mobile.devicedelegatingviewresolver.mobile-prefix=mobile/
#Prefixthatgetsprependedtoviewnamesformobiledevices.
spring.mobile.devicedelegatingviewresolver.mobile-suffix=#Suff
ixthatgetsappendedtoviewnamesformobiledevices.
spring.mobile.devicedelegatingviewresolver.normal-prefix=#Pref
ixthatgetsprependedtoviewnamesfornormaldevices.
spring.mobile.devicedelegatingviewresolver.normal-suffix=#Suff
ixthatgetsappendedtoviewnamesfornormaldevices.
spring.mobile.devicedelegatingviewresolver.tablet-prefix=tablet/
#Prefixthatgetsprependedtoviewnamesfortabletdevices.
spring.mobile.devicedelegatingviewresolver.tablet-suffix=#Suff
ixthatgetsappendedtoviewnamesfortabletdevices.
#SPRINGMOBILESITEPREFERENCE(SitePreferenceAutoConfiguration
)
附录A.常见应用属性
649

spring.mobile.sitepreference.enabled=true#EnableSitePreferenc
eHandler.
#MUSTACHETEMPLATES(MustacheAutoConfiguration)
spring.mustache.allow-request-override=#SetwhetherHttpServle
tRequestattributesareallowedtooverride(hide)controllerge
neratedmodelattributesofthesamename.
spring.mustache.allow-session-override=#SetwhetherHttpSessio
nattributesareallowedtooverride(hide)controllergenerated
modelattributesofthesamename.
spring.mustache.cache=#Enabletemplatecaching.
spring.mustache.charset=#Templateencoding.
spring.mustache.check-template-location=#Checkthatthetempla
teslocationexists.
spring.mustache.content-type=#Content-Typevalue.
spring.mustache.enabled=#EnableMVCviewresolutionforthist
echnology.
spring.mustache.expose-request-attributes=#Setwhetherallreq
uestattributesshouldbeaddedtothemodelpriortomergingwi
ththetemplate.
spring.mustache.expose-session-attributes=#SetwhetherallHtt
pSessionattributesshouldbeaddedtothemodelpriortomergin
gwiththetemplate.
spring.mustache.expose-spring-macro-helpers=#Setwhethertoex
poseaRequestContextforusebySpring'smacrolibrary,undert
hename"springMacroRequestContext".
spring.mustache.prefix=classpath:/templates/#Prefixtoapplyt
otemplatenames.
spring.mustache.request-context-attribute=#NameoftheRequest
Contextattributeforallviews.
spring.mustache.suffix=.html#Suffixtoapplytotemplatenames
.
spring.mustache.view-names=#Whitelistofviewnamesthatcan
beresolved.
#SPRINGMVC(WebMvcProperties)
spring.mvc.async.request-timeout=#Amountoftime(inmilliseco
nds)beforeasynchronousrequesthandlingtimesout.
spring.mvc.date-format=#Dateformattouse.Forinstance`dd/M
M/yyyy`.
附录A.常见应用属性
650

spring.mvc.dispatch-trace-request=false#DispatchTRACErequest
stotheFrameworkServletdoServicemethod.
spring.mvc.dispatch-options-request=true#DispatchOPTIONSrequ
eststotheFrameworkServletdoServicemethod.
spring.mvc.favicon.enabled=true#Enableresolutionoffavicon.i
co.
spring.mvc.formcontent.putfilter.enabled=true#EnableSpring's
HttpPutFormContentFilter.
spring.mvc.ignore-default-model-on-redirect=true#Iftheconten
tofthe"default"modelshouldbeignoredduringredirectscena
rios.
spring.mvc.locale=#Localetouse.Bydefault,thislocaleiso
verriddenbythe"Accept-Language"header.
spring.mvc.locale-resolver=accept-header#Definehowthelocale
shouldberesolved.
spring.mvc.log-resolved-exception=false#Enablewarnloggingof
exceptionsresolvedbya"HandlerExceptionResolver".
spring.mvc.media-types.*=#Mapsfileextensionstomediatypes
forcontentnegotiation.
spring.mvc.message-codes-resolver-format=#Formattingstrategy
formessagecodes.Forinstance`PREFIX_ERROR_CODE`.
spring.mvc.servlet.load-on-startup=-1#Loadonstartuppriority
oftheSpringWebServicesservlet.
spring.mvc.static-path-pattern=/**#Pathpatternusedforstati
cresources.
spring.mvc.throw-exception-if-no-handler-found=false#Ifa"NoH
andlerFoundException"shouldbethrownifnoHandlerwasfoundt
oprocessarequest.
spring.mvc.view.prefix=#SpringMVCviewprefix.
spring.mvc.view.suffix=#SpringMVCviewsuffix.
#SPRINGRESOURCESHANDLING(ResourceProperties)
spring.resources.add-mappings=true#Enabledefaultresourcehan
dling.
spring.resources.cache-period=#Cacheperiodfortheresources
servedbytheresourcehandler,inseconds.
spring.resources.chain.cache=true#EnablecachingintheResour
cechain.
spring.resources.chain.enabled=#EnabletheSpringResourceHan
dlingchain.Disabledbydefaultunlessatleastonestrategyha
附录A.常见应用属性
651

sbeenenabled.
spring.resources.chain.gzipped=false#Enableresolutionofalre
adygzippedresources.
spring.resources.chain.html-application-cache=false#EnableHTM
L5applicationcachemanifestrewriting.
spring.resources.chain.strategy.content.enabled=false#Enablet
hecontentVersionStrategy.
spring.resources.chain.strategy.content.paths=/**#Comma-separa
tedlistofpatternstoapplytotheVersionStrategy.
spring.resources.chain.strategy.fixed.enabled=false#Enablethe
fixedVersionStrategy.
spring.resources.chain.strategy.fixed.paths=/**#Comma-separate
dlistofpatternstoapplytotheVersionStrategy.
spring.resources.chain.strategy.fixed.version=#Versionstring
tousefortheVersionStrategy.
spring.resources.static-locations=classpath:/META-INF/resources/
,classpath:/resources/,classpath:/static/,classpath:/public/#L
ocationsofstaticresources.
#SPRINGSESSION(SessionProperties)
spring.session.hazelcast.map-name=spring:session:sessions#Name
ofthemapusedtostoresessions.
spring.session.jdbc.initializer.enabled=#Createtherequireds
essiontablesonstartupifnecessary.Enabledautomaticallyif
thedefaulttablenameissetoracustomschemaisconfigured.
spring.session.jdbc.schema=classpath:org/springframework/session
/jdbc/schema-@@platform@@.sql#PathtotheSQLfiletousetoi
nitializethedatabaseschema.
spring.session.jdbc.table-name=SPRING_SESSION#Nameofdatabase
tableusedtostoresessions.
spring.session.mongo.collection-name=sessions#Collectionname
usedtostoresessions.
spring.session.redis.flush-mode=#FlushmodefortheRedissess
ions.
spring.session.redis.namespace=#Namespaceforkeysusedtosto
resessions.
spring.session.store-type=#Sessionstoretype.
#SPRINGSOCIAL(SocialWebAutoConfiguration)
spring.social.auto-connection-views=false#Enabletheconnectio
附录A.常见应用属性
652

nstatusviewforsupportedproviders.
#SPRINGSOCIALFACEBOOK(FacebookAutoConfiguration)
spring.social.facebook.app-id=#yourapplication'sFacebookApp
ID
spring.social.facebook.app-secret=#yourapplication'sFacebook
AppSecret
#SPRINGSOCIALLINKEDIN(LinkedInAutoConfiguration)
spring.social.linkedin.app-id=#yourapplication'sLinkedInApp
ID
spring.social.linkedin.app-secret=#yourapplication'sLinkedIn
AppSecret
#SPRINGSOCIALTWITTER(TwitterAutoConfiguration)
spring.social.twitter.app-id=#yourapplication'sTwitterAppI
D
spring.social.twitter.app-secret=#yourapplication'sTwitterA
ppSecret
#THYMELEAF(ThymeleafAutoConfiguration)
spring.thymeleaf.cache=true#Enabletemplatecaching.
spring.thymeleaf.check-template=true#Checkthatthetemplatee
xistsbeforerenderingit.
spring.thymeleaf.check-template-location=true#Checkthatthet
emplateslocationexists.
spring.thymeleaf.content-type=text/html#Content-Typevalue.
spring.thymeleaf.enabled=true#EnableMVCThymeleafviewresolu
tion.
spring.thymeleaf.encoding=UTF-8#Templateencoding.
spring.thymeleaf.excluded-view-names=#Comma-separatedlistof
viewnamesthatshouldbeexcludedfromresolution.
spring.thymeleaf.mode=HTML5#Templatemodetobeappliedtotem
plates.SeealsoStandardTemplateModeHandlers.
spring.thymeleaf.prefix=classpath:/templates/#Prefixthatgets
prependedtoviewnameswhenbuildingaURL.
spring.thymeleaf.suffix=.html#Suffixthatgetsappendedtovie
wnameswhenbuildingaURL.
spring.thymeleaf.template-resolver-order=#Orderofthetemplat
eresolverinthechain.
附录A.常见应用属性
653

spring.thymeleaf.view-names=#Comma-separatedlistofviewname
sthatcanberesolved.
#VELOCITYTEMPLATES(VelocityAutoConfiguration)
spring.velocity.allow-request-override=false#SetwhetherHttpS
ervletRequestattributesareallowedtooverride(hide)controll
ergeneratedmodelattributesofthesamename.
spring.velocity.allow-session-override=false#SetwhetherHttpS
essionattributesareallowedtooverride(hide)controllergene
ratedmodelattributesofthesamename.
spring.velocity.cache=#Enabletemplatecaching.
spring.velocity.charset=UTF-8#Templateencoding.
spring.velocity.check-template-location=true#Checkthatthete
mplateslocationexists.
spring.velocity.content-type=text/html#Content-Typevalue.
spring.velocity.date-tool-attribute=#NameoftheDateToolhelp
erobjecttoexposeintheVelocitycontextoftheview.
spring.velocity.enabled=true#EnableMVCviewresolutionforth
istechnology.
spring.velocity.expose-request-attributes=false#Setwhetheral
lrequestattributesshouldbeaddedtothemodelpriortomergi
ngwiththetemplate.
spring.velocity.expose-session-attributes=false#Setwhetheral
lHttpSessionattributesshouldbeaddedtothemodelpriortom
ergingwiththetemplate.
spring.velocity.expose-spring-macro-helpers=true#Setwhethert
oexposeaRequestContextforusebySpring'smacrolibrary,und
erthename"springMacroRequestContext".
spring.velocity.number-tool-attribute=#NameoftheNumberTool
helperobjecttoexposeintheVelocitycontextoftheview.
spring.velocity.prefer-file-system-access=true#Preferfilesys
temaccessfortemplateloading.Filesystemaccessenableshot
detectionoftemplatechanges.
spring.velocity.prefix=#Prefixthatgetsprependedtoviewnam
eswhenbuildingaURL.
spring.velocity.properties.*=#Additionalvelocityproperties.
spring.velocity.request-context-attribute=#NameoftheRequest
Contextattributeforallviews.
spring.velocity.resource-loader-path=classpath:/templates/#Tem
platepath.
附录A.常见应用属性
654

spring.velocity.suffix=.vm#Suffixthatgetsappendedtoviewn
ameswhenbuildingaURL.
spring.velocity.toolbox-config-location=#VelocityToolboxconf
iglocation.Forinstance`/WEB-INF/toolbox.xml`
spring.velocity.view-names=#Whitelistofviewnamesthatcan
beresolved.
#SPRINGWEBSERVICES(WebServicesProperties)
spring.webservices.path=/services#Paththatservesasthebase
URIfortheservices.
spring.webservices.servlet.init=#Servletinitparameterstopa
sstoSpringWebServices.
spring.webservices.servlet.load-on-startup=-1#Loadonstartup
priorityoftheSpringWebServicesservlet.
#----------------------------------------
#SECURITYPROPERTIES
#----------------------------------------
#SECURITY(SecurityProperties)
security.basic.authorize-mode=role#Securityauthorizemodeto
apply.
security.basic.enabled=true#Enablebasicauthentication.
security.basic.path=/**#Comma-separatedlistofpathstosecur
e.
security.basic.realm=Spring#HTTPbasicrealmname.
security.enable-csrf=false#EnableCrossSiteRequestForgerys
upport.
security.filter-order=0#Securityfilterchainorder.
security.filter-dispatcher-types=ASYNC,FORWARD,INCLUDE,REQUES
T#Securityfilterchaindispatchertypes.
security.headers.cache=true#EnablecachecontrolHTTPheaders.
security.headers.content-type=true#Enable"X-Content-Type-Opti
ons"header.
security.headers.frame=true#Enable"X-Frame-Options"header.
security.headers.hsts=#HTTPStrictTransportSecurity(HSTS)m
ode(none,domain,all).
security.headers.xss=true#Enablecrosssitescripting(XSS)pr
otection.
附录A.常见应用属性
655

security.ignored=#Comma-separatedlistofpathstoexcludefro
mthedefaultsecuredpaths.
security.require-ssl=false#Enablesecurechannelforallreque
sts.
security.sessions=stateless#Sessioncreationpolicy(always,n
ever,if_required,stateless).
security.user.name=user#Defaultusername.
security.user.password=#Passwordforthedefaultusername.A
randompasswordisloggedonstartupbydefault.
security.user.role=USER#Grantedrolesforthedefaultusernam
e.
#SECURITYOAUTH2CLIENT(OAuth2ClientProperties
security.oauth2.client.client-id=#OAuth2clientid.
security.oauth2.client.client-secret=#OAuth2clientsecret.A
randomsecretisgeneratedbydefault
#SECURITYOAUTH2RESOURCES(ResourceServerProperties
security.oauth2.resource.id=#Identifieroftheresource.
security.oauth2.resource.jwt.key-uri=#TheURIoftheJWTtoken
.Canbesetifthevalueisnotavailableandthekeyispublic
.
security.oauth2.resource.jwt.key-value=#Theverificationkeyo
ftheJWTtoken.CaneitherbeasymmetricsecretorPEM-encoded
RSApublickey.
security.oauth2.resource.prefer-token-info=true#Usethetoken
info,canbesettofalsetousetheuserinfo.
security.oauth2.resource.service-id=resource#
security.oauth2.resource.token-info-uri=#URIofthetokendeco
dingendpoint.
security.oauth2.resource.token-type=#Thetokentypetosendwh
enusingtheuserInfoUri.
security.oauth2.resource.user-info-uri=#URIoftheuserendpoi
nt.
#SECURITYOAUTH2SSO(OAuth2SsoProperties
security.oauth2.sso.filter-order=#Filterordertoapplyifnot
providinganexplicitWebSecurityConfigurerAdapter
security.oauth2.sso.login-path=/login#Pathtotheloginpage,
i.e.theonethattriggerstheredirecttotheOAuth2Authorizat
附录A.常见应用属性
656

ionServer
#----------------------------------------
#DATAPROPERTIES
#----------------------------------------
#FLYWAY(FlywayProperties)
flyway.baseline-description=#
flyway.baseline-version=1#versiontostartmigration
flyway.baseline-on-migrate=#
flyway.check-location=false#Checkthatmigrationscriptslocat
ionexists.
flyway.clean-on-validation-error=#
flyway.enabled=true#Enableflyway.
flyway.encoding=#
flyway.ignore-failed-future-migration=#
flyway.init-sqls=#SQLstatementstoexecutetoinitializeaco
nnectionimmediatelyafterobtainingit.
flyway.locations=classpath:db/migration#locationsofmigration
sscripts
flyway.out-of-order=#
flyway.password=#JDBCpasswordifyouwantFlywaytocreateit
sownDataSource
flyway.placeholder-prefix=#
flyway.placeholder-replacement=#
flyway.placeholder-suffix=#
flyway.placeholders.*=#
flyway.schemas=#schemastoupdate
flyway.sql-migration-prefix=V#
flyway.sql-migration-separator=#
flyway.sql-migration-suffix=.sql#
flyway.table=#
flyway.url=#JDBCurlofthedatabasetomigrate.Ifnotset,t
heprimaryconfigureddatasourceisused.
flyway.user=#Loginuserofthedatabasetomigrate.
flyway.validate-on-migrate=#
#LIQUIBASE(LiquibaseProperties)
liquibase.change-log=classpath:/db/changelog/db.changelog-master
附录A.常见应用属性
657

.yaml#Changelogconfigurationpath.
liquibase.check-change-log-location=true#Checkthechangelog
locationexists.
liquibase.contexts=#Comma-separatedlistofruntimecontextst
ouse.
liquibase.default-schema=#Defaultdatabaseschema.
liquibase.drop-first=false#Dropthedatabaseschemafirst.
liquibase.enabled=true#Enableliquibasesupport.
liquibase.labels=#Comma-separatedlistofruntimelabelstous
e.
liquibase.parameters.*=#Changelogparameters.
liquibase.password=#Loginpasswordofthedatabasetomigrate.
liquibase.rollback-file=#FiletowhichrollbackSQLwillbewr
ittenwhenanupdateisperformed.
liquibase.url=#JDBCurlofthedatabasetomigrate.Ifnotset
,theprimaryconfigureddatasourceisused.
liquibase.user=#Loginuserofthedatabasetomigrate.
#COUCHBASE(CouchbaseProperties)
spring.couchbase.bootstrap-hosts=#Couchbasenodes(hostorIP
address)tobootstrapfrom.
spring.couchbase.bucket.name=default#Nameofthebuckettocon
nectto.
spring.couchbase.bucket.password=#Passwordofthebucket.
spring.couchbase.env.endpoints.key-value=1#Numberofsocketsp
ernodeagainsttheKey/valueservice.
spring.couchbase.env.endpoints.query=1#Numberofsocketspern
odeagainsttheQuery(N1QL)service.
spring.couchbase.env.endpoints.view=1#Numberofsocketsperno
deagainsttheviewservice.
spring.couchbase.env.ssl.enabled=#EnableSSLsupport.Enabled
automaticallyifa"keyStore"isprovidedunlessspecifiedother
wise.
spring.couchbase.env.ssl.key-store=#PathtotheJVMkeystore
thatholdsthecertificates.
spring.couchbase.env.ssl.key-store-password=#Passwordusedto
accessthekeystore.
spring.couchbase.env.timeouts.connect=5000#Bucketconnections
timeoutinmilliseconds.
spring.couchbase.env.timeouts.key-value=2500#Blockingoperatio
附录A.常见应用属性
658

nsperformedonaspecifickeytimeoutinmilliseconds.
spring.couchbase.env.timeouts.query=7500#N1QLqueryoperations
timeoutinmilliseconds.
spring.couchbase.env.timeouts.socket-connect=1000#Socketconne
ctconnectionstimeoutinmilliseconds.
spring.couchbase.env.timeouts.view=7500#Regularandgeospatial
viewoperationstimeoutinmilliseconds.
#DAO(PersistenceExceptionTranslationAutoConfiguration)
spring.dao.exceptiontranslation.enabled=true#EnablethePersis
tenceExceptionTranslationPostProcessor.
#CASSANDRA(CassandraProperties)
spring.data.cassandra.cluster-name=#NameoftheCassandraclus
ter.
spring.data.cassandra.compression=#Compressionsupportedbyth
eCassandrabinaryprotocol.
spring.data.cassandra.connect-timeout-millis=#Socketoption:c
onnectiontimeout.
spring.data.cassandra.consistency-level=#Queriesconsistencyl
evel.
spring.data.cassandra.contact-points=localhost#Comma-separated
listofclusternodeaddresses.
spring.data.cassandra.fetch-size=#Queriesdefaultfetchsize.
spring.data.cassandra.keyspace-name=#Keyspacenametouse.
spring.data.cassandra.load-balancing-policy=#Classnameofthe
loadbalancingpolicy.
spring.data.cassandra.port=#PortoftheCassandraserver.
spring.data.cassandra.password=#Loginpasswordoftheserver.
spring.data.cassandra.read-timeout-millis=#Socketoption:read
timeout.
spring.data.cassandra.reconnection-policy=#Reconnectionpolicy
class.
spring.data.cassandra.retry-policy=#Classnameoftheretrypo
licy.
spring.data.cassandra.serial-consistency-level=#Queriesserial
consistencylevel.
spring.data.cassandra.schema-action=none#Schemaactiontotake
atstartup.
spring.data.cassandra.ssl=false#EnableSSLsupport.
附录A.常见应用属性
659

spring.data.cassandra.username=#Loginuseroftheserver.
#DATACOUCHBASE(CouchbaseDataProperties)
spring.data.couchbase.auto-index=false#Automaticallycreatevi
ewsandindexes.
spring.data.couchbase.consistency=read-your-own-writes#Consist
encytoapplybydefaultongeneratedqueries.
spring.data.couchbase.repositories.enabled=true#EnableCouchba
serepositories.
#ELASTICSEARCH(ElasticsearchProperties)
spring.data.elasticsearch.cluster-name=elasticsearch#Elasticse
archclustername.
spring.data.elasticsearch.cluster-nodes=#Comma-separatedlist
ofclusternodeaddresses.Ifnotspecified,startsaclientnod
e.
spring.data.elasticsearch.properties.*=#Additionalproperties
usedtoconfiguretheclient.
spring.data.elasticsearch.repositories.enabled=true#EnableEla
sticsearchrepositories.
#MONGODB(MongoProperties)
spring.data.mongodb.authentication-database=#Authenticationda
tabasename.
spring.data.mongodb.database=test#Databasename.
spring.data.mongodb.field-naming-strategy=#Fullyqualifiednam
eoftheFieldNamingStrategytouse.
spring.data.mongodb.grid-fs-database=#GridFSdatabasename.
spring.data.mongodb.host=localhost#Mongoserverhost.
spring.data.mongodb.password=#Loginpasswordofthemongoserv
er.
spring.data.mongodb.port=27017#Mongoserverport.
spring.data.mongodb.repositories.enabled=true#EnableMongorep
ositories.
spring.data.mongodb.uri=mongodb://localhost/test#Mongodatabas
eURI.Whenset,hostandportareignored.
spring.data.mongodb.username=#Loginuserofthemongoserver.
#DATAREDIS
spring.data.redis.repositories.enabled=true#EnableRedisrepos
附录A.常见应用属性
660

itories.
#NEO4J(Neo4jProperties)
spring.data.neo4j.compiler=#Compilertouse.
spring.data.neo4j.embedded.enabled=true#Enableembeddedmodei
ftheembeddeddriverisavailable.
spring.data.neo4j.password=#Loginpasswordoftheserver.
spring.data.neo4j.repositories.enabled=true#EnableNeo4jrepos
itories.
spring.data.neo4j.session.scope=singleton#Scope(lifetime)of
thesession.
spring.data.neo4j.uri=#URIusedbythedriver.Auto-detectedb
ydefault.
spring.data.neo4j.username=#Loginuseroftheserver.
#DATAREST(RepositoryRestProperties)
spring.data.rest.base-path=#BasepathtobeusedbySpringDat
aRESTtoexposerepositoryresources.
spring.data.rest.default-page-size=#Defaultsizeofpages.
spring.data.rest.enable-enum-translation=#Enableenumvaluetr
anslationviatheSpringDataRESTdefaultresourcebundle.
spring.data.rest.limit-param-name=#NameoftheURLquerystrin
gparameterthatindicateshowmanyresultstoreturnatonce.
spring.data.rest.max-page-size=#Maximumsizeofpages.
spring.data.rest.page-param-name=#NameoftheURLquerystring
parameterthatindicateswhatpagetoreturn.
spring.data.rest.return-body-on-create=#Returnaresponsebody
aftercreatinganentity.
spring.data.rest.return-body-on-update=#Returnaresponsebody
afterupdatinganentity.
spring.data.rest.sort-param-name=#NameoftheURLquerystring
parameterthatindicateswhatdirectiontosortresults.
#SOLR(SolrProperties)
spring.data.solr.host=http://127.0.0.1:8983/solr#Solrhost.Ig
noredif"zk-host"isset.
spring.data.solr.repositories.enabled=true#EnableSolrreposit
ories.
spring.data.solr.zk-host=#ZooKeeperhostaddressintheformH
OST:PORT.
附录A.常见应用属性
661

#DATASOURCE(DataSourceAutoConfiguration&DataSourceProperties
)
spring.datasource.continue-on-error=false#Donotstopifaner
roroccurswhileinitializingthedatabase.
spring.datasource.data=#Data(DML)scriptresourcereference.
spring.datasource.data-username=#Userofthedatabasetoexecu
teDMLscripts(ifdifferent).
spring.datasource.data-password=#Passwordofthedatabasetoe
xecuteDMLscripts(ifdifferent).
spring.datasource.dbcp.*=#CommonsDBCPspecificsettings
spring.datasource.dbcp2.*=#CommonsDBCP2specificsettings
spring.datasource.driver-class-name=#Fullyqualifiednameoft
heJDBCdriver.Auto-detectedbasedontheURLbydefault.
spring.datasource.hikari.*=#Hikarispecificsettings
spring.datasource.initialize=true#Populatethedatabaseusing
'data.sql'.
spring.datasource.jmx-enabled=false#EnableJMXsupport(ifpro
videdbytheunderlyingpool).
spring.datasource.jndi-name=#JNDIlocationofthedatasource.
Class,url,username&passwordareignoredwhenset.
spring.datasource.name=testdb#Nameofthedatasource.
spring.datasource.password=#Loginpasswordofthedatabase.
spring.datasource.platform=all#Platformtouseintheschemar
esource(schema-${platform}.sql).
spring.datasource.schema=#Schema(DDL)scriptresourcereferen
ce.
spring.datasource.schema-username=#Userofthedatabasetoexe
cuteDDLscripts(ifdifferent).
spring.datasource.schema-password=#Passwordofthedatabaseto
executeDDLscripts(ifdifferent).
spring.datasource.separator=;#StatementseparatorinSQLiniti
alizationscripts.
spring.datasource.sql-script-encoding=#SQLscriptsencoding.
spring.datasource.tomcat.*=#Tomcatdatasourcespecificsetting
s
spring.datasource.type=#Fullyqualifiednameoftheconnection
poolimplementationtouse.Bydefault,itisauto-detectedfro
mtheclasspath.
spring.datasource.url=#JDBCurlofthedatabase.
附录A.常见应用属性
662

spring.datasource.username=
#JEST(ElasticsearchHTTPclient)(JestProperties)
spring.elasticsearch.jest.connection-timeout=3000#Connectiont
imeoutinmilliseconds.
spring.elasticsearch.jest.password=#Loginpassword.
spring.elasticsearch.jest.proxy.host=#ProxyhosttheHTTPclie
ntshoulduse.
spring.elasticsearch.jest.proxy.port=#ProxyporttheHTTPclie
ntshoulduse.
spring.elasticsearch.jest.read-timeout=3000#Readtimeoutinmi
lliseconds.
spring.elasticsearch.jest.uris=http://localhost:9200#Comma-sep
aratedlistoftheElasticsearchinstancestouse.
spring.elasticsearch.jest.username=#Loginuser.
#H2WebConsole(H2ConsoleProperties)
spring.h2.console.enabled=false#Enabletheconsole.
spring.h2.console.path=/h2-console#Pathatwhichtheconsolew
illbeavailable.
spring.h2.console.settings.trace=false#Enabletraceoutput.
spring.h2.console.settings.web-allow-others=false#Enableremot
eaccess.
#JOOQ(JooqAutoConfiguration)
spring.jooq.sql-dialect=#SQLDialectJOOQusedwhencommunicati
ngwiththeconfigureddatasource.Forinstance`POSTGRES`
#JPA(JpaBaseConfiguration,HibernateJpaAutoConfiguration)
spring.data.jpa.repositories.enabled=true#EnableJPArepositor
ies.
spring.jpa.database=#Targetdatabasetooperateon,auto-detec
tedbydefault.Canbealternativelysetusingthe"databasePlat
form"property.
spring.jpa.database-platform=#Nameofthetargetdatabasetoo
perateon,auto-detectedbydefault.Canbealternativelysetus
ingthe"Database"enum.
spring.jpa.generate-ddl=false#Initializetheschemaonstartup
.
spring.jpa.hibernate.ddl-auto=#DDLmode.Thisisactuallyash
附录A.常见应用属性
663

ortcutforthe"hibernate.hbm2ddl.auto"property.Defaultto"cr
eate-drop"whenusinganembeddeddatabase,"none"otherwise.
spring.jpa.hibernate.naming.implicit-strategy=#Hibernate5imp
licitnamingstrategyfullyqualifiedname.
spring.jpa.hibernate.naming.physical-strategy=#Hibernate5phy
sicalnamingstrategyfullyqualifiedname.
spring.jpa.hibernate.naming.strategy=#Hibernate4namingstrat
egyfullyqualifiedname.NotsupportedwithHibernate5.
spring.jpa.hibernate.use-new-id-generator-mappings=#UseHibern
ate'snewerIdentifierGeneratorforAUTO,TABLEandSEQUENCE.
spring.jpa.open-in-view=true#RegisterOpenEntityManagerInViewI
nterceptor.BindsaJPAEntityManagertothethreadfortheenti
reprocessingoftherequest.
spring.jpa.properties.*=#Additionalnativepropertiestoseto
ntheJPAprovider.
spring.jpa.show-sql=false#EnableloggingofSQLstatements.
#JTA(JtaAutoConfiguration)
spring.jta.enabled=true#EnableJTAsupport.
spring.jta.log-dir=#Transactionlogsdirectory.
spring.jta.transaction-manager-id=#Transactionmanagerunique
identifier.
#ATOMIKOS(AtomikosProperties)
spring.jta.atomikos.connectionfactory.borrow-connection-timeout=
30#Timeout,inseconds,forborrowingconnectionsfromthepoo
l.
spring.jta.atomikos.connectionfactory.ignore-session-transacted-
flag=true#Whetherornottoignorethetransactedflagwhencr
eatingsession.
spring.jta.atomikos.connectionfactory.local-transaction-mode=fal
se#Whetherornotlocaltransactionsaredesired.
spring.jta.atomikos.connectionfactory.maintenance-interval=60#
Thetime,inseconds,betweenrunsofthepool'smaintenancethr
ead.
spring.jta.atomikos.connectionfactory.max-idle-time=60#Thetim
e,inseconds,afterwhichconnectionsarecleanedupfromthep
ool.
spring.jta.atomikos.connectionfactory.max-lifetime=0#Thetime,
inseconds,thataconnectioncanbepooledforbeforebeingde
附录A.常见应用属性
664

stroyed.0denotesnolimit.
spring.jta.atomikos.connectionfactory.max-pool-size=1#Themaxi
mumsizeofthepool.
spring.jta.atomikos.connectionfactory.min-pool-size=1#Themini
mumsizeofthepool.
spring.jta.atomikos.connectionfactory.reap-timeout=0#Thereap
timeout,inseconds,forborrowedconnections.0denotesnolimi
t.
spring.jta.atomikos.connectionfactory.unique-resource-name=jmsCo
nnectionFactory#Theuniquenameusedtoidentifytheresource
duringrecovery.
spring.jta.atomikos.datasource.borrow-connection-timeout=30#Ti
meout,inseconds,forborrowingconnectionsfromthepool.
spring.jta.atomikos.datasource.default-isolation-level=#Defaul
tisolationlevelofconnectionsprovidedbythepool.
spring.jta.atomikos.datasource.login-timeout=#Timeout,inseco
nds,forestablishingadatabaseconnection.
spring.jta.atomikos.datasource.maintenance-interval=60#Thetim
e,inseconds,betweenrunsofthepool'smaintenancethread.
spring.jta.atomikos.datasource.max-idle-time=60#Thetime,ins
econds,afterwhichconnectionsarecleanedupfromthepool.
spring.jta.atomikos.datasource.max-lifetime=0#Thetime,insec
onds,thataconnectioncanbepooledforbeforebeingdestroyed
.0denotesnolimit.
spring.jta.atomikos.datasource.max-pool-size=1#Themaximumsiz
eofthepool.
spring.jta.atomikos.datasource.min-pool-size=1#Theminimumsiz
eofthepool.
spring.jta.atomikos.datasource.reap-timeout=0#Thereaptimeout
,inseconds,forborrowedconnections.0denotesnolimit.
spring.jta.atomikos.datasource.test-query=#SQLqueryorstatem
entusedtovalidateaconnectionbeforereturningit.
spring.jta.atomikos.datasource.unique-resource-name=dataSource#
Theuniquenameusedtoidentifytheresourceduringrecovery.
spring.jta.atomikos.properties.checkpoint-interval=500#Interva
lbetweencheckpoints.
spring.jta.atomikos.properties.console-file-count=1#Numberof
debuglogsfilesthatcanbecreated.
spring.jta.atomikos.properties.console-file-limit=-1#Howmany
bytescanbestoredatmostindebuglogsfiles.
附录A.常见应用属性
665

spring.jta.atomikos.properties.console-file-name=tm.out#Debug
logsfilename.
spring.jta.atomikos.properties.console-log-level=#Consolelog
level.
spring.jta.atomikos.properties.default-jta-timeout=10000#Defau
lttimeoutforJTAtransactions.
spring.jta.atomikos.properties.enable-logging=true#Enabledisk
logging.
spring.jta.atomikos.properties.force-shutdown-on-vm-exit=false#
SpecifyifaVMshutdownshouldtriggerforcedshutdownofthe
transactioncore.
spring.jta.atomikos.properties.log-base-dir=#Directoryinwhic
hthelogfilesshouldbestored.
spring.jta.atomikos.properties.log-base-name=tmlog#Transaction
slogfilebasename.
spring.jta.atomikos.properties.max-actives=50#Maximumnumbero
factivetransactions.
spring.jta.atomikos.properties.max-timeout=300000#Maximumtime
out(inmilliseconds)thatcanbeallowedfortransactions.
spring.jta.atomikos.properties.output-dir=#Directoryinwhich
tostorethedebuglogfiles.
spring.jta.atomikos.properties.serial-jta-transactions=true#Sp
ecifyifsub-transactionsshouldbejoinedwhenpossible.
spring.jta.atomikos.properties.service=#Transactionmanagerim
plementationthatshouldbestarted.
spring.jta.atomikos.properties.threaded-two-phase-commit=true#
Usedifferent(andconcurrent)threadsfortwo-phasecommitont
heparticipatingresources.
spring.jta.atomikos.properties.transaction-manager-unique-name=
#Transactionmanager'suniquename.
#BITRONIX
spring.jta.bitronix.connectionfactory.acquire-increment=1#Numb
erofconnectionstocreatewhengrowingthepool.
spring.jta.bitronix.connectionfactory.acquisition-interval=1#T
ime,inseconds,towaitbeforetryingtoacquireaconnectiona
gainafteraninvalidconnectionwasacquired.
spring.jta.bitronix.connectionfactory.acquisition-timeout=30#T
imeout,inseconds,foracquiringconnectionsfromthepool.
spring.jta.bitronix.connectionfactory.allow-local-transactions=t
附录A.常见应用属性
666

rue#Whetherornotthetransactionmanagershouldallowmixing
XAandnon-XAtransactions.
spring.jta.bitronix.connectionfactory.apply-transaction-timeout=
false#Whetherornotthetransactiontimeoutshouldbeseton
theXAResourcewhenitisenlisted.
spring.jta.bitronix.connectionfactory.automatic-enlisting-enable
d=true#Whetherornotresourcesshouldbeenlistedanddeliste
dautomatically.
spring.jta.bitronix.connectionfactory.cache-producers-consumers=
true#Whetherornotproducesandconsumersshouldbecached.
spring.jta.bitronix.connectionfactory.defer-connection-release=t
rue#Whetherornottheprovidercanrunmanytransactionsont
hesameconnectionandsupportstransactioninterleaving.
spring.jta.bitronix.connectionfactory.ignore-recovery-failures=f
alse#Whetherornotrecoveryfailuresshouldbeignored.
spring.jta.bitronix.connectionfactory.max-idle-time=60#Thetim
e,inseconds,afterwhichconnectionsarecleanedupfromthep
ool.
spring.jta.bitronix.connectionfactory.max-pool-size=10#Themax
imumsizeofthepool.0denotesnolimit.
spring.jta.bitronix.connectionfactory.min-pool-size=0#Themini
mumsizeofthepool.
spring.jta.bitronix.connectionfactory.password=#Thepasswordt
ousetoconnecttotheJMSprovider.
spring.jta.bitronix.connectionfactory.share-transaction-connecti
ons=false#WhetherornotconnectionsintheACCESSIBLEstate
canbesharedwithinthecontextofatransaction.
spring.jta.bitronix.connectionfactory.test-connections=true#Wh
etherornotconnectionsshouldbetestedwhenacquiredfromthe
pool.
spring.jta.bitronix.connectionfactory.two-pc-ordering-position=1
#Thepositionthatthisresourceshouldtakeduringtwo-phase
commit(alwaysfirstisInteger.MIN_VALUE,alwayslastisIntege
r.MAX_VALUE).
spring.jta.bitronix.connectionfactory.unique-name=jmsConnectionF
actory#Theuniquenameusedtoidentifytheresourceduringre
covery.
spring.jta.bitronix.connectionfactory.use-tm-join=trueWhethero
rnotTMJOINshouldbeusedwhenstartingXAResources.
spring.jta.bitronix.connectionfactory.user=#Theusertouseto
附录A.常见应用属性
667

connecttotheJMSprovider.
spring.jta.bitronix.datasource.acquire-increment=1#Numberofc
onnectionstocreatewhengrowingthepool.
spring.jta.bitronix.datasource.acquisition-interval=1#Time,in
seconds,towaitbeforetryingtoacquireaconnectionagainaf
teraninvalidconnectionwasacquired.
spring.jta.bitronix.datasource.acquisition-timeout=30#Timeout,
inseconds,foracquiringconnectionsfromthepool.
spring.jta.bitronix.datasource.allow-local-transactions=true#W
hetherornotthetransactionmanagershouldallowmixingXAand
non-XAtransactions.
spring.jta.bitronix.datasource.apply-transaction-timeout=false#
WhetherornotthetransactiontimeoutshouldbesetontheXAR
esourcewhenitisenlisted.
spring.jta.bitronix.datasource.automatic-enlisting-enabled=true
#Whetherornotresourcesshouldbeenlistedanddelistedautom
atically.
spring.jta.bitronix.datasource.cursor-holdability=#Thedefault
cursorholdabilityforconnections.
spring.jta.bitronix.datasource.defer-connection-release=true#W
hetherornotthedatabasecanrunmanytransactionsonthesame
connectionandsupportstransactioninterleaving.
spring.jta.bitronix.datasource.enable-jdbc4-connection-test=#W
hetherornotConnection.isValid()iscalledwhenacquiringaco
nnectionfromthepool.
spring.jta.bitronix.datasource.ignore-recovery-failures=false#
Whetherornotrecoveryfailuresshouldbeignored.
spring.jta.bitronix.datasource.isolation-level=#Thedefaultis
olationlevelforconnections.
spring.jta.bitronix.datasource.local-auto-commit=#Thedefault
auto-commitmodeforlocaltransactions.
spring.jta.bitronix.datasource.login-timeout=#Timeout,inseco
nds,forestablishingadatabaseconnection.
spring.jta.bitronix.datasource.max-idle-time=60#Thetime,ins
econds,afterwhichconnectionsarecleanedupfromthepool.
spring.jta.bitronix.datasource.max-pool-size=10#Themaximumsi
zeofthepool.0denotesnolimit.
spring.jta.bitronix.datasource.min-pool-size=0#Theminimumsiz
eofthepool.
spring.jta.bitronix.datasource.prepared-statement-cache-size=0#
附录A.常见应用属性
668

Thetargetsizeofthepreparedstatementcache.0disablesthe
cache.
spring.jta.bitronix.datasource.share-transaction-connections=fal
se#WhetherornotconnectionsintheACCESSIBLEstatecanbe
sharedwithinthecontextofatransaction.
spring.jta.bitronix.datasource.test-query=#SQLqueryorstatem
entusedtovalidateaconnectionbeforereturningit.
spring.jta.bitronix.datasource.two-pc-ordering-position=1#The
positionthatthisresourceshouldtakeduringtwo-phasecommit
(alwaysfirstisInteger.MIN_VALUE,alwayslastisInteger.MAX_V
ALUE).
spring.jta.bitronix.datasource.unique-name=dataSource#Theuniq
uenameusedtoidentifytheresourceduringrecovery.
spring.jta.bitronix.datasource.use-tm-join=trueWhetherornotT
MJOINshouldbeusedwhenstartingXAResources.
spring.jta.bitronix.properties.allow-multiple-lrc=false#Allow
multipleLRCresourcestobeenlistedintothesametransaction.
spring.jta.bitronix.properties.asynchronous2-pc=false#Enablea
synchronouslyexecutionoftwophasecommit.
spring.jta.bitronix.properties.background-recovery-interval-seco
nds=60#Intervalinsecondsatwhichtoruntherecoveryproces
sinthebackground.
spring.jta.bitronix.properties.current-node-only-recovery=true#
Recoveronlythecurrentnode.
spring.jta.bitronix.properties.debug-zero-resource-transaction=f
alse#Logthecreationandcommitcallstacksoftransactionse
xecutedwithoutasingleenlistedresource.
spring.jta.bitronix.properties.default-transaction-timeout=60#
Defaulttransactiontimeoutinseconds.
spring.jta.bitronix.properties.disable-jmx=false#EnableJMXsu
pport.
spring.jta.bitronix.properties.exception-analyzer=#Settheful
lyqualifiednameoftheexceptionanalyzerimplementationtous
e.
spring.jta.bitronix.properties.filter-log-status=false#Enable
filteringoflogssothatonlymandatorylogsarewritten.
spring.jta.bitronix.properties.force-batching-enabled=true#Se
tifdiskforcesarebatched.
spring.jta.bitronix.properties.forced-write-enabled=true#Seti
flogsareforcedtodisk.
附录A.常见应用属性
669

spring.jta.bitronix.properties.graceful-shutdown-interval=60#M
aximumamountofsecondstheTMwillwaitfortransactionstoge
tdonebeforeabortingthematshutdowntime.
spring.jta.bitronix.properties.jndi-transaction-synchronization-
registry-name=#JNDInameoftheTransactionSynchronizationRegi
stry.
spring.jta.bitronix.properties.jndi-user-transaction-name=#JND
InameoftheUserTransaction.
spring.jta.bitronix.properties.journal=disk#Nameofthejourna
l.Canbe'disk','null'oraclassname.
spring.jta.bitronix.properties.log-part1-filename=btm1.tlog#Na
meofthefirstfragmentofthejournal.
spring.jta.bitronix.properties.log-part2-filename=btm2.tlog#Na
meofthesecondfragmentofthejournal.
spring.jta.bitronix.properties.max-log-size-in-mb=2#Maximumsi
zeinmegabytesofthejournalfragments.
spring.jta.bitronix.properties.resource-configuration-filename=
#ResourceLoaderconfigurationfilename.
spring.jta.bitronix.properties.server-id=#ASCIIIDthatmustu
niquelyidentifythisTMinstance.Defaulttothemachine'sIPa
ddress.
spring.jta.bitronix.properties.skip-corrupted-logs=false#Skip
corruptedtransactionslogentries.
spring.jta.bitronix.properties.warn-about-zero-resource-transact
ion=true#Logawarningfortransactionsexecutedwithoutasin
gleenlistedresource.
#NARAYANA(NarayanaProperties)
spring.jta.narayana.default-timeout=60#Transactiontimeoutin
seconds.
spring.jta.narayana.expiry-scanners=com.arjuna.ats.internal.arju
na.recovery.ExpiredTransactionStatusManagerScanner#Comma-separ
atedlistofexpiryscanners.
spring.jta.narayana.log-dir=#Transactionobjectstoredirector
y.
spring.jta.narayana.one-phase-commit=true#Enableonephasecom
mitoptimisation.
spring.jta.narayana.periodic-recovery-period=120#Intervalinw
hichperiodicrecoveryscansareperformedinseconds.
spring.jta.narayana.recovery-backoff-period=10#Backoffperiod
附录A.常见应用属性
670

betweenfirstandsecondphasesoftherecoveryscaninseconds
.
spring.jta.narayana.recovery-db-pass=#Databasepasswordtobe
usedbyrecoverymanager.
spring.jta.narayana.recovery-db-user=#Databaseusernametobe
usedbyrecoverymanager.
spring.jta.narayana.recovery-jms-pass=#JMSpasswordtobeused
byrecoverymanager.
spring.jta.narayana.recovery-jms-user=#JMSusernametobeused
byrecoverymanager.
spring.jta.narayana.recovery-modules=#Comma-separatedlistof
recoverymodules.
spring.jta.narayana.transaction-manager-id=1#Uniquetransactio
nmanagerid.
spring.jta.narayana.xa-resource-orphan-filters=#Comma-separate
dlistoforphanfilters.
#EMBEDDEDMONGODB(EmbeddedMongoProperties)
spring.mongodb.embedded.features=SYNC_DELAY#Comma-separatedli
stoffeaturestoenable.
spring.mongodb.embedded.storage.databaseDir=#Directoryusedfo
rdatastorage.
spring.mongodb.embedded.storage.oplogSize=#Maximumsizeofthe
oploginmegabytes.
spring.mongodb.embedded.storage.replSetName=#Nameoftherepli
caset.
spring.mongodb.embedded.version=2.6.10#VersionofMongotouse
.
#REDIS(RedisProperties)
spring.redis.cluster.max-redirects=#Maximumnumberofredirect
stofollowwhenexecutingcommandsacrossthecluster.
spring.redis.cluster.nodes=#Comma-separatedlistof"host:port
"pairstobootstrapfrom.
spring.redis.database=0#Databaseindexusedbytheconnection
factory.
spring.redis.host=localhost#Redisserverhost.
spring.redis.password=#Loginpasswordoftheredisserver.
spring.redis.pool.max-active=8#Maxnumberofconnectionsthat
canbeallocatedbythepoolatagiventime.Useanegativeval
附录A.常见应用属性
671

uefornolimit.
spring.redis.pool.max-idle=8#Maxnumberof"idle"connections
inthepool.Useanegativevaluetoindicateanunlimitednumbe
rofidleconnections.
spring.redis.pool.max-wait=-1#Maximumamountoftime(inmilli
seconds)aconnectionallocationshouldblockbeforethrowingan
exceptionwhenthepoolisexhausted.Useanegativevaluetob
lockindefinitely.
spring.redis.pool.min-idle=0#Targetfortheminimumnumberof
idleconnectionstomaintaininthepool.Thissettingonlyhas
aneffectifitispositive.
spring.redis.port=6379#Redisserverport.
spring.redis.sentinel.master=#NameofRedisserver.
spring.redis.sentinel.nodes=#Comma-separatedlistofhost:port
pairs.
spring.redis.timeout=0#Connectiontimeoutinmilliseconds.
#----------------------------------------
#INTEGRATIONPROPERTIES
#----------------------------------------
#ACTIVEMQ(ActiveMQProperties)
spring.activemq.broker-url=#URLoftheActiveMQbroker.Auto-g
eneratedbydefault.Forinstance`tcp://localhost:61616`
spring.activemq.in-memory=true#SpecifyifthedefaultbrokerU
RLshouldbeinmemory.Ignoredifanexplicitbrokerhasbeens
pecified.
spring.activemq.password=#Loginpasswordofthebroker.
spring.activemq.user=#Loginuserofthebroker.
spring.activemq.packages.trust-all=false#Trustallpackages.
spring.activemq.packages.trusted=#Comma-separatedlistofspec
ificpackagestotrust(whennottrustingallpackages).
spring.activemq.pool.configuration.*=#SeePooledConnectionFact
ory.
spring.activemq.pool.enabled=false#WhetheraPooledConnectionF
actoryshouldbecreatedinsteadofaregularConnectionFactory.
spring.activemq.pool.expiry-timeout=0#Connectionexpirationti
meoutinmilliseconds.
spring.activemq.pool.idle-timeout=30000#Connectionidletimeou
附录A.常见应用属性
672

tinmilliseconds.
spring.activemq.pool.max-connections=1#Maximumnumberofpoole
dconnections.
#ARTEMIS(ArtemisProperties)
spring.artemis.embedded.cluster-password=#Clusterpassword.Ra
ndomlygeneratedonstartupbydefault.
spring.artemis.embedded.data-directory=#Journalfiledirectory
.Notnecessaryifpersistenceisturnedoff.
spring.artemis.embedded.enabled=true#Enableembeddedmodeift
heArtemisserverAPIsareavailable.
spring.artemis.embedded.persistent=false#Enablepersistentsto
re.
spring.artemis.embedded.queues=#Comma-separatedlistofqueues
tocreateonstartup.
spring.artemis.embedded.server-id=#Serverid.Bydefault,ana
uto-incrementedcounterisused.
spring.artemis.embedded.topics=#Comma-separatedlistoftopics
tocreateonstartup.
spring.artemis.host=localhost#Artemisbrokerhost.
spring.artemis.mode=#Artemisdeploymentmode,auto-detectedby
default.
spring.artemis.password=#Loginpasswordofthebroker.
spring.artemis.port=61616#Artemisbrokerport.
spring.artemis.user=#Loginuserofthebroker.
#SPRINGBATCH(BatchProperties)
spring.batch.initializer.enabled=#Createtherequiredbatchta
blesonstartupifnecessary.Enabledautomaticallyifnocustom
tableprefixissetorifacustomschemaisconfigured.
spring.batch.job.enabled=true#ExecuteallSpringBatchjobsin
thecontextonstartup.
spring.batch.job.names=#Comma-separatedlistofjobnamestoe
xecuteonstartup(Forinstance`job1,job2`).Bydefault,allJo
bsfoundinthecontextareexecuted.
spring.batch.schema=classpath:org/springframework/batch/core/sch
ema-@@platform@@.sql#PathtotheSQLfiletousetoinitialize
thedatabaseschema.
spring.batch.table-prefix=#Tableprefixforallthebatchmeta
-datatables.
附录A.常见应用属性
673

#HORNETQ(HornetQProperties)
spring.hornetq.embedded.cluster-password=#Clusterpassword.Ra
ndomlygeneratedonstartupbydefault.
spring.hornetq.embedded.data-directory=#Journalfiledirectory
.Notnecessaryifpersistenceisturnedoff.
spring.hornetq.embedded.enabled=true#Enableembeddedmodeift
heHornetQserverAPIsareavailable.
spring.hornetq.embedded.persistent=false#Enablepersistentsto
re.
spring.hornetq.embedded.queues=#Comma-separatedlistofqueues
tocreateonstartup.
spring.hornetq.embedded.server-id=#Serverid.Bydefault,ana
uto-incrementedcounterisused.
spring.hornetq.embedded.topics=#Comma-separatedlistoftopics
tocreateonstartup.
spring.hornetq.host=localhost#HornetQbrokerhost.
spring.hornetq.mode=#HornetQdeploymentmode,auto-detectedby
default.
spring.hornetq.password=#Loginpasswordofthebroker.
spring.hornetq.port=5445#HornetQbrokerport.
spring.hornetq.user=#Loginuserofthebroker.
#JMS(JmsProperties)
spring.jms.jndi-name=#ConnectionfactoryJNDIname.Whenset,
takesprecedencetoothersconnectionfactoryauto-configuration
s.
spring.jms.listener.acknowledge-mode=#Acknowledgemodeofthe
container.Bydefault,thelisteneristransactedwithautomatic
acknowledgment.
spring.jms.listener.auto-startup=true#Startthecontainerauto
maticallyonstartup.
spring.jms.listener.concurrency=#Minimumnumberofconcurrent
consumers.
spring.jms.listener.max-concurrency=#Maximumnumberofconcurr
entconsumers.
spring.jms.pub-sub-domain=false#Specifyifthedefaultdestina
tiontypeistopic.
#RABBIT(RabbitProperties)
附录A.常见应用属性
674

spring.rabbitmq.addresses=#Comma-separatedlistofaddressest
owhichtheclientshouldconnect.
spring.rabbitmq.cache.channel.checkout-timeout=#Numberofmill
isecondstowaittoobtainachannelifthecachesizehasbeen
reached.
spring.rabbitmq.cache.channel.size=#Numberofchannelstoreta
ininthecache.
spring.rabbitmq.cache.connection.mode=CHANNEL#Connectionfacto
rycachemode.
spring.rabbitmq.cache.connection.size=#Numberofconnectionst
ocache.
spring.rabbitmq.connection-timeout=#Connectiontimeout,inmil
liseconds;zeroforinfinite.
spring.rabbitmq.dynamic=true#CreateanAmqpAdminbean.
spring.rabbitmq.host=localhost#RabbitMQhost.
spring.rabbitmq.listener.acknowledge-mode=#Acknowledgemodeof
container.
spring.rabbitmq.listener.auto-startup=true#Startthecontainer
automaticallyonstartup.
spring.rabbitmq.listener.concurrency=#Minimumnumberofconsum
ers.
spring.rabbitmq.listener.default-requeue-rejected=#Whetheror
nottorequeuedeliveryfailures;default`true`.
spring.rabbitmq.listener.max-concurrency=#Maximumnumberofco
nsumers.
spring.rabbitmq.listener.prefetch=#Numberofmessagestobeha
ndledinasinglerequest.Itshouldbegreaterthanorequalto
thetransactionsize(ifused).
spring.rabbitmq.listener.retry.enabled=false#Whetherornotpu
blishingretriesareenabled.
spring.rabbitmq.listener.retry.initial-interval=1000#Interval
betweenthefirstandsecondattempttodeliveramessage.
spring.rabbitmq.listener.retry.max-attempts=3#Maximumnumbero
fattemptstodeliveramessage.
spring.rabbitmq.listener.retry.max-interval=10000#Maximuminte
rvalbetweenattempts.
spring.rabbitmq.listener.retry.multiplier=1.0#Amultiplierto
applytothepreviousdeliveryretryinterval.
spring.rabbitmq.listener.retry.stateless=true#Whetherornotr
etryisstatelessorstateful.
附录A.常见应用属性
675

spring.rabbitmq.listener.transaction-size=#Numberofmessages
tobeprocessedinatransaction.Forbestresultsitshouldbe
lessthanorequaltotheprefetchcount.
spring.rabbitmq.password=#Logintoauthenticateagainstthebr
oker.
spring.rabbitmq.port=5672#RabbitMQport.
spring.rabbitmq.publisher-confirms=false#Enablepublisherconf
irms.
spring.rabbitmq.publisher-returns=false#Enablepublisherretur
ns.
spring.rabbitmq.requested-heartbeat=#Requestedheartbeattimeo
ut,inseconds;zerofornone.
spring.rabbitmq.ssl.enabled=false#EnableSSLsupport.
spring.rabbitmq.ssl.key-store=#Pathtothekeystorethathold
stheSSLcertificate.
spring.rabbitmq.ssl.key-store-password=#Passwordusedtoacces
sthekeystore.
spring.rabbitmq.ssl.trust-store=#TruststorethatholdsSSLce
rtificates.
spring.rabbitmq.ssl.trust-store-password=#Passwordusedtoacc
essthetruststore.
spring.rabbitmq.ssl.algorithm=#SSLalgorithmtouse.Bydefaul
tconfigurebytherabbitclientlibrary.
spring.rabbitmq.template.mandatory=false#Enablemandatorymess
ages.
spring.rabbitmq.template.receive-timeout=0#Timeoutfor`receiv
e()`methods.
spring.rabbitmq.template.reply-timeout=5000#Timeoutfor`sendA
ndReceive()`methods.
spring.rabbitmq.template.retry.enabled=false#Settotruetoen
ableretriesinthe`RabbitTemplate`.
spring.rabbitmq.template.retry.initial-interval=1000#Interval
betweenthefirstandsecondattempttopublishamessage.
spring.rabbitmq.template.retry.max-attempts=3#Maximumnumbero
fattemptstopublishamessage.
spring.rabbitmq.template.retry.max-interval=10000#Maximumnumb
erofattemptstopublishamessage.
spring.rabbitmq.template.retry.multiplier=1.0#Amultiplierto
applytothepreviouspublishingretryinterval.
spring.rabbitmq.username=#Loginusertoauthenticatetothebr
附录A.常见应用属性
676

oker.
spring.rabbitmq.virtual-host=#Virtualhosttousewhenconnect
ingtothebroker.
#----------------------------------------
#ACTUATORPROPERTIES
#----------------------------------------
#ENDPOINTS(AbstractEndpointsubclasses)
endpoints.enabled=true#Enableendpoints.
endpoints.sensitive=#Defaultendpointsensitivesetting.
endpoints.actuator.enabled=true#Enabletheendpoint.
endpoints.actuator.path=#EndpointURLpath.
endpoints.actuator.sensitive=false#Enablesecurityontheendp
oint.
endpoints.autoconfig.enabled=#Enabletheendpoint.
endpoints.autoconfig.id=#Endpointidentifier.
endpoints.autoconfig.path=#Endpointpath.
endpoints.autoconfig.sensitive=#Markiftheendpointexposess
ensitiveinformation.
endpoints.beans.enabled=#Enabletheendpoint.
endpoints.beans.id=#Endpointidentifier.
endpoints.beans.path=#Endpointpath.
endpoints.beans.sensitive=#Markiftheendpointexposessensit
iveinformation.
endpoints.configprops.enabled=#Enabletheendpoint.
endpoints.configprops.id=#Endpointidentifier.
endpoints.configprops.keys-to-sanitize=password,secret,key,token
,.*credentials.*,vcap_services#Keysthatshouldbesanitized.
Keyscanbesimplestringsthatthepropertyendswithorregex
expressions.
endpoints.configprops.path=#Endpointpath.
endpoints.configprops.sensitive=#Markiftheendpointexposes
sensitiveinformation.
endpoints.docs.curies.enabled=false#Enablethecuriegeneratio
n.
endpoints.docs.enabled=true#Enableactuatordocsendpoint.
endpoints.docs.path=/docs#
endpoints.docs.sensitive=false#
附录A.常见应用属性
677

endpoints.dump.enabled=#Enabletheendpoint.
endpoints.dump.id=#Endpointidentifier.
endpoints.dump.path=#Endpointpath.
endpoints.dump.sensitive=#Markiftheendpointexposessensiti
veinformation.
endpoints.env.enabled=#Enabletheendpoint.
endpoints.env.id=#Endpointidentifier.
endpoints.env.keys-to-sanitize=password,secret,key,token,.*crede
ntials.*,vcap_services#Keysthatshouldbesanitized.Keyscan
besimplestringsthatthepropertyendswithorregexexpressi
ons.
endpoints.env.path=#Endpointpath.
endpoints.env.sensitive=#Markiftheendpointexposessensitiv
einformation.
endpoints.flyway.enabled=#Enabletheendpoint.
endpoints.flyway.id=#Endpointidentifier.
endpoints.flyway.sensitive=#Markiftheendpointexposessensi
tiveinformation.
endpoints.health.enabled=#Enabletheendpoint.
endpoints.health.id=#Endpointidentifier.
endpoints.health.mapping.*=#MappingofhealthstatusestoHttp
Statuscodes.Bydefault,registeredhealthstatusesmaptosens
ibledefaults(i.e.UPmapsto200).
endpoints.health.path=#Endpointpath.
endpoints.health.sensitive=#Markiftheendpointexposessensi
tiveinformation.
endpoints.health.time-to-live=1000#Timetoliveforcachedres
ult,inmilliseconds.
endpoints.heapdump.enabled=#Enabletheendpoint.
endpoints.heapdump.path=#Endpointpath.
endpoints.heapdump.sensitive=#Markiftheendpointexposessen
sitiveinformation.
endpoints.info.enabled=#Enabletheendpoint.
endpoints.info.id=#Endpointidentifier.
endpoints.info.path=#Endpointpath.
endpoints.info.sensitive=#Markiftheendpointexposessensiti
veinformation.
endpoints.jolokia.enabled=true#EnableJolokiaendpoint.
endpoints.jolokia.path=/jolokia#EndpointURLpath.
endpoints.jolokia.sensitive=true#Enablesecurityontheendpoi
附录A.常见应用属性
678

nt.
endpoints.liquibase.enabled=#Enabletheendpoint.
endpoints.liquibase.id=#Endpointidentifier.
endpoints.liquibase.sensitive=#Markiftheendpointexposesse
nsitiveinformation.
endpoints.logfile.enabled=true#Enabletheendpoint.
endpoints.logfile.external-file=#ExternalLogfiletobeaccess
ed.
endpoints.logfile.path=/logfile#EndpointURLpath.
endpoints.logfile.sensitive=true#Enablesecurityontheendpoi
nt.
endpoints.mappings.enabled=#Enabletheendpoint.
endpoints.mappings.id=#Endpointidentifier.
endpoints.mappings.path=#Endpointpath.
endpoints.mappings.sensitive=#Markiftheendpointexposessen
sitiveinformation.
endpoints.metrics.enabled=#Enabletheendpoint.
endpoints.metrics.filter.enabled=true#Enablethemetricsservl
etfilter.
endpoints.metrics.filter.gauge-submissions=merged#Httpfilter
gaugesubmissions(merged,per-http-method)
endpoints.metrics.filter.counter-submissions=merged#Httpfilte
rcountersubmissions(merged,per-http-method)
endpoints.metrics.id=#Endpointidentifier.
endpoints.metrics.path=#Endpointpath.
endpoints.metrics.sensitive=#Markiftheendpointexposessens
itiveinformation.
endpoints.shutdown.enabled=#Enabletheendpoint.
endpoints.shutdown.id=#Endpointidentifier.
endpoints.shutdown.path=#Endpointpath.
endpoints.shutdown.sensitive=#Markiftheendpointexposessen
sitiveinformation.
endpoints.trace.enabled=#Enabletheendpoint.
endpoints.trace.id=#Endpointidentifier.
endpoints.trace.path=#Endpointpath.
endpoints.trace.sensitive=#Markiftheendpointexposessensit
iveinformation.
#ENDPOINTSCORSCONFIGURATION(EndpointCorsProperties)
endpoints.cors.allow-credentials=#Setwhethercredentialsare
附录A.常见应用属性
679

supported.Whennotset,credentialsarenotsupported.
endpoints.cors.allowed-headers=#Comma-separatedlistofheader
stoallowinarequest.'*'allowsallheaders.
endpoints.cors.allowed-methods=GET#Comma-separatedlistofmet
hodstoallow.'*'allowsallmethods.
endpoints.cors.allowed-origins=#Comma-separatedlistoforigin
stoallow.'*'allowsallorigins.Whennotset,CORSsupporti
sdisabled.
endpoints.cors.exposed-headers=#Comma-separatedlistofheader
stoincludeinaresponse.
endpoints.cors.max-age=1800#Howlong,inseconds,theresponse
fromapre-flightrequestcanbecachedbyclients.
#JMXENDPOINT(EndpointMBeanExportProperties)
endpoints.jmx.domain=#JMXdomainname.Initializedwiththeva
lueof'spring.jmx.default-domain'ifset.
endpoints.jmx.enabled=true#EnableJMXexportofallendpoints.
endpoints.jmx.static-names=#Additionalstaticpropertiestoap
pendtoallObjectNamesofMBeansrepresentingEndpoints.
endpoints.jmx.unique-names=false#EnsurethatObjectNamesarem
odifiedincaseofconflict.
#JOLOKIA(JolokiaProperties)
jolokia.config.*=#SeeJolokiamanual
#MANAGEMENTHTTPSERVER(ManagementServerProperties)
management.add-application-context-header=true#Addthe"X-Appl
ication-Context"HTTPheaderineachresponse.
management.address=#Networkaddressthatthemanagementendpoi
ntsshouldbindto.
management.context-path=#Managementendpointcontext-path.For
instance`/actuator`
management.port=#ManagementendpointHTTPport.Usesthesame
portastheapplicationbydefault.Configureadifferentportt
ousemanagement-specificSSL.
management.security.enabled=true#Enablesecurity.
management.security.roles=ADMIN#Comma-separatedlistofroles
thatcanaccessthemanagementendpoint.
management.security.sessions=stateless#Sessioncreatingpolicy
touse(always,never,if_required,stateless).
附录A.常见应用属性
680

management.ssl.ciphers=#SupportedSSLciphers.Requiresacust
ommanagement.port.
management.ssl.client-auth=#Whetherclientauthenticationisw
anted("want")orneeded("need").Requiresatruststore.Requi
resacustommanagement.port.
management.ssl.enabled=#EnableSSLsupport.Requiresacustom
management.port.
management.ssl.enabled-protocols=#EnabledSSLprotocols.Requi
resacustommanagement.port.
management.ssl.key-alias=#Aliasthatidentifiesthekeyinthe
keystore.Requiresacustommanagement.port.
management.ssl.key-password=#Passwordusedtoaccessthekeyi
nthekeystore.Requiresacustommanagement.port.
management.ssl.key-store=#Pathtothekeystorethatholdsthe
SSLcertificate(typicallyajksfile).Requiresacustommanag
ement.port.
management.ssl.key-store-password=#Passwordusedtoaccessthe
keystore.Requiresacustommanagement.port.
management.ssl.key-store-provider=#Providerforthekeystore.
Requiresacustommanagement.port.
management.ssl.key-store-type=#Typeofthekeystore.Requires
acustommanagement.port.
management.ssl.protocol=TLS#SSLprotocoltouse.Requiresacu
stommanagement.port.
management.ssl.trust-store=#TruststorethatholdsSSLcertifi
cates.Requiresacustommanagement.port.
management.ssl.trust-store-password=#Passwordusedtoaccesst
hetruststore.Requiresacustommanagement.port.
management.ssl.trust-store-provider=#Providerforthetrustst
ore.Requiresacustommanagement.port.
management.ssl.trust-store-type=#Typeofthetruststore.Requ
iresacustommanagement.port.
#HEALTHINDICATORS(previouslyhealth.*)
management.health.db.enabled=true#Enabledatabasehealthcheck
.
management.health.defaults.enabled=true#Enabledefaulthealth
indicators.
management.health.diskspace.enabled=true#Enablediskspacehea
lthcheck.
附录A.常见应用属性
681

management.health.diskspace.path=#Pathusedtocomputetheava
ilablediskspace.
management.health.diskspace.threshold=0#Minimumdiskspacetha
tshouldbeavailable,inbytes.
management.health.elasticsearch.enabled=true#Enableelasticsea
rchhealthcheck.
management.health.elasticsearch.indices=#Comma-separatedindex
names.
management.health.elasticsearch.response-timeout=100#Thetime,
inmilliseconds,towaitforaresponsefromthecluster.
management.health.jms.enabled=true#EnableJMShealthcheck.
management.health.mail.enabled=true#EnableMailhealthcheck.
management.health.mongo.enabled=true#EnableMongoDBhealthche
ck.
management.health.rabbit.enabled=true#EnableRabbitMQhealthc
heck.
management.health.redis.enabled=true#EnableRedishealthcheck
.
management.health.solr.enabled=true#EnableSolrhealthcheck.
management.health.status.order=DOWN,OUT_OF_SERVICE,UNKNOWN,UP
#Comma-separatedlistofhealthstatusesinorderofseverity.
#INFOCONTRIBUTORS(InfoContributorProperties)
management.info.build.enabled=true#Enablebuildinfo.
management.info.defaults.enabled=true#Enabledefaultinfocont
ributors.
management.info.env.enabled=true#Enableenvironmentinfo.
management.info.git.enabled=true#Enablegitinfo.
management.info.git.mode=simple#Modetousetoexposegitinfo
rmation.
#REMOTESHELL(ShellProperties)
management.shell.auth.type=simple#Authenticationtype.Auto-de
tectedaccordingtotheenvironment.
management.shell.auth.jaas.domain=my-domain#JAASdomain.
management.shell.auth.key.path=#Pathtotheauthenticationkey
.Thisshouldpointtoavalid".pem"file.
management.shell.auth.simple.user.name=user#Loginuser.
management.shell.auth.simple.user.password=#Loginpassword.
management.shell.auth.spring.roles=ADMIN#Comma-separatedlist
附录A.常见应用属性
682

ofrequiredrolestologintotheCRaSHconsole.
management.shell.command-path-patterns=classpath*:/commands/**,c
lasspath*:/crash/commands/**#Patternstousetolookforcomma
nds.
management.shell.command-refresh-interval=-1#Scanforchanges
andupdatethecommandifnecessary(inseconds).
management.shell.config-path-patterns=classpath*:/crash/*#Patt
ernstousetolookforconfigurations.
management.shell.disabled-commands=jpa*,jdbc*,jndi*#Comma-sepa
ratedlistofcommandstodisable.
management.shell.disabled-plugins=#Comma-separatedlistofplu
ginstodisable.Certainpluginsaredisabledbydefaultbasedo
ntheenvironment.
management.shell.ssh.auth-timeout=#Numberofmillisecondsaft
eruserwillbepromptedtologinagain.
management.shell.ssh.enabled=true#EnableCRaSHSSHsupport.
management.shell.ssh.idle-timeout=#Numberofmillisecondsaft
erwhichunusedconnectionsareclosed.
management.shell.ssh.key-path=#PathtotheSSHserverkey.
management.shell.ssh.port=2000#SSHport.
management.shell.telnet.enabled=false#EnableCRaSHtelnetsupp
ort.EnabledbydefaultiftheTelnetPluginisavailable.
management.shell.telnet.port=5000#Telnetport.
#TRACING(TraceProperties)
management.trace.include=request-headers,response-headers,cookie
s,errors#Itemstobeincludedinthetrace.
#METRICSEXPORT(MetricExportProperties)
spring.metrics.export.aggregate.key-pattern=#Patternthattell
stheaggregatorwhattodowiththekeysfromthesourcereposi
tory.
spring.metrics.export.aggregate.prefix=#Prefixforglobalrepo
sitoryifactive.
spring.metrics.export.delay-millis=5000#Delayinmilliseconds
betweenexportticks.Metricsareexportedtoexternalsourceso
naschedulewiththisdelay.
spring.metrics.export.enabled=true#Flagtoenablemetricexpor
t(assumingaMetricWriterisavailable).
spring.metrics.export.excludes=#Listofpatternsformetricna
附录A.常见应用属性
683

mestoexclude.Appliedaftertheincludes.
spring.metrics.export.includes=#Listofpatternsformetricna
mestoinclude.
spring.metrics.export.redis.key=keys.spring.metrics#Keyforre
disrepositoryexport(ifactive).
spring.metrics.export.redis.prefix=spring.metrics#Prefixforr
edisrepositoryifactive.
spring.metrics.export.send-latest=#Flagtoswitchoffanyavai
lableoptimizationsbasedonnotexportingunchangedmetricvalu
es.
spring.metrics.export.statsd.host=#Hostofastatsdserverto
receiveexportedmetrics.
spring.metrics.export.statsd.port=8125#Portofastatsdserver
toreceiveexportedmetrics.
spring.metrics.export.statsd.prefix=#Prefixforstatsdexporte
dmetrics.
spring.metrics.export.triggers.*=#Specifictriggerproperties
perMetricWriterbeanname.
#----------------------------------------
#DEVTOOLSPROPERTIES
#----------------------------------------
#DEVTOOLS(DevToolsProperties)
spring.devtools.livereload.enabled=true#Enablealivereload.co
mcompatibleserver.
spring.devtools.livereload.port=35729#Serverport.
spring.devtools.restart.additional-exclude=#Additionalpattern
sthatshouldbeexcludedfromtriggeringafullrestart.
spring.devtools.restart.additional-paths=#Additionalpathsto
watchforchanges.
spring.devtools.restart.enabled=true#Enableautomaticrestart.
spring.devtools.restart.exclude=META-INF/maven/**,META-INF/resou
rces/**,resources/**,static/**,public/**,templates/**,**/*Test.c
lass,**/*Tests.class,git.properties#Patternsthatshouldbeex
cludedfromtriggeringafullrestart.
spring.devtools.restart.poll-interval=1000#Amountoftime(in
milliseconds)towaitbetweenpollingforclasspathchanges.
spring.devtools.restart.quiet-period=400#Amountofquiettime
附录A.常见应用属性
684

(inmilliseconds)requiredwithoutanyclasspathchangesbefore
arestartistriggered.
spring.devtools.restart.trigger-file=#Nameofaspecificfile
thatwhenchangedwilltriggertherestartcheck.Ifnotspecifi
edanyclasspathfilechangewilltriggertherestart.
#REMOTEDEVTOOLS(RemoteDevToolsProperties)
spring.devtools.remote.context-path=/.~~spring-boot!~#Context
pathusedtohandletheremoteconnection.
spring.devtools.remote.debug.enabled=true#Enableremotedebug
support.
spring.devtools.remote.debug.local-port=8000#Localremotedebu
gserverport.
spring.devtools.remote.proxy.host=#Thehostoftheproxytous
etoconnecttotheremoteapplication.
spring.devtools.remote.proxy.port=#Theportoftheproxytous
etoconnecttotheremoteapplication.
spring.devtools.remote.restart.enabled=true#Enableremoterest
art.
spring.devtools.remote.secret=#Asharedsecretrequiredtoest
ablishaconnection(requiredtoenableremotesupport).
spring.devtools.remote.secret-header-name=X-AUTH-TOKEN#HTTPhe
aderusedtotransferthesharedsecret.
附录A.常见应用属性
685

附录B.配置元数据
SpringBootjars包含元数据文件,它们提供了所有支持的配置属性详情。这些文件
设计用于让IDE开发者能够为使
用application.properties或application.yml文件的用户提供上下文帮助
及代码完成功能。
主要的元数据文件是在编译器通过处理所有被 @ConfigurationProperties注解
的节点来自动生成的。
附录B.配置元数据
686

附录B.1.元数据格式
配置元数据位于jars文件中的 META-INF/spring-configuration-
metadata.json,它们使用一个具有"groups"或"properties"分类节点的简单JSON
格式:
{"groups":[
{
"name":"server",
"type":"org.springframework.boot.autoconfigure.web.Serv
erProperties",
"sourceType":"org.springframework.boot.autoconfigure.we
b.ServerProperties"
},
{
"name":"spring.jpa.hibernate",
"type":"org.springframework.boot.autoconfigure.orm.jpa.
JpaProperties$Hibernate",
"sourceType":"org.springframework.boot.autoconfigure.or
m.jpa.JpaProperties",
"sourceMethod":"getHibernate()"
}
...
],"properties":[
{
"name":"server.port",
"type":"java.lang.Integer",
"sourceType":"org.springframework.boot.autoconfigure.we
b.ServerProperties"
},
{
"name":"server.servlet-path",
"type":"java.lang.String",
"sourceType":"org.springframework.boot.autoconfigure.we
b.ServerProperties",
"defaultValue":"/"
},
{
附录B.1.元数据格式
687

"name":"spring.jpa.hibernate.ddl-auto",
"type":"java.lang.String",
"description":"DDLmode.Thisisactuallyashortcut
forthe\"hibernate.hbm2ddl.auto\"property.",
"sourceType":"org.springframework.boot.autoconfigure.
orm.jpa.JpaProperties$Hibernate"
}
...
],"hints":[
{
"name":"spring.jpa.hibernate.ddl-auto",
"values":[
{
"value":"none",
"description":"DisableDDLhandling."
},
{
"value":"validate",
"description":"Validatetheschema,makenocha
ngestothedatabase."
},
{
"value":"update",
"description":"Updatetheschemaifnecessary."
},
{
"value":"create",
"description":"Createtheschemaanddestroypr
eviousdata."
},
{
"value":"create-drop",
"description":"Createandthendestroythesche
maattheendofthesession."
}
]
}
]}
附录B.1.元数据格式
688

每个"property"是一个配置节点,用户可以使用特定的值指定它。例
如, server.port和server.servlet-path可能
在application.properties中如以下定义:
server.port=9090
server.servlet-path=/home
"groups"是高级别的节点,它们本身不指定一个值,但为properties提供一个有上下
文关联的分组。例如, server.port和server.servlet-path属性
是server组的一部分。
注:不需要每个"property"都有一个"group",一些属性可以以自己的形式存在。
附录B.1.元数据格式
689

附录B.1.1.Group属性
groups数组包含的JSON对象可以由以下属性组成:
名称 类型 目的
name String group的全名,该属性是强制性的
type String
group数据类型的类名。例如,如果group是基于一
个被 @ConfigurationProperties注解的类,该属
性将包含该类的全限定名。如果基于一个 @Bean方
法,它将是该方法的返回类型。如果该类型未知,
则该属性将被忽略
description String
一个简短的group描述,用于展示给用户。如果没有
可用描述,该属性将被忽略。推荐使用一个简短的
段落描述,第一行提供一个简洁的总结,最后一行
以句号结尾
sourceType String
贡献该组的来源类名。例如,如果组基于一个
被@ConfigurationProperties注解的 @Bean方
法,该属性将包含 @Configuration类的全限定
名,该类包含此方法。如果来源类型未知,则该属
性将被忽略
sourceMethod String
贡献该组的方法的全名(包含括号及参数类型)。
例如,被 @ConfigurationProperties注解
的@Bean方法名。如果源方法未知,该属性将被忽
略
附录B.1.元数据格式
690

附录B.1.2.Property属性
properties数组中包含的JSON对象可由以下属性构成:
名称 类型 目的
name String property的全名,格式为小写虚线分割的形式(比
如server.servlet-path)。该属性是强制性的
type String
property数据类型的类名。例
如java.lang.String。该属性可以用来指导用户
他们可以输入值的类型。为了保持一致,原生类型
使用它们的包装类代替,比如 boolean变成
了java.lang.Boolean。注意,这个类可能是个
从一个字符串转换而来的复杂类型。如果类型未知
则该属性会被忽略
description String
一个简短的组的描述,用于展示给用户。如果没有
描述可用则该属性会被忽略。推荐使用一个简短的
段落描述,开头提供一个简洁的总结,最后一行以
句号结束
sourceType String
贡献property的来源类名。例如,如果property来自
一个被 @ConfigurationProperties注解的类,
该属性将包括该类的全限定名。如果来源类型未知
则该属性会被忽略
defaultValue Object
当property没有定义时使用的默认值。如果property
类型是个数组则该属性也可以是个数组。如果默认
值未知则该属性会被忽略
deprecated boolean 指定该property是否过期。如果该字段没有过期或该
信息未知则该属性会被忽略
附录B.1.元数据格式
691

附录B.1.3.可重复的元数据节点
在同一个元数据文件中出现多次相同名称的"property"和"group"对象是可以接受
的。例如,SpringBoot将spring.datasource属性绑定到Hikari,Tomcat和
DBCP类,并且每个都潜在的提供了重复的属性名。这些元数据的消费者需要确保
他们支持这样的场景。
附录B.1.元数据格式
692

附录B.2.使用注解处理器产生自己的元数据
通过使用 spring-boot-configuration-processorjar,你可以从
被@ConfigurationProperties注解的节点轻松的产生自己的配置元数据文件。
该jar包含一个在你的项目编译时会被调用的Java注解处理器。想要使用该处理器,
你只需简单添加 spring-boot-configuration-processor依赖,例如使用
Maven你需要添加:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
使用Gradle时,你可以使用propdeps-plugin并指定:
dependencies{
optional"org.springframework.boot:spring-boot-configura
tion-processor"
}
compileJava.dependsOn(processResources)
}
注:你需要将 compileJava.dependsOn(processResources)添加到构建中,以
确保资源在代码编译之前处理。如果没有该指令,任何 additional-spring-
configuration-metadata.json文件都不会被处理。
该处理器会处理被 @ConfigurationProperties注解的类和方法,description属
性用于产生配置类字段值的Javadoc说明。
注:你应该使用简单的文本来设置 @ConfigurationProperties字段的
Javadoc,因为在没有被添加到JSON之前它们是不被处理的。
属性是通过判断是否存在标准的getters和setters来发现的,对于集合类型有特殊处
理(即使只出现一个getter)。该注解处理器也支持使用lombok的@Data,
@Getter和@Setter注解。
附录B.2.使用注解处理器产生自己的元数据
693

附录B.2.使用注解处理器产生自己的元数据
694

附录B.2.1.内嵌属性
该注解处理器自动将内部类当做内嵌属性处理。例如,下面的类:
@ConfigurationProperties(prefix="server")
publicclassServerProperties{
privateStringname;
privateHosthost;
//...getterandsetters
privatestaticclassHost{
privateStringip;
privateintport;
//...getterandsetters
}
}
附录B.2.使用注解处理器产生自己的元数据
695

附录B.2.2.添加其他的元数据
附录B.2.使用注解处理器产生自己的元数据
696

附录C.自动配置类
这里有一个SpringBoot提供的所有自动配置类的文档链接和源码列表。也要记着看
一下你的应用都开启了哪些自动配置(使用 --debug或-Debug启动应用,或在
一个Actuator应用中使用 autoconfig端点)。
附录C.自动配置类
697

附录C.1来自 spring-boot-autoconfigure模块
下面的自动配置类来自 spring-boot-autoconfigure模块:
配置类 链接
ActiveMQAutoConfiguration javadoc
AopAutoConfiguration javadoc
BatchAutoConfiguration javadoc
CacheAutoConfiguration javadoc
CloudAutoConfiguration javadoc
DataSourceAutoConfiguration javadoc
DataSourceTransactionManagerAutoConfiguration javadoc
DeviceDelegatingViewResolverAutoConfiguration javadoc
DeviceResolverAutoConfiguration javadoc
DispatcherServletAutoConfiguration javadoc
附录C.1.来自spring-boot-autoconfigure模块
698

附录C.2来自 spring-boot-actuator模块
下列的自动配置类来自于 spring-boot-actuator模块:
附录C.2.来自spring-boot-actuator模块
699

附录D.可执行jar格式
spring-boot-loader模块允许SpringBoot对可执行jar和war文件的支持。如果
你正在使用Maven或Gradle插件,可执行jar会被自动产生,通常你不需要了解它是
如何工作的。
如果你需要从一个不同的构建系统创建可执行jars,或你只是对底层技术好奇,本
章节将提供一些背景资料。
附录D.可执行jar格式
700

附录D.1.内嵌JARs
Java没有提供任何标准的方式来加载内嵌的jar文件(也就是jar文件自身包含到一个
jar中)。如果你正分发一个在不解压缩的情况下可以从命令行运行的自包含应用,
那这将是个问题。
为了解决这个问题,很多开发者使用"影子"jars。一个影子jar只是简单的将所有jars
的类打包进一个单独的"超级jar"。使用影子jars的问题是它很难分辨在你的应用中
实际可以使用的库。在多个jars中存在相同的文件名(内容不同)也是一个问题。
SpringBoot另劈稀径,让你能够直接嵌套jars。
附录D.1.内嵌JARs
701

附录D.1.1可执行jar文件结构
SpringBootLoader兼容的jar文件应该遵循以下结构:
example.jar
|
+-META-INF
|+-MANIFEST.MF
+-org
|+-springframework
|+-boot
|+-loader
|+-<springbootloaderclasses>
+-com
|+-mycompany
|+project
|+-YouClasses.class
+-lib
+-dependency1.jar
+-dependency2.jar
依赖需要放到内部的lib目录下。
附录D.1.内嵌JARs
702

附录D.1.2.可执行war文件结构
SpringBootLoader兼容的war文件应该遵循以下结构:
example.jar
|
+-META-INF
|+-MANIFEST.MF
+-org
|+-springframework
|+-boot
|+-loader
|+-<springbootloaderclasses>
+-WEB-INF
+-classes
|+-com
|+-mycompany
|+-project
|+-YouClasses.class
+-lib
|+-dependency1.jar
|+-dependency2.jar
+-lib-provided
+-servlet-api.jar
+-dependency3.jar
依赖需要放到内嵌的 WEB-INF/lib目录下。任何运行时需要但部署到普通web容
器不需要的依赖应该放到 WEB-INF/lib-provided目录下。
附录D.1.内嵌JARs
703

附录D.2.SpringBoot的"JarFile"类
SpringBoot用于支持加载内嵌jars的核心类
是org.springframework.boot.loader.jar.JarFile。它允许你从一个标准的
jar文件或内嵌的子jar数据中加载jar内容。当首次加载的时候,每个JarEntry的位置
被映射到一个偏移于外部jar的物理文件:
myapp.jar
+---------+---------------------+
||/lib/mylib.jar|
|A.class|+---------+---------+|
|||B.class|B.class||
||+---------+---------+|
+---------+---------------------+
^^^
006334523980
上面的示例展示了如何在myapp.jar的0063处找到A.class。来自于内嵌jar的B.class
实际可以在myapp.jar的3452处找到,B.class可以在3980处找到(图有问题?)。
有了这些信息,我们就可以通过简单的寻找外部jar的合适部分来加载指定的内嵌实
体。我们不需要解压存档,也不需要将所有实体读取到内存中。
附录D.2.SpringBoot的"JarFile"类
704

附录D.2.1对标准Java"JarFile"的兼容性
SpringBootLoader努力保持对已有代码和库的兼
容。 org.springframework.boot.loader.jar.JarFile继承
自java.util.jar.JarFile,可以作为降级替换。
附录D.2.SpringBoot的"JarFile"类
705

附录D.3.启动可执行jars
org.springframework.boot.loader.Launcher类是个特殊的启动类,用于一个
可执行jars的主要入口。它实际上就是你jar文件的 Main-Class,并用来设置一个
合适的 URLClassLoader,最后调用你的 main()方法。
这里有3个启动器子类,JarLauncher,WarLauncher和PropertiesLauncher。它们
的作用是从嵌套的jar或war文件目录中(相对于显示的从classpath)加载资源
(.class文件等)。在 [Jar|War]Launcher情况下,嵌套路径是固定的
(lib/*.jar和war的lib-provided/*.jar),所以如果你需要很多其他jars
只需添加到那些位置即可。PropertiesLauncher默认查找你应用存档的 lib/目
录,但你可以通过设置环境变量 LOADER_PATH或application.properties中
的loader.path来添加其他的位置(逗号分割的目录或存档列表)。
附录D.3.启动可执行jars
706

附录D.3.1Launchermanifest
你需要指定一个合适的Launcher作为 META-INF/MANIFEST.MF的Main-Class属
性。你实际想要启动的类(也就是你编写的包含main方法的类)需要在 Start-
Class属性中定义。
例如,这里有个典型的可执行jar文件的MANIFEST.MF:
Main-Class:org.springframework.boot.loader.JarLauncher
Start-Class:com.mycompany.project.MyApplication
对于一个war文件,它可能是这样的:
Main-Class:org.springframework.boot.loader.WarLauncher
Start-Class:com.mycompany.project.MyApplication
注:你不需要在manifest文件中指定 Class-Path实体,classpath会从嵌套的jars
中被推导出来。
附录D.3.启动可执行jars
707

附录D.3.2.暴露的存档
一些PaaS实现可能选择在运行前先解压存档。例如,CloudFoundry就是这样操作
的。你可以运行一个解压的存档,只需简单的启动合适的启动器:
$unzip-qmyapp.jar
$javaorg.springframework.boot.loader.JarLaunche
附录D.3.启动可执行jars
708

附录D.4.PropertiesLauncher特性
PropertiesLauncher有一些特殊的性质,它们可以通过外部属性来启用(系统属
性,环境变量,manifest实体或application.properties)。
Key 作用
loader.path 逗号分割的classpath,比如 lib:${HOME}/app/lib
loader.home 其他属性文件的位置,比如/opt/app(默认
为${user.dir})
loader.args main方法的默认参数(以空格分割)
loader.main 要启动的main类名称,比如 com.app.Application
loader.config.name 属性文件名,比如loader(默认为application)
loader.config.location
属性文件路径,比
如classpath:loader.properties(默认为
application.properties)
loader.system 布尔标识,表明所有的属性都应该添加到系统属性中
(默认为false)
Manifest实体keys通过大写单词首字母及将分隔符从"."改为"-"(比如 Loader-
Path)来进行格式化。 loader.main是个特例,它是通过查找manifest
的Start-Class,这样也兼容JarLauncher。
环境变量可以大写字母并且用下划线代替句号。
loader.home是其他属性文件(覆盖默认)的目录位置,只要没有指
定loader.config.location。
loader.path可以包含目录(递归地扫描jar和zip文件),存档路径或通配符
模式(针对默认的JVM行为)。
占位符在使用前会被系统和环境变量加上属性文件本身的值替换掉。
附录D.4.PropertiesLauncher特性
709

附录D.5.可执行jar的限制
当使用SpringBootLoader打包的应用时有一些你需要考虑的限制。
附录D.5.可执行jar的限制
710

附录D.5.1Zip实体压缩
对于一个嵌套jar的ZipEntry必须使用 ZipEntry.STORED方法保存。这是需要的,
这样我们可以直接查找嵌套jar中的个别内容。嵌套jar的内容本身可以仍旧被压缩,
正如外部jar的其他任何实体。
附录D.5.可执行jar的限制
711

附录D.5.2.系统ClassLoader
启动的应用在加载类时应该使用 Thread.getContextClassLoader()(多数库和
框架都默认这样做)。尝试通过 ClassLoader.getSystemClassLoader()加载嵌
套的类将失败。请注意 java.util.Logging总是使用系统类加载器,由于这个原
因你需要考虑一个不同的日志实现。
附录D.5.可执行jar的限制
712

附录E.依赖版本
下面的表格提供了详尽的依赖版本信息,这些版本由SpringBoot自身的CLI,
Maven的依赖管理(dependencymanagement)和Gradle插件提供。当你声明一
个对以下artifacts的依赖而没有声明版本时,将使用下面表格中列出的版本。
附录E.依赖版本
714








































































