Spring Boot参考指南

目录

I. Spring Boot文件
1.关于文档
2.获得帮助
3.第一步
4.使用Spring Boot
5.了解Spring Boot功能
6.转向生产
7.高级主题
II。入门
8.介绍Spring Boot
9.系统要求
9.1.Servlet容器
10.安装Spring Boot
10.1.Java Developer的安装说明
10.1.1.Maven安装
10.1.2.Gradle安装
10.2.安装Spring Boot CLI
10.2.1.手动安装
10.2.2.使用SDKMAN安装!
10.2.3.OSX Homebrew安装
10.2.4.MacPorts安装
10.2.5.命令行完成
10.2.6.Windows Scoop安装
10.2.7.快速启动Spring CLI示例
10.3.从早期版本的Spring Boot升级
11.开发您的第一个Spring Boot应用程序
11.1.创建POM
11.2.添加Classpath依赖项
11.3.编写代码
11.3.1.@RestController和@RequestMapping Annotations
11.3.2.@EnableAutoConfiguration注释
11.3.3.“主要”方法
11.4.运行示例
11.5.创建一个可执行的Jar
12.接下来要阅读的内容
III。使用Spring Boot
13.构建系统
13.1.依赖管理
13.2.Maven
13.2.1.继承Starter Parent
13.2.2.在没有父POM的情况下使用Spring Boot
13.2.3.使用Spring Boot Maven插件
13.3.Gradle
13.4.Ant
13.5.Starters
14.构建您的代码
14.1.使用“默认”包
14.2.找到主应用程序类
15.配置类
15.1.导入其他配置类
15.2.导入XML配置
16.自动配置
16.1.逐步更换自动配置
16.2.禁用特定的自动配置类
17. Spring Beans和依赖注入
18.使用@SpringBootApplication Annotation
19.运行您的应用程序
19.1.从IDE运行
19.2.作为打包应用程序运行
19.3.使用Maven插件
19.4.使用Gradle插件
19.5.热插拔
20.开发人员工具
20.1.Property默认值
20.2.自动重启
20.2.1.记录条件评估中的更改
20.2.2.不包括资源
20.2.3.观看其他路径
20.2.4.禁用重启
20.2.5.使用触发器文件
20.2.6.自定义重新启动类加载器
20.2.7.已知限制
20.3.LiveReload
20.4.全局设置
20.5.远程应用
20.5.1.运行远程客户端应用程序
20.5.2.远程更新
21.包装您的生产应用程序
22.接下来要阅读的内容
IV。Spring Boot功能
23. SpringApplication
23.1.启动失败
23.2.自定义横幅
23.3.自定义SpringApplication
23.4.Fluent Builder API
23.5.应用程序事件和监听器
23.6.网络环境
23.7.访问应用程序参数
23.8.使用ApplicationRunner或CommandLineRunner
23.9.申请退出
23.10.管理功能
24.外部配置
24.1.配置随机值
24.2.访问命令行属性
24.3.应用程序Property文件
24.4.配置文件特定的属性
24.5.属性中的占位符
24.6.加密属性
24.7.使用YAML而不是属性
24.7.1.加载YAML
24.7.2.在Spring环境中将YAML公开为属性
24.7.3.多个档案的YAML文件
24.7.4.YAML缺点
24.8.类型安全的配置属性
24.8.1.第三方配置
24.8.2.轻松绑定
24.8.3.合并复杂类型
24.8.4.属性转换
转换持续时间
转换数据大小
24.8.5.@ConfigurationProperties验证
24.8.6.@ConfigurationProperties vs. @Value
25.简介
25.1.添加活动配置文件
25.2.以编程方式设置配置文件
25.3.配置文件特定的配置文件
26.记录
26.1.日志格式
26.2.控制台输出
26.2.1.彩色编码输出
26.3.文件输出
26.4.日志级别
26.5.日志组
26.6.自定义日志配置
26.7.Logback Extensions
26.7.1.特定于配置文件的配置
26.7.2.环境属性
27. JSON
27.1.Jackson
27.2.GSON
27.3.JSON-B
28.开发Web应用程序
28.1.“Spring Web MVC框架”
28.1.1.Spring MVC自动配置
28.1.2.HttpMessageConverters
28.1.3.自定义JSON序列化程序和反序列化程序
28.1.4.MessageCodesResolver的信息
28.1.5.静态内容
28.1.6.欢迎页面
28.1.7.自定义Favicon
28.1.8.路径匹配和内容协商
28.1.9.ConfigurableWebBindingInitializer
28.1.10.模板引擎
28.1.11.错误处理
自定义错误页面
将错误页面映射到Spring MVC之外
28.1.12.Spring HATEOAS
28.1.13.CORS支持
28.2.“Spring WebFlux框架”
28.2.1.Spring WebFlux自动配置
28.2.2.带有HttpMessageReaders和HttpMessageWriters的HTTP编解码器
28.2.3.静态内容
28.2.4.模板引擎
28.2.5.错误处理
自定义错误页面
28.2.6.网络过滤器
28.3.JAX-RS和Jersey
28.4.嵌入式Servlet容器支持
28.4.1.Servlet,过滤器和监听器
注册Servlet,过滤器和监听器Spring Beans
28.4.2.Servlet上下文初始化
扫描Servlet,过滤器和侦听器
28.4.3.ServletWebServerApplicationContext
28.4.4.自定义嵌入式Servlet容器
程序化定制
直接自定义ConfigurableServletWebServerFactory
28.4.5.JSP限制
28.5.嵌入式Reactive Server支持
28.6.Reactive Server资源配置
29.安全
29.1.MVC安全
29.2.WebFlux安全
29.3.OAuth2
29.3.1.客户
OAuth2共同提供者的客户注册
29.3.2.资源服务器
29.3.3.授权服务器
29.4.执行器安全
29.4.1.跨站点请求伪造保护
30.使用SQL数据库
30.1.配置DataSource
30.1.1.嵌入式数据库支持
30.1.2.连接到生产数据库
30.1.3.连接到JNDI数据源
30.2.使用JdbcTemplate
30.3.JPA和Spring Data JPA
30.3.1.实体类
30.3.2.Spring数据JPA存储库
30.3.3.创建和删除JPA数据库
30.3.4.在View中打开EntityManager
30.4.Spring数据JDBC
30.5.使用H2的Web控制台
30.5.1.更改H2控制台的路径
30.6.使用jOOQ
30.6.1.代码生成
30.6.2.使用DSLContext
30.6.3.jOOQ SQL方言
30.6.4.自定义jOOQ
31.使用NoSQL Technologies
31.1.Redis
31.1.1.连接到Redis
31.2.MongoDB的
31.2.1.连接到MongoDB数据库
31.2.2.MongoTemplate
31.2.3.Spring数据MongoDB存储库
31.2.4.嵌入式Mongo
31.3.Neo4j的
31.3.1.连接到Neo4j数据库
31.3.2.使用嵌入模式
31.3.3.Neo4jSession
31.3.4.Spring数据Neo4j存储库
31.4.Gemfire
31.5.Solr的
31.5.1.连接到Solr
31.5.2.Spring Data Solr存储库
31.6.Elasticsearch
31.6.1.通过REST客户端连接到Elasticsearch
31.6.2.使用Jest连接到Elasticsearch
31.6.3.使用Spring数据连接到Elasticsearch
31.6.4.Spring Data Elasticsearch存储库
31.7.Cassandra
31.7.1.连接到Cassandra
31.7.2.Spring数据Cassandra存储库
31.8.Couchbase
31.8.1.连接到Couchbase
31.8.2.Spring数据Couchbase存储库
31.9.LDAP
31.9.1.连接到LDAP服务器
31.9.2.Spring数据LDAP存储库
31.9.3.嵌入式内存LDAP服务器
31.10.InfluxDB
31.10.1.连接到InfluxDB
32.缓存
32.1.支持的缓存提供程序
32.1.1.通用
32.1.2.JCache(JSR-107)
32.1.3.EhCache 2.x
32.1.4.Hazelcast
32.1.5.Infinispan
32.1.6.Couchbase
32.1.7.Redis
32.1.8.Caffeine
32.1.9.简单
32.1.10.None
33.消息传递
33.1.JMS
33.1.1.ActiveMQ支持
33.1.2.Artemis支持
33.1.3.使用JNDI ConnectionFactory
33.1.4.发送消息
33.1.5.收到消息
33.2.AMQP
33.2.1.RabbitMQ支持
33.2.2.发送消息
33.2.3.收到消息
33.3.Apache Kafka支持
33.3.1.发送消息
33.3.2.收到消息
33.3.3.卡夫卡流
33.3.4.其他Kafka Properties
34.使用RestTemplate调用REST服务
34.1.RestTemplate自定义
35.使用WebClient调用REST服务
35.1.WebClient运行时
35.2.WebClient自定义
36.验证
37.发送电子邮件
38.使用JTA的分布式事务
38.1.使用Atomikos事务管理器
38.2.使用Bitronix事务管理器
38.3.使用Java EE托管事务管理器
38.4.混合XA和非XA JMS连接
38.5.支持替代嵌入式事务管理器
39. Hazelcast
40. Quartz Scheduler
41.任务执行和调度
42. Spring Integration
43. Spring Session
44.对JMX的监测和管理
45.测试
45.1.测试范围依赖性
45.2.测试Spring应用程序
45.3.测试Spring Boot应用程序
45.3.1.检测Web应用程序类型
45.3.2.检测测试配置
45.3.3.排除测试配置
45.3.4.使用模拟环境进行测试
45.3.5.使用正在运行的服务器进
45.3.6.使用JMX
45.3.7.嘲弄和间谍Beans
45.3.8.自动配置的测试
45.3.9.自动配置的JSON测试
45.3.10.自动配置的Spring MVC测试
45.3.11.自动配置Spring WebFlux测试
45.3.12.自动配置的数据JPA测试
45.3.13.自动配置的JDBC测试
45.3.14.自动配置的数据JDBC测试
45.3.15.自动配置的jOOQ测试
45.3.16.自动配置的数据MongoDB测试
45.3.17.自动配置的数据Neo4j测试
45.3.18.自动配置的数据Redis测试
45.3.19.自动配置的数据LDAP测试
45.3.20.自动配置的REST客户端
45.3.21.自动配置的Spring REST文档测试
使用Mock MVC自动配置Spring REST文档测试
使用REST Assured自动配置Spring REST文档测试
45.3.22.额外的自动配置和切片
45.3.23.用户配置和切片
45.3.24.使用Spock测试Spring Boot应用程序
45.4.测试实用程序
45.4.1.ConfigFileApplicationContextInitializer
45.4.2.TestPropertyValues
45.4.3.OutputCapture
45.4.4.TestRestTemplate
46. WebSockets
47.网络服务
48.使用WebServiceTemplate调用Web服务
49.创建自己的自动配置
49.1.了解自动配置Beans
49.2.找到自动配置候选者
49.3.条件Annotations
49.3.1.课程条件
49.3.2.Bean条件
49.3.3.Property条件
49.3.4.资源条件
49.3.5.网络应用条件
49.3.6.SpEL表达条件
49.4.测试您的自动配置
49.4.1.模拟Web上下文
49.4.2.覆盖Classpath
49.5.创建自己的初学者
49.5.1.命名
49.5.2.autoconfigure模块
49.5.3.入门模块
50. Kotlin的支持
50.1.要求
50.2.空安全
50.3.Kotlin API
50.3.1.runApplication
50.3.2.扩展
50.4.依赖管理
50.5.@ConfigurationProperties
50.6.测试
50.7.资源
50.7.1.进一步阅读
50.7.2.例子
51.接下来要阅读的内容
V. Spring Boot Actuator:生产就绪功能
52.启用生产就绪功能
53.终点
53.1.启用端点
53.2.公开端点
53.3.保护HTTP端点
53.4.配置端点
53.5.用于执行器Web端点的超媒体
53.6.CORS支持
53.7.实现自定义端点
53.7.1.接收输入
输入类型转换
53.7.2.自定义Web端点
Web端点请求谓词
路径
HTTP方法
消费
产生
Web端点响应状态
Web端点范围请求
Web端点安全
53.7.3.Servlet端点
53.7.4.控制器端点
53.8.健康信息
53.8.1.自动配置的HealthIndicators
53.8.2.编写自定义HealthIndicators
53.8.3.反应健康指标
53.8.4.自动配置的ReactiveHealthIndicators
53.9.应用信息
53.9.1.自动配置的InfoContributors
53.9.2.定制应用信息
53.9.3.Git提交信息
53.9.4.建立信息
53.9.5.编写自定义InfoContributors
54.通过HTTP进行监控和管理
54.1.自定义管理端点路径
54.2.自定义管理服务器端口
54.3.配置特定于管理的SSL
54.4.自定义管理服务器地址
54.5.禁用HTTP端点
55.对JMX的监测和管理
55.1.自定义MBean名称
55.2.禁用JMX端点
55.3.通过HTTP使用Jolokia for JMX
55.3.1.定制Jolokia
55.3.2.禁用Jolokia
56.记录器
56.1.配置记录器
57.度量标准
57.1.入门
57.2.支持的监控系统
57.2.1.AppOptics
57.2.2.Atlas
57.2.3.Datadog
57.2.4.Dynatrace
57.2.5.Elastic
57.2.6.Ganglia
57.2.7.Graphite
57.2.8.Humio
57.2.9.Influx
57.2.10.JMX
57.2.11.KairosDB
57.2.12.New Relic
57.2.13.Prometheus
57.2.14.SignalFx
57.2.15.简单
57.2.16.StatsD
57.2.17.Wavefront
57.3.支持的指标
57.3.1.Spring MVC指标
57.3.2.Spring WebFlux指标
57.3.3.Jersey服务器指标
57.3.4.HTTP客户端度量标准
57.3.5.缓存指标
57.3.6.数据源度量标准
57.3.7.Hibernate度量标准
57.3.8.RabbitMQ指标
57.4.注册自定义指标
57.5.自定义个别指标
57.5.1.常用标签
57.5.2.Per-meter属性
57.6.度量标准端点
58.审计
59. HTTP跟踪
59.1.自定义HTTP跟踪
60.过程监测
60.1.扩展配置
60.2.编程
61. Cloud Foundry支持
61.1.禁用Extended Cloud Foundry Actuator支持
61.2.Cloud Foundry自签名证书
61.3.自定义上下文路径
62.接下来要阅读的内容
VI。部署Spring Boot应用程序
63.部署到云端
63.1.Cloud Foundry
63.1.1.绑定到服务
63.2.Heroku的
63.3.OpenShift
63.4.亚马逊网络服务(AWS)
63.4.1.AWS Elastic Beanstalk
使用Tomcat平台
使用Java SE平台
63.4.2.摘要
63.5.Boxfuse和亚马逊网络服务
63.6.谷歌云
64.安装Spring Boot应用程序
64.1.支持的操作系统
64.2.Unix / Linux服务
64.2.1.安装为init.d服务(系统V)
保护init.d服务
64.2.2.安装为systemd服务
64.2.3.自定义启动脚本
写入时自定义启动脚本
它运行时自定义脚本
64.3.Microsoft Windows服务
65.接下来要阅读的内容
七。Spring Boot CLI
66.安装CLI
67.使用CLI
67.1.使用CLI运行应用程序
67.1.1.推断“抓住”依赖关系
67.1.2.推断“抓住”坐标
67.1.3.默认导入语句
67.1.4.自动主要方法
67.1.5.自定义依赖关系管理
67.2.多源文件的应用程序
67.3.打包您的应用程序
67.4.初始化一个新项目
67.5.使用嵌入式Shell
67.6.将扩展添加到CLI
68.使用Groovy Beans DSL开发应用程序
69.使用settings.xml配置CLI
70.接下来要阅读的内容
八。构建工具插件
71. Spring Boot Maven插件
71.1.包括插件
71.2.打包可执行文件夹和War文件
72. Spring Boot Gradle插件
73. Spring Boot AntLib模块
73.1.Spring Boot Ant任务
73.1.1.spring-boot:exejar
73.1.2.例子
73.2.spring-boot:findmainclass
73.2.1.例子
74.支持其他构建系统
74.1.重新包装档案
74.2.嵌套库
74.3.寻找主类
74.4.重新打包实施示例
75.接下来要阅读的内容
IX。'如何'指南
76. Spring Boot申请
76.1.创建自己的失败分析器
76.2.自动配置疑难解答
76.3.在开始之前自定义Environment或ApplicationContext
76.4.构建ApplicationContext层次结构(添加父或根上下文)
76.5.创建非Web应用程序
77.属性和配置
77.1.在构建时自动展开属性
77.1.1.使用Maven自动Property扩展
77.1.2.使用Gradle自动Property扩展
77.2.外化SpringApplication的配置
77.3.更改应用程序的外部属性的位置
77.4.使用“短”命令行参数
77.5.使用YAML作为外部属性
77.6.设置活动Spring Profiles
77.7.根据环境更改配置
77.8.发现外部属性的内置选项
78.嵌入式Web服务器
78.1.使用其他Web服务器
78.2.禁用Web服务器
78.3.更改HTTP端口
78.4.使用随机未分配的HTTP端口
78.5.在运行时发现HTTP端口
78.6.启用HTTP响应压缩
78.7.配置SSL
78.8.配置HTTP / 2
78.8.1.带有Undertow的HTTP / 2
78.8.2.带Jetty的HTTP / 2
78.8.3.与Tomcat的HTTP / 2
78.8.4.带有Reactor Netty的HTTP / 2
78.9.配置Web服务器
78.10.向应用程序添加Servlet,过滤器或监听器
78.10.1.使用Spring Bean添加Servlet,过滤器或监听器
禁用Servlet或过滤器的注册
78.10.2.使用类路径扫描添加Servlet,过滤器和侦听器
78.11.配置访问日志记录
78.12.在前端代理服务器后面运行
78.12.1.自定义Tomcat的代理配置
78.13.使用Tomcat启用多个连接器
78.14.使用Tomcat的LegacyCookieProcessor
78.15.使用Undertow启用多个侦听器
78.16.使用@ServerEndpoint创建WebSocket端点
79. Spring MVC
79.1.编写JSON REST服务
79.2.编写XML REST服务
79.3.自定义Jackson ObjectMapper
79.4.自定义@ResponseBody渲染
79.5.处理多部分文件上载
79.6.关闭Spring MVC DispatcherServlet
79.7.关闭默认MVC配置
79.8.自定义ViewResolvers
80.使用Spring安全性进行测试
81. Jersey
81.1.使用Spring安全性保护Jersey端点
82. HTTP客户端
82.1.配置RestTemplate以使用代理
83.记录
83.1.配置Logging for Logging
83.1.1.配置仅文件输出的回溯
83.2.配置Log4j进行日志记录
83.2.1.使用YAML或JSON配置Log4j 2
84.数据访问
84.1.配置自定义数据源
84.2.配置两个DataSource
84.3.使用Spring数据存储库
84.4.从Spring配置中分离@Entity定义
84.5.配置JPA属性
84.6.配置Hibernate命名策略
84.7.配置Hibernate二级缓存
84.8.在Hibernate组件中使用依赖注入
84.9.使用自定义EntityManagerFactory
84.10.使用两个EntityManagers
84.11.使用传统的persistence.xml文件
84.12.使用Spring Data JPA和Mongo Repositories
84.13.自定义Spring数据的Web支持
84.14.将Spring数据存储库公开为REST端点
84.15.配置JPA使用的组件
84.16.使用两个DataSource配置jOOQ
85.数据库初始化
85.1.使用JPA初始化数据库
85.2.使用Hibernate初始化数据库
85.3.初始化数据库
85.4.初始化Spring批处理数据库
85.5.使用更高级别的数据库迁移工具
85.5.1.在启动时执行Flyway数据库迁移
85.5.2.在启动时执行Liquibase数据库迁移
86.消息传递
86.1.禁用事务处理的JMS会话
87.批量申请
87.1.在启动时执行Spring批处理作业
88.执行器
88.1.更改执行器端点的HTTP端口或地址
88.2.自定义'whitelabel'错误页面
88.3.消除明智的价值观
89.安全
89.1.关闭Spring Boot安全配置
89.2.更改UserDetailsS​​ervice和添加用户帐户
89.3.在代理服务器后运行时启用HTTPS
90.热插拔
90.1.重新加载静态内容
90.2.重新加载模板而不重新启动容器
90.2.1.Thymeleaf模板
90.2.2.FreeMarker模板
90.2.3.Groovy模板
90.3.快速申请重新启动
90.4.重新加载Java类而不重新启动容器
91.建立
91.1.生成构建信息
91.2.生成Git信息
91.3.自定义依赖性版本
91.4.使用Maven创建可执行JAR
91.5.使用Spring Boot应用程序作为依赖项
91.6.可执行jar运行时提取特定库
91.7.使用排除项创建不可执行的JAR
91.8.使用Maven开始远程调试Spring Boot应用程序
91.9.从Ant构建可执行文件,而不使用spring-boot-antlib
92.传统部署
92.1.创建可部署的War文件
92.2.将现有应用程序转换为Spring Boot
92.3.将WAR部署到WebLogic
92.4.使用Jedis代替Lettuce
X.附录
A.常见应用程序属性
B.配置元数据
B.1.元数据格式
B.1.1.组属性
B.1.2.Property属性
B.1.3.提示属性
B.1.4.重复的元数据项
B.2.提供手动提示
B.2.1.价值提示
B.2.2.价值提供者
任何
课程参考
处理为
记录器名称
Spring Bean参考
Spring个人资料名称
B.3.使用注释处理器生成自己的元数据
B.3.1.嵌套属性
B.3.2.添加其他元数据
C.自动配置类
C.1.来自“spring-boot-autoconfigure”模块
C.2.来自“spring-boot-actuator-autoconfigure”模块
D.测试自动配置注释
E.可执行的Jar格式
E.1.嵌套的JAR
E.1.1.可执行Jar文件结构
E.1.2.可执行文件War文件结构
E.2.Spring Boot的“JarFile”课程
E.2.1.与标准Java“JarFile”的兼容性
E.3.启动可执行的Jars
E.3.1.启动器清单
E.3.2.爆炸档案
E.4.PropertiesLauncher功能
E.5.可执行的Jar限制
E.6.替代单罐解决方案
F.依赖版本

第一部分。Spring Boot文件

本节简要概述了Spring Boot参考文档。它用作文档其余部分的映射。

1.关于文档

Spring Boot参考指南可用作

最新的副本可在docs.spring.io/spring-boot/docs/current/reference上找到

本文档的副本可供您自己使用并分发给他人,前提是您不对此类副本收取任何费用,并且每份副本均包含本版权声明,无论是以印刷版还是电子版分发。

2.获得帮助

如果您在使用Spring Boot时遇到问题,我们很乐意为您提供帮助。

[注意]注意

所有Spring Boot都是开源的,包括文档。如果您发现文档存在问题或想要改进它们,请参与其中

3.第一步

如果您开始使用Spring Boot或“Spring”,请从以下主题开始

4.使用Spring Boot

准备开始使用Spring Boot?我们为您提供

5.了解Spring Boot功能

需要有关Spring Boot核心功能的更多详细信息? 以下内容适合您

6.转向生产

当您准备将Spring Boot应用程序推向生产时,我们有 一些您可能喜欢的技巧

7.高级主题

最后,我们为更高级的用户提供了一些主题:

第二部分。入门

如果您开始使用Spring Boot或“Spring”,请首先阅读本节。它回答了基本的“什么?”,“如何?”和“为什么?”的问题。它包括对Spring Boot的介绍以及安装说明。然后,我们将引导您构建您的第一个Spring Boot应用程序,并在我们讨论时讨论一些核心原则。

8.介绍Spring Boot

Spring Boot可以轻松创建可以运行的独立的,基于生产级Spring的应用程序。我们对Spring平台和第三方库进行了自以为是的观点,以便您可以尽量少开始。大多数Spring Boot应用程序需要非常少的Spring配置。

您可以使用Spring Boot创建可以使用java -jar或更多传统战争部署启动的Java应用程序。我们还提供了一个运行“spring脚本”的命令行工具。

我们的主要目标是:

  • 为所有Spring开发提供从根本上更快且可广泛访问的入门体验。
  • 开箱即用,但随着需求开始偏离默认值而迅速摆脱困境。
  • 提供大型项目(例如嵌入式服务器,安全性,度量标准,运行状况检查和外部化配置)通用的一系列非功能性功能。
  • 绝对没有代码生成,也不需要XML配置。

9.系统要求

Spring Boot 2.1.1.RELEASE需要Java 8并且与Java 11兼容(包括在内)。Spring框架5.1.3.RELEASE 或以上也是必需的。

为以下构建工具提供了显式构建支持:

构建工具

Maven

3.3+

Gradle

4.4+

9.1 Servlet容器

Spring Boot支持以下嵌入式servlet容器:

名称Servlet版本

Tomcat 9.0

4.0

Jetty 9.4

3.1

Undertow 2.0

4.0

您还可以将Spring Boot应用程序部署到任何Servlet 3.1+兼容容器。

10.安装Spring Boot

Spring Boot可以与“经典”Java开发工具一起使用,也可以作为命令行工具安装。无论哪种方式,您都需要Java SDK v1.8或更高版本。在开始之前,您应该使用以下命令检查当前的Java安装:

$ java -version

如果您不熟悉Java开发,或者想要试用Spring Boot,则可能需要先尝试Spring Boot CLI(命令行界面)。否则,请继续阅读“经典”安装说明。

10.1 Java Developer的安装说明

您可以像使用任何标准Java库一样使用Spring Boot。为此,请在类路径中包含相应的spring-boot-*.jar文件。Spring Boot不需要任何特殊工具集成,因此您可以使用任何IDE或文本编辑器。此外,Spring Boot应用程序没有什么特别之处,因此您可以像运行任何其他Java程序一样运行和调试Spring引导应用程序。

虽然您可以复制Spring Boot罐,但我们通常建议您使用支持依赖关系管理的构建工具(例如Maven或Gradle)。

10.1.1 Maven安装

Spring Boot与Apache Maven 3.3或更高版本兼容。如果您尚未安装Maven,则可以按照maven.apache.org上的说明进行操作

[提示]提示

在许多操作系统上,Maven可以与软件包管理器一起安装。如果您使用OSX Homebrew,请尝试brew install mavenUbuntu用户可以运行sudo apt-get install maven使用Chocolatey的 Windows用户可以从提升(管理员)提示符运行choco install maven

Spring Boot依赖项使用org.springframework.boot groupId通常,您的Maven POM文件继承自spring-boot-starter-parent项目,并声明对一个或多个“Starters”的依赖关系Spring Boot还提供了一个可选的 Maven插件来创建可执行jar。

以下清单显示了典型的pom.xml文件:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://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>

	<!-- Inherit defaults from Spring Boot -->
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.1.1.RELEASE</version>
	</parent>

	<!-- Add typical dependencies for a web application -->
	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
	</dependencies>

	<!-- Package as an executable jar -->
	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>

</project>
[提示]提示

spring-boot-starter-parent是使用Spring Boot的好方法,但它可能并不适合所有时间。有时您可能需要从其他父POM继承,或者您可能不喜欢我们的默认设置。在这些情况下,请参见 第13.2.2节“使用不带父POM的Spring Boot”作为使用import范围的替代解决方案。

10.1.2 Gradle安装

Spring Boot与Gradle 4.4及更高版本兼容。如果您尚未安装Gradle,则可以按照gradle.org上的说明进行操作

可以使用org.springframework.boot group声明Spring Boot依赖项。通常,您的项目会声明对一个或多个“Starters”的依赖关系 Spring Boot提供了一个有用的Gradle插件,可用于简化依赖声明和创建可执行jar。

有关Spring Boot和Gradle 入门的更多详细信息 ,请参阅Gradle插件参考指南的“ 入门”部分

10.2安装Spring Boot CLI

Spring Boot CLI(命令行界面)是一个命令行工具,可用于使用Spring快速原型。它允许您运行Groovy脚本,这意味着您拥有熟悉的类似Java的语法,而没有太多的样板代码。

您不需要使用CLI来使用Spring Boot,但它绝对是实现Spring应用程序的最快方法。

10.2.1手动安装

您可以从Spring软件存储库下载Spring CLI分发版:

还提供最先进的 快照分发

下载完成后,请按照 解压缩的存档中INSTALL.txt说明进行操作。总之,在.zip文件的bin/目录中有一个spring脚本(Windows为spring.bat)。或者,您可以将java -jar.jar文件一起使用(该脚本可帮助您确保正确设置类路径)。

10.2.2使用SDKMAN安装!

SDKMAN!(软件开发工具包管理器)可用于管理各种二进制SDK的多个版本,包括Groovy和Spring Boot CLI。获取SDKMAN!sdkman.io并使用以下命令安装Spring Boot:

$ sdk install springboot
$ spring --version
Spring Boot v2.1.1.RELEASE

如果您为CLI开发功能并希望轻松访问您构建的版本,请使用以下命令:

$ sdk install springboot dev /path/to/spring-boot/spring-boot-cli/target/spring-boot-cli-2.1.1.RELEASE-bin/spring-2.1.1.RELEASE/
$ sdk default springboot dev
$ spring --version
Spring CLI v2.1.1.RELEASE

前面的说明安装了一个名为dev实例的spring本地实例。它指向您的目标构建位置,因此每次重建Spring Boot时,spring都是最新的。

您可以通过运行以下命令来查看它:

$ sdk ls springboot

================================================================================
Available Springboot Versions
================================================================================
> + dev
* 2.1.1.RELEASE

================================================================================
+ - local version
* - installed
> - currently in use
================================================================================

10.2.3 OSX Homebrew安装

如果您使用的是Mac并使用Homebrew,则可以使用以下命令安装Spring Boot CLI:

$ brew tap pivotal/tap
$ brew install springboot

Homebrew将spring安装到/usr/local/bin

[注意]注意

如果您没有看到公式,那么您的brew安装可能已过时。在这种情况下,运行brew update并再试一次。

10.2.4 MacPorts安装

如果您使用的是Mac并使用MacPorts,则可以使用以下命令安装Spring Boot CLI:

$ sudo port install spring-boot-cli

10.2.5命令行完成

Spring Boot CLI包括为BASHzsh shell 提供命令完成的脚本 您可以在任何shell中source脚本(也称为spring)或将其放入您的个人或系统范围的bash完成初始化中。在Debian系统上,系统范围的脚本位于/shell-completion/bash,并且当新shell启动时,该目录中的所有脚本都将执行。例如,要使用SDKMAN!安装,请手动运行脚本,请使用以下命令:

$ . ~/.sdkman/candidates/springboot/current/shell-completion/bash/spring
$ spring <HIT TAB HERE>
  grab  help  jar  run  test  version
[注意]注意

如果使用Homebrew或MacPorts安装Spring Boot CLI,则命令行完成脚本将自动注册到shell。

10.2.6 Windows Scoop安装

如果您使用的是Windows并使用Scoop,则可以使用以下命令安装Spring Boot CLI:

> scoop bucket add extras
> scoop install springboot

Scoop安装spring~/scoop/apps/springboot/current/bin

[注意]注意

如果您没有看到应用清单,则您的scoop安装可能已过时。在这种情况下,请运行scoop update并重试。

10.2.7快速启动Spring CLI示例

您可以使用以下Web应用程序来测试您的安装。首先,创建一个名为app.groovy的文件,如下所示:

@RestController
class ThisWillActuallyRun {

	@RequestMapping("/")
	String home() {
		"Hello World!"
	}

}

然后从shell运行它,如下所示:

$ spring run app.groovy
[注意]注意

随着依赖项的下载,应用程序的第一次运行速度很慢。后续运行要快得多。

在您喜欢的网络浏览器中打开localhost:8080您应该看到以下输出:

Hello World!

10.3从早期版本的Spring Boot升级

如果要从早期版本的Spring Boot升级,请查看 项目Wiki上的“迁移指南”, 其中提供了详细的升级说明。另请查看 “发行说明”,了解每个版本的“新的和值得注意的”功能列表。

升级到新功能版本时,某些属性可能已重命名或删除。Spring Boot提供了一种在启动时分析应用程序环境和打印诊断的方法,还可以在运行时临时迁移属性。要启用该功能,请将以下依赖项添加到项目中:

<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-properties-migrator</artifactId>
	<scope>runtime</scope>
</dependency>
[警告]警告

添加到环境后期的属性(例如使用@PropertySource时)将不会被考虑在内。

[注意]注意

完成迁移后,请确保从项目的依赖项中删除此模块。

要升级现有CLI安装,请使用相应的软件包管理器命令(例如,brew upgrade),或者,如果手动安装CLI,请按照 标准说明操作,记住更新PATH环境变量以删除任何旧版本引用。

11.开发您的第一个Spring Boot应用程序

本节介绍如何开发一个简单的“Hello World!”Web应用程序,该应用程序突出了Spring Boot的一些主要功能。我们使用Maven来构建这个项目,因为大多数IDE都支持它。

[提示]提示

spring.io网站包含了许多“入门” 指导在使用Spring Boot。如果您需要解决特定问题,请先检查一下。

您可以通过转到start.spring.io并从依赖关系搜索器中选择“Web”启动器来快捷执行以下步骤这样做会生成一个新的项目结构,以便您可以立即开始编码查看Spring Initializr文档以获取更多详细信息。

在开始之前,打开终端并运行以下命令以确保您安装了有效版本的Java和Maven:

$ java -version
java version "1.8.0_102"
Java(TM) SE Runtime Environment (build 1.8.0_102-b14)
Java HotSpot(TM) 64-Bit Server VM (build 25.102-b14, mixed mode)
$ mvn -v
Apache Maven 3.5.4 (1edded0938998edf8bf061f1ceb3cfdeccf443fe; 2018-06-17T14:33:14-04:00)
Maven home: /usr/local/Cellar/maven/3.3.9/libexec
Java version: 1.8.0_102, vendor: Oracle Corporation
[注意]注意

此示例需要在其自己的文件夹中创建。后续说明假定您已创建合适的文件夹,并且它是您当前的目录。

11.1创建POM

我们需要先创建一个Maven pom.xml文件。pom.xml是用于构建项目的配方。打开您喜欢的文本编辑器并添加以下内容:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://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>2.1.1.RELEASE</version>
	</parent>

	<!-- Additional lines to be added here... -->

</project>

上面的清单应该为您提供有效的构建。您可以通过运行mvn package来测试它(现在,您可以忽略“jar将为空 - 没有内容被标记为包含!”警告)。

[注意]注意

此时,您可以将项目导入IDE(大多数现代Java IDE包含对Maven的内置支持)。为简单起见,我们继续为此示例使用纯文本编辑器。

11.2添加类路径依赖项

Spring Boot提供了一些“Starters”,可让您将jar添加到类路径中。我们的示例应用程序已经在POM的parent部分使用了spring-boot-starter-parentspring-boot-starter-parent是一个特殊的启动器,提供有用的Maven默认值。它还提供了一个 dependency-management 部分,以便您可以省略version标签中的“祝福”依赖项。

其他“Starters”提供了在开发特定类型的应用程序时可能需要的依赖项。由于我们正在开发Web应用程序,因此我们添加了spring-boot-starter-web依赖项。在此之前,我们可以通过运行以下命令来查看当前的内容:

$ mvn dependency:tree

[INFO] com.example:myproject:jar:0.0.1-SNAPSHOT

mvn dependency: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>

如果再次运行mvn dependency:tree,您会发现现在有许多其他依赖项,包括Tomcat Web服务器和Spring Boot本身。

11.3编写代码

要完成我们的应用程序,我们需要创建一个Java文件。默认情况下,Maven编译来自src/main/java的源,因此您需要创建该文件夹结构,然后添加名为src/main/java/Example.java的文件以包含以下代码:

import org.springframework.boot.*;
import org.springframework.boot.autoconfigure.*;
import org.springframework.web.bind.annotation.*;

@RestController
@EnableAutoConfiguration
public class Example {

	@RequestMapping("/")
	String home() {
		return "Hello World!";
	}

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

}

虽然这里的代码不多,但还是有很多代码。我们将在接下来的几节中逐步介绍重要部分。

11.3.1 @RestController和@RequestMapping Annotations

Example类的第一个注释是@RestController这被称为 构造型注释。它为阅读代码的人提供了提示,并为Spring提供了该类扮演特定角色的提示。在这种情况下,我们的类是一个web @Controller,所以Spring在处理传入的Web请求时会考虑它。

@RequestMapping注释提供“路由”信息。它告诉Spring任何带有/路径的HTTP请求都应该映射到home方法。@RestController注释告诉Spring将结果字符串直接呈现给调用者。

[提示]提示

@RestController@RequestMapping注释是Spring MVC注释。(它们不是Spring Boot特有的。)有关详细信息,请参阅Spring参考文档中MVC部分

11.3.2 @EnableAutoConfiguration注释

第二个类级别注释是@EnableAutoConfiguration这个注释告诉Spring Boot根据你添加的jar依赖关系“猜测”你想要如何配置Spring。由于spring-boot-starter-web添加了Tomcat和Spring MVC,因此自动配置假定您正在开发Web应用程序并相应地设置Spring。

11.3.3“主要”方法

我们的应用程序的最后一部分是main方法。这只是遵循应用程序入口点的Java约定的标准方法。我们的主要方法是通过调用run来委托Spring Boot的SpringApplication类。SpringApplication引导我们的应用程序,从Spring开始,然后启动自动配置的Tomcat Web服务器。我们需要将Example.class作为参数传递给run方法,以告诉SpringApplication哪个是主要的Spring组件。还会传递args数组以公开任何命令行参数。

11.4运行示例

此时,您的应用程序应该工作。由于您使用了spring-boot-starter-parent POM,因此您可以使用有用的run目标来启动应用程序。从根项目目录中键入mvn spring-boot:run以启动应用程序。您应该看到类似于以下内容的输出:

$ mvn spring-boot:run

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::  (v2.1.1.RELEASE)
....... . . .
....... . . . (log output here)
....... . . .
........ Started Example in 2.222 seconds (JVM running for 6.514)

如果您打开Web浏览器到localhost:8080,您应该看到以下输出:

Hello World!

要正常退出应用程序,请按ctrl-c

11.5创建一个可执行的Jar

我们通过创建一个完全自包含的可执行jar文件来完成我们的示例,我们可以在生产中运行它。可执行jar(有时称为“fat jar”)是包含已编译类以及代码需要运行的所有jar依赖项的归档。

要创建可执行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-parent POM包含<executions>配置以绑定repackage目标。如果您不使用父POM,则需要自己声明此配置。有关详细信息,请参阅插件文档

保存pom.xml并从命令行运行mvn package,如下所示:

$ mvn package

[INFO] Scanning for projects...
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building myproject 0.0.1-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO] .... ..
[INFO] --- maven-jar-plugin:2.4:jar (default-jar) @ myproject ---
[INFO] Building jar: /Users/developer/example/spring-boot-example/target/myproject-0.0.1-SNAPSHOT.jar
[INFO]
[INFO] --- spring-boot-maven-plugin:2.1.1.RELEASE:repackage (default) @ myproject ---
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------

如果你查看target目录,你应该看到myproject-0.0.1-SNAPSHOT.jar该文件大小应为10 MB左右。如果要查看内部,可以使用jar tvf,如下所示:

$ jar tvf target/myproject-0.0.1-SNAPSHOT.jar

您还应该在target目录中看到一个名为myproject-0.0.1-SNAPSHOT.jar.original的小文件。这是Maven在Spring Boot重新打包之前创建的原始jar文件。

要运行该应用程序,请使用java -jar命令,如下所示:

$ java -jar target/myproject-0.0.1-SNAPSHOT.jar

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::  (v2.1.1.RELEASE)
....... . . .
....... . . . (log output here)
....... . . .
........ Started Example in 2.536 seconds (JVM running for 2.864)

和以前一样,要退出应用程序,请按ctrl-c

12.接下来要阅读的内容

希望本节提供了一些Spring Boot基础知识,让您开始编写自己的应用程序。如果您是面向任务的开发人员类型,您可能希望跳转到spring.io并查看一些 入门指南,这些指南解决了特定的“我如何使用Spring?”问题。我们还有Spring Boot特定的“ 操作方法 ”参考文档。

Spring Boot库也有 一堆样品可以运行。样本独立于其余代码(也就是说,您无需构建其余代码来运行或使用示例)。

否则,下一个逻辑步骤是阅读第III部分“使用Spring Boot”如果你真的很不耐烦,你也可以跳过去阅读 Spring Boot功能

第三部分。使用Spring Boot

本节详细介绍了如何使用Spring Boot。它涵盖了构建系统,自动配置以及如何运行应用程序等主题。我们还介绍了一些Spring Boot最佳做法。虽然Spring Boot没有什么特别之处(它只是你可以使用的另一个库),但有一些建议,如果遵循这些建议,可以使您的开发过程更容易一些。

如果您从Spring Boot 开始,在进入本节之前,您应该阅读“ 入门指南”

13.构建系统

强烈建议您选择支持依赖关系管理且可以使用发布到“Maven Central”存储库的工件的构建系统 我们建议您选择Maven或Gradle。可以使Spring Boot与其他构建系统(例如Ant)一起使用,但它们并没有得到特别好的支持。

13.1依赖管理

Spring Boot的每个版本都提供了它支持的依赖项的策划列表。实际上,您不需要为构建配置中的任何这些依赖项提供版本,因为Spring Boot会为您管理。升级Spring引导时,这些依赖项也会以一致的方式升级。

[注意]注意

如果需要,您仍然可以指定版本并覆盖Spring Boot的建议。

精选列表包含您可以使用Spring Boot的所有spring modules以及精选的第三方库列表。该列表以标准 物料清单(spring-boot-dependencies)的形式提供 ,可与MavenGradle一起使用

[警告]警告

Spring Boot的每个版本都与Spring框架的基本版本相关联。我们强烈建议您不要指定其版本。

13.2 Maven

Maven用户可以继承spring-boot-starter-parent项目以获得合理的默认值。父项目提供以下功能:

  • Java 1.8作为默认编译器级别。
  • UTF-8源编码。
  • 一个依赖管理部分,从春天启动依赖性继承POM,管理公共依赖的版本。此依赖关系管理允许您在自己的pom中使用时省略这些依赖项的<version>标记。
  • 使用repackage执行ID 执行repackage目标
  • 明智的 资源过滤
  • 明智的插件配置(exec插件Git提交ID阴影)。
  • application.propertiesapplication.yml的合理资源过滤,包括特定于配置文件的文件(例如,application-dev.propertiesapplication-dev.yml

请注意,由于application.propertiesapplication.yml文件接受Spring样式占位符(${…​}),因此Maven过滤更改为使用@..@占位符。(您可以通过设置名为resource.delimiter的Maven属性来覆盖它。)

13.2.1继承Starter Parent

要将项目配置为从spring-boot-starter-parent继承,请按以下方式设置parent

<!-- Inherit defaults from Spring Boot -->
<parent>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-parent</artifactId>
	<version>2.1.1.RELEASE</version>
</parent>
[注意]注意

您应该只需要在此依赖项上指定Spring Boot版本号。如果导入其他启动器,则可以安全地省略版本号。

通过该设置,您还可以通过覆盖自己项目中的属性来覆盖单个依赖项。例如,要升级到另一个Spring数据发布列表,您可以将以下内容添加到pom.xml

<properties>
	<spring-data-releasetrain.version>Fowler-SR2</spring-data-releasetrain.version>
</properties>
[提示]提示

检查 spring-boot-dependencies pom 以获取支持的属性列表。

13.2.2在没有父POM的情况下使用Spring Boot

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

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

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

如上所述,前面的示例设置不允许您使用属性覆盖单个依赖项。要获得相同的结果,您需要spring-boot-dependencies条目之前项目的dependencyManagement中添加条目。例如,要升级到另一个Spring数据发布列,您可以将以下元素添加到pom.xml

<dependencyManagement>
	<dependencies>
		<!-- Override Spring Data release train provided by Spring Boot -->
		<dependency>
			<groupId>org.springframework.data</groupId>
			<artifactId>spring-data-releasetrain</artifactId>
			<version>Fowler-SR2</version>
			<type>pom</type>
			<scope>import</scope>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-dependencies</artifactId>
			<version>2.1.1.RELEASE</version>
			<type>pom</type>
			<scope>import</scope>
		</dependency>
	</dependencies>
</dependencyManagement>
[注意]注意

在前面的示例中,我们指定了BOM,但是可以以相同的方式覆盖任何依赖关系类型。

13.2.3使用Spring Boot Maven插件

Spring Boot包含一个Maven插件,可以将项目打包为可执行jar。如果要使用插件,请将插件添加到<plugins>部分,如以下示例所示:

<build>
	<plugins>
		<plugin>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-maven-plugin</artifactId>
		</plugin>
	</plugins>
</build>
[注意]注意

如果您使用Spring Boot启动程序父pom,则只需添加插件。除非您要更改父级中定义的设置,否则无需对其进行配置。

13.3 Gradle

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

13.4 Ant

可以使用Apache Ant + Ivy构建一个Spring Boot项目。spring-boot-antlib“AntLib”模块也可用于帮助Ant创建可执行jar。

要声明依赖项,典型的ivy.xml文件类似于以下示例:

<ivy-module version="2.0">
	<info organisation="org.springframework.boot" module="spring-boot-sample-ant" />
	<configurations>
		<conf name="compile" description="everything needed to compile this module" />
		<conf name="runtime" extends="compile" description="everything needed to run this module" />
	</configurations>
	<dependencies>
		<dependency org="org.springframework.boot" name="spring-boot-starter"
			rev="${spring-boot.version}" conf="compile" />
	</dependencies>
</ivy-module>

典型的build.xml类似于以下示例:

<project
	xmlns:ivy="antlib:org.apache.ivy.ant"
	xmlns:spring-boot="antlib:org.springframework.boot.ant"
	name="myapp" default="build">

	<property name="spring-boot.version" value="2.1.1.RELEASE" />

	<target name="resolve" description="--> retrieve dependencies with ivy">
		<ivy:retrieve pattern="lib/[conf]/[artifact]-[type]-[revision].[ext]" />
	</target>

	<target name="classpaths" depends="resolve">
		<path id="compile.classpath">
			<fileset dir="lib/compile" includes="*.jar" />
		</path>
	</target>

	<target name="init" depends="classpaths">
		<mkdir dir="build/classes" />
	</target>

	<target name="compile" depends="init" description="compile">
		<javac srcdir="src/main/java" destdir="build/classes" classpathref="compile.classpath" />
	</target>

	<target name="build" depends="compile">
		<spring-boot:exejar destfile="build/myapp.jar" classes="build/classes">
			<spring-boot:lib>
				<fileset dir="lib/runtime" />
			</spring-boot:lib>
		</spring-boot:exejar>
	</target>
</project>
[提示]提示

如果您不想使用spring-boot-antlib模块,请参见 第91.9节“从Ant构建可执行文件,而不使用spring-boot-antlib “操作方法”。

13.5 Starters

Starters是一组方便的依赖描述符,您可以在应用程序中包含这些描述符。您可以获得所需的所有Spring和相关技术的一站式服务,而无需搜索示例代码和复制粘贴依赖描述符的负载。例如,如果要开始使用Spring和JPA进行数据库访问,请在项目中包含spring-boot-starter-data-jpa依赖项。

启动器包含许多依赖项,这些依赖项是使项目快速启动和运行所需的依赖项,以及一组受支持的托管传递依赖项。

以下应用程序启动程序由org.springframework.boot组下的Spring Boot提供:

表13.1。Spring Boot应用程序启动器

名称描述双响炮

spring-boot-starter

核心启动器,包括自动配置支持,日志记录和YAML

双响炮

spring-boot-starter-activemq

使用Apache ActiveMQ进行JMS消息传递的入门者

双响炮

spring-boot-starter-amqp

使用Spring AMQP和Rabbit MQ的入门者

双响炮

spring-boot-starter-aop

使用Spring AOP和AspectJ进行面向方面编程的入门者

双响炮

spring-boot-starter-artemis

使用Apache Artemis进行JMS消息传递的入门者

双响炮

spring-boot-starter-batch

使用Spring批处理的初学者

双响炮

spring-boot-starter-cache

使用Spring Framework的缓存支持的初学者

双响炮

spring-boot-starter-cloud-connectors

使用Spring云连接器的初学者简化了与Cloud Foundry和Heroku等云平台中的服务的连接

双响炮

spring-boot-starter-data-cassandra

使用Cassandra分布式数据库和Spring数据的初学者Cassandra

双响炮

spring-boot-starter-data-cassandra-reactive

使用Cassandra分布式数据库和Spring数据Cassandra Reactive的入门者

双响炮

spring-boot-starter-data-couchbase

使用Couchbase面向文档的数据库和Spring Data Couchbase的入门者

双响炮

spring-boot-starter-data-couchbase-reactive

使用Couchbase面向文档的数据库和Spring Data Couchbase Reactive的入门者

双响炮

spring-boot-starter-data-elasticsearch

使用Elasticsearch搜索和分析引擎以及Spring Data Elasticsearch的初学者

双响炮

spring-boot-starter-data-jdbc

使用Spring数据JDBC的入门者

双响炮

spring-boot-starter-data-jpa

使用Spring Data JPA和Hibernate的初学者

双响炮

spring-boot-starter-data-ldap

使用Spring数据LDAP的入门者

双响炮

spring-boot-starter-data-mongodb

使用MongoDB面向文档的数据库和Spring Data MongoDB的初学者

双响炮

spring-boot-starter-data-mongodb-reactive

使用MongoDB面向文档的数据库和Spring Data MongoDB Reactive的入门者

双响炮

spring-boot-starter-data-neo4j

使用Neo4j图形数据库和Spring数据Neo4j的入门者

双响炮

spring-boot-starter-data-redis

使用Spring数据Redis和Lettuce客户端使用Redis键值数据存储的入门者

双响炮

spring-boot-starter-data-redis-reactive

使用Redis数据Redis被动和Lettuce客户端的Redis键值数据存储的入门者

双响炮

spring-boot-starter-data-rest

使用Spring Data REST通过REST公开Spring数据存储库的入门者

双响炮

spring-boot-starter-data-solr

使用带有Spring Data Solr的Apache Solr搜索平台的初学者

双响炮

spring-boot-starter-freemarker

使用FreeMarker视图构建MVC Web应用程序的入门者

双响炮

spring-boot-starter-groovy-templates

使用Groovy模板视图构建MVC Web应用程序的入门者

双响炮

spring-boot-starter-hateoas

使用Spring MVC和Spring HATEOAS构建基于超媒体的RESTful Web应用程序的入门者

双响炮

spring-boot-starter-integration

使用Spring Integration的入门者

双响炮

spring-boot-starter-jdbc

将JDBC与HikariCP连接池一起使用的入门者

双响炮

spring-boot-starter-jersey

使用JAX-RS和Jersey构建RESTful Web应用程序的入门者。替代spring-boot-starter-web

双响炮

spring-boot-starter-jooq

使用jOOQ访问SQL数据库的初学者。替代spring-boot-starter-data-jpaspring-boot-starter-jdbc

双响炮

spring-boot-starter-json

阅读和写作json的初学者

双响炮

spring-boot-starter-jta-atomikos

使用Atomikos进行JTA交易的入门者

双响炮

spring-boot-starter-jta-bitronix

使用Bitronix进行JTA事务的入门者

双响炮

spring-boot-starter-mail

使用Java Mail和Spring Framework的电子邮件发送支持的入门者

双响炮

spring-boot-starter-mustache

使用Mustache视图构建Web应用程序的入门者

双响炮

spring-boot-starter-oauth2-client

使用Spring安全性OAuth2 / OpenID Connect客户端功能的入门级产品

双响炮

spring-boot-starter-oauth2-resource-server

使用Spring安全性OAuth2资源服务器功能的入门者

双响炮

spring-boot-starter-quartz

使用Quartz调度程序的入门者

双响炮

spring-boot-starter-security

使用Spring安全性的入门者

双响炮

spring-boot-starter-test

用于测试包含JUnit,Hamcrest和Mockito等库的Spring Boot应用程序的入门者

双响炮

spring-boot-starter-thymeleaf

使用Thymeleaf视图构建MVC Web应用程序的入门者

双响炮

spring-boot-starter-validation

使用Java Bean验证与Hibernate Validator的初学者

双响炮

spring-boot-starter-web

使用Spring MVC构建Web(包括RESTful)应用程序的入门者。使用Tomcat作为默认嵌入式容器

双响炮

spring-boot-starter-web-services

使用Spring Web服务的入门者

双响炮

spring-boot-starter-webflux

使用Spring Framework的Reactive Web支持构建WebFlux应用程序的初学者

双响炮

spring-boot-starter-websocket

使用Spring Framework的WebSocket支持构建WebSocket应用程序的入门者

双响炮


除应用程序启动器外,还可以使用以下启动器添加 生产就绪功能:

表13.2。Spring Boot制作首发

名称描述双响炮

spring-boot-starter-actuator

使用Spring Boot的Actuator的启动器,它提供生产就绪功能,帮助您监控和管理您的应用程序

双响炮


最后,Spring Boot还包括以下可用于排除或交换特定技术方面的启动器:

表13.3。Spring Boot技术先发者

名称描述双响炮

spring-boot-starter-jetty

使用Jetty作为嵌入式servlet容器的入门。替代spring-boot-starter-tomcat

双响炮

spring-boot-starter-log4j2

使用Log4j2进行日志记录的入门。替代spring-boot-starter-logging

双响炮

spring-boot-starter-logging

使用Logback进行日志记录的入门。默认日志启动器

双响炮

spring-boot-starter-reactor-netty

使用Reactor Netty作为嵌入式响应式HTTP服务器的入门者。

双响炮

spring-boot-starter-tomcat

使用Tomcat作为嵌入式servlet容器的入门者。使用的默认servlet容器启动器spring-boot-starter-web

双响炮

spring-boot-starter-undertow

使用Undertow作为嵌入式servlet容器的入门者。替代spring-boot-starter-tomcat

双响炮


[提示]提示

有关其他社区贡献的启动器的列表,请参阅GitHub上spring-boot-starters模块中README文件

14.构建您的代码

Spring Boot不需要任何特定的代码布局。但是,有一些最佳实践可以提供帮助。

14.1使用“默认”包

当一个类不包含package声明时,它被认为是在“默认包”中。通常不鼓励使用“默认包”,应该避免使用。对于使用@ComponentScan@EntityScan@SpringBootApplication注释的Spring Boot应用程序,它可能会导致特定问题,因为每个jar中的每个类都被读取。

[提示]提示

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

14.2找到主应用程序类

我们通常建议您将主应用程序类放在其他类之上的根包中。@SpringBootApplication注释往往放在主类,它隐式地定义某些项目碱“的搜索包”。例如,如果您正在编写JPA应用程序,则使用@SpringBootApplication带注释类的包来搜索@Entity项。使用根包还允许组件扫描仅应用于您的项目。

[提示]提示

如果您不想使用@SpringBootApplication,它导入的@EnableAutoConfiguration@ComponentScan注释会定义该行为,因此您也可以使用它。

以下清单显示了典型的布局:

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

Application.java文件将声明main方法以及基本@SpringBootApplication,如下所示:

package com.example.myapplication;

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

@SpringBootApplication
public class Application {

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

}

15.配置类

Spring Boot支持基于Java的配置。虽然可以将SpringApplication与XML源一起使用,但我们通常建议您的主要来源是单个@Configuration类。通常,定义main方法的类是主要的@Configuration候选者。

[提示]提示

许多Spring配置示例已在Internet上发布,使用XML配置。如果可能,请始终尝试使用等效的基于Java的配置。搜索Enable*注释可能是一个很好的起点。

15.1导入其他配置类

你不需要将所有@Configuration放入一个班级。@Import注释可用于导入其他配置类。或者,您可以使用@ComponentScan自动选取所有Spring组件,包括@Configuration类。

15.2导入XML配置

如果您绝对必须使用基于XML的配置,我们建议您仍然使用@Configuration类。然后,您可以使用@ImportResource注释来加载XML配置文件。

16.自动配置

Spring Boot自动配置尝试根据您添加的jar依赖项自动配置您的Spring应用程序。例如,如果HSQLDB在您的类路径上,并且您尚未手动配置任何数据库连接beans,则Spring Boot会自动配置内存数据库。

您需要通过向@Configuration类之一添加@EnableAutoConfiguration@SpringBootApplication注释来选择加入自动配置。

[提示]提示

您应该只添加一个@SpringBootApplication@EnableAutoConfiguration注释。我们通常建议您仅将一个或另一个添加到主@Configuration类。

16.1逐步更换自动配置

自动配置是非侵入性的。在任何时候,您都可以开始定义自己的配置以替换自动配置的特定部分。例如,如果添加自己的DataSource bean,则默认的嵌入式数据库支持会退回。

如果您需要了解当前正在应用的自动配置以及原因,请使用--debug开关启动您的应用程序。这样做可以为选择的核心记录器启用调试日志,并将条件报告记录到控制台。

16.2禁用特定的自动配置类

如果发现正在应用您不需要的特定自动配置类,则可以使用@EnableAutoConfiguration的exclude属性禁用它们,如以下示例所示:

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

@Configuration
@EnableAutoConfiguration(exclude={DataSourceAutoConfiguration.class})
public class MyConfiguration {
}

如果类不在类路径上,则可以使用注释的excludeName属性并指定完全限定名称。最后,您还可以使用spring.autoconfigure.exclude属性控制要排除的自动配置类列表。

[提示]提示

您可以在注释级别和使用属性定义排除项。

17. Spring Beans和依赖注入

您可以自由使用任何标准Spring框架技术来定义beans及其注入的依赖项。为简单起见,我们经常发现使用@ComponentScan(找到你的beans)和使用@Autowired(做构造函数注入)效果很好。

如果按照上面的建议构建代码(在根包中定位应用程序类),则可以添加@ComponentScan而不带任何参数。您的所有应用程序组件(@Component@Service@Repository@Controller等)都会自动注册为Spring Beans。

以下示例显示了@Service Bean,它使用构造函数注入来获取所需的RiskAssessor bean:

package com.example.service;

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

@Service
public class DatabaseAccountService implements AccountService {

	private final RiskAssessor riskAssessor;

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

	// ...

}

如果bean有一个构造函数,则可以省略@Autowired,如以下示例所示:

@Service
public class DatabaseAccountService implements AccountService {

	private final RiskAssessor riskAssessor;

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

	// ...

}
[提示]提示

请注意使用构造函数注入如何将riskAssessor字段标记为final,表示无法随后更改它。

18.使用@SpringBootApplication Annotation

许多Spring Boot开发人员喜欢他们的应用程序使用自动配置,组件扫描,并能够在他们的“应用程序类”上定义额外的配置。单个@SpringBootApplication注释可用于启用这三个功能,即:

  • @EnableAutoConfiguration:启用Spring Boot的自动配置机制
  • @ComponentScan:对应用程序所在的软件包启用@Component扫描(请参阅最佳实践
  • @Configuration:允许在上下文中注册额外的beans或导入其他配置类

@SpringBootApplication注释等效于使用@Configuration@EnableAutoConfiguration@ComponentScan及其默认属性,如以下示例所示:

package com.example.myapplication;

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

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

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

}
[注意]注意

@SpringBootApplication还提供了别名来自定义@EnableAutoConfiguration@ComponentScan的属性。

[注意]注意

这些功能中的None是强制性的,您可以选择使用它启用的任何功能替换此单个注释。例如,您可能不希望在应用程序中使用组件扫描:

package com.example.myapplication;

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

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

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

}

在此示例中,Application与任何其他Spring Boot应用程序一样,除了@Component - 未自动检测带注释的类,并且显式导入用户定义的beans(请参阅@Import) 。

19.运行您的应用程序

将应用程序打包为jar并使用嵌入式HTTP服务器的最大优势之一是,您可以像运行任何其他服务器一样运行应用程序。调试Spring Boot应用程序也很容易。您不需要任何特殊的IDE插件或扩展。

[注意]注意

本节仅介绍基于罐子的包装。如果您选择将应用程序打包为war文件,则应参阅服务器和IDE文档。

19.1从IDE运行

您可以从IDE运行Spring Boot应用程序作为简单的Java应用程序。但是,您首先需要导入项目。导入步骤因IDE和构建系统而异。大多数IDE可以直接导入Maven项目。例如,Eclipse用户可以从File菜单中选择Import…​Existing Maven Projects

如果无法将项目直接导入IDE,则可以使用构建插件生成IDE元数据。Maven包括EclipseIDEA的插件 Gradle提供各种IDE的插件

[提示]提示

如果您不小心运行了两次Web应用程序,则会看到“端口已在使用中”错误。STS用户可以使用Relaunch按钮而不是Run按钮来确保关闭任何现有实例。

19.2作为打包应用程序运行

如果您使用Spring Boot Maven或Gradle插件创建可执行jar,则可以使用java -jar运行应用程序,如以下示例所示:

$ java -jar target/myapplication-0.0.1-SNAPSHOT.jar

也可以运行启用了远程调试支持的打包应用程序。这样做可以将调试器附加到打包的应用程序,如以下示例所示:

$ java -Xdebug -Xrunjdwp:server=y,transport=dt_socket,address=8000,suspend=n \
       -jar target/myapplication-0.0.1-SNAPSHOT.jar

19.3使用Maven插件

Spring Boot Maven插件包含run目标,可用于快速编译和运行您的应用程序。应用程序以分解形式运行,就像在IDE中一样。以下示例显示了运行Spring Boot应用程序的典型Maven命令:

$ mvn spring-boot:run

您可能还想使用MAVEN_OPTS操作系统环境变量,如以下示例所示:

$ export MAVEN_OPTS=-Xmx1024m

19.4使用Gradle插件

Spring Boot Gradle插件还包含bootRun任务,可用于以爆炸形式运行您的应用程序。每当您应用org.springframework.bootjava插件时,都会添加bootRun任务,如以下示例所示:

$ gradle bootRun

您可能还想使用JAVA_OPTS操作系统环境变量,如以下示例所示:

$ export JAVA_OPTS=-Xmx1024m

19.5热插拔

由于Spring Boot应用程序只是普通的Java应用程序,因此JVM热交换应该是开箱即用的。JVM热交换在某种程度上受限于它可以替换的字节码。要获得更完整的解决方案, 可以使用JRebel

spring-boot-devtools模块还包括对快速应用程序重启的支持。有关详细信息,请参阅本章后面第20章“ 开发人员工具”部分和 热交换“操作方法”

20.开发人员工具

Spring Boot包括一组额外的工具,可以使应用程序开发体验更加愉快。spring-boot-devtools模块可以包含在任何项目中,以提供额外的开发时间功能。要包含devtools支持,请将模块依赖项添加到您的构建中,如以下Maven和Gradle列表所示:

Maven. 

<dependencies>
	<dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-devtools</artifactId>
		<optional>true</optional>
	</dependency>
</dependencies>

Gradle. 

configurations {
	developmentOnly
	runtimeClasspath {
		extendsFrom developmentOnly
	}
}
dependencies {
	developmentOnly("org.springframework.boot:spring-boot-devtools")
}

[注意]注意

运行完全打包的应用程序时会自动禁用开发人员工具。如果您的应用程序是从java -jar启动的,或者它是从特殊的类加载器启动的,则它被视为“生产应用程序”。在Maven中将依赖项标记为可选,或在Gradle中使用custom`developmentOnly`配置(如上所示)是防止devtools传递应用于使用项目的其他模块的最佳实践。

[提示]提示

重新打包的归档默认情况下不包含devtools。如果要使用 某个远程devtools功能,则需要禁用excludeDevtools构建属性以包含它。Maven和Gradle插件均支持该属性。

20.1 Property默认值

Spring Boot支持的几个库使用缓存来提高性能。例如,模板引擎缓存已编译的模板以避免重复解析模板文件。此外,Spring MVC可以在提供静态资源时为响应添加HTTP缓存头。

虽然缓存在生产中非常有用,但在开发过程中可能会适得其反,从而使您无法看到刚刚在应用程序中进行的更改。因此,spring-boot-devtools默认禁用缓存选项。

缓存选项通常由application.properties文件中的设置配置。例如,Thymeleaf提供spring.thymeleaf.cache财产。spring-boot-devtools模块不需要手动设置这些属性,而是自动应用合理的开发时配置。

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

[注意]注意

如果您不希望应用属性默认值,则可以在application.properties中将spring.devtools.add-properties设置为false

[提示]提示

有关devtools应用的属性的完整列表,请参阅 DevToolsPropertyDefaultsPostProcessor

20.2自动重启

只要类路径上的文件发生更改,使用spring-boot-devtools的应用程序就会自动重新启动。在IDE中工作时,这可能是一个有用的功能,因为它为代码更改提供了非常快速的反馈循环。默认情况下,将监视类路径上指向文件夹的任何条目的更改。请注意,某些资源(如静态资产和视图模板)无需重新启动应用程序

[注意]注意

只要启用了分叉,您也可以使用支持的构建插件(Maven和Gradle)启动应用程序,因为DevTools需要一个独立的应用程序类加载器才能正常运行。默认情况下,Gradle和Maven在类路径上检测到DevTools时会这样做。

[提示]提示

与LiveReload一起使用时,自动重启非常有效。 有关详细信息,请参阅LiveReload部分如果使用JRebel,则禁用自动重新启动以支持动态类重新加载。其他devtools功能(例如LiveReload和属性覆盖)仍然可以使用。

[注意]注意

DevTools依赖于应用程序上下文的关闭钩子来在重启期间关闭它。如果禁用了关闭挂钩(SpringApplication.setRegisterShutdownHook(false)),它将无法正常工作。

[注意]注意

在确定类路径上的条目是否应在更改时触发重新启动时,DevTools会自动忽略名为spring-bootspring-boot-devtoolsspring-boot-autoconfigurespring-boot-actuatorspring-boot-starter的项目。

[注意]注意

DevTools需要自定义ApplicationContext使用的ResourceLoader如果您的应用程序已经提供了一个,它将被包装。不支持直接覆盖ApplicationContext上的getResource方法。

20.2.1记录条件评估中的变化

默认情况下,每次应用程序重新启动时,都会记录一个显示条件评估增量的报告。该报告显示在您进行更改(例如添加或删除beans和设置配置属性)时对应用程序的自动配置所做的更改。

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

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

20.2.2不包括资源

某些资源在更改时不一定需要触发重启。例如,可以就地编辑Thymeleaf模板。默认情况下,更改/META-INF/maven/META-INF/resources/resources/static/public/templates中的资源不会触发重新启动,但会触发 实时重新加载如果要自定义这些排除项,可以使用spring.devtools.restart.exclude属性。例如,要仅排除/static/public,您需要设置以下属性:

spring.devtools.restart.exclude=static/**,public/**
[提示]提示

如果要保留这些默认值并添加其他排除项,请改用spring.devtools.restart.additional-exclude属性。

20.2.3查看其他路径

当您对不在类路径中的文件进行更改时,您可能希望重新启动或重新加载应用程序。为此,请使用spring.devtools.restart.additional-paths属性配置其他路径以监视更改。您可以使用前面描述spring.devtools.restart.exclude属性 来控制其他路径下的更改是触发完全重新启动还是 实时重新加载

20.2.4禁用重启

如果您不想使用重新启动功能,可以使用spring.devtools.restart.enabled属性将其禁用。在大多数情况下,您可以在application.properties中设置此属性(这样做仍会初始化重新启动的类加载器,但它不会监视文件更改)。

如果您需要完全禁用重新启动支持(例如,因为它不能与特定库一起使用),则需要在调用SpringApplication.run(…​)之前将spring.devtools.restart.enabled System属性设置为false,如如下例所示:

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

20.2.5使用触发文件

如果使用不断编译已更改文件的IDE,则可能更喜欢仅在特定时间触发重新启动。为此,您可以使用“触发器文件”,这是一个特殊文件,当您想要实际触发重新启动检查时,必须对其进行修改。更改文件只会触发检查,只有在Devtools检测到必须执行某些操作时才会重新启动。触发器文件可以手动更新,也可以使用IDE插件更新。

要使用触发器文件,请将spring.devtools.restart.trigger-file属性设置为触发器文件的路径。

[提示]提示

您可能希望将spring.devtools.restart.trigger-file 设置全局设置,以便所有项目的行为方式相同。

20.2.6自定义重启类加载器

如前面在Restart vs Reload部分中所述,使用两个类加载器实现了重启功能。对于大多数应用程序,此方法运行良好。但是,它有时会导致类加载问题。

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

spring-devtools.properties文件可以包含前缀为restart.excluderestart.include的属性。include元素是应该被拉入“restart”类加载器的项目,exclude元素是应该被下推到“基础”类加载器中的项目。该属性的值是应用于类路径的正则表达式模式,如以下示例所示:

restart.exclude.companycommonlibs=/mycorp-common-[\\w-]+\.jar
restart.include.projectcommon=/mycorp-myproj-[\\w-]+\.jar
[注意]注意

所有属性键必须是唯一的。只要属性以restart.include.restart.exclude.开头,就会被考虑。

[提示]提示

从类路径中加载所有META-INF/spring-devtools.properties您可以将文件打包到项目中,也可以打包在项目使用的库中。

20.2.7已知限制

对于使用标准ObjectInputStream反序列化的对象,重新启动功能不起作用。如果您需要反序列化数据,则可能需要将Spring的ConfigurableObjectInputStreamThread.currentThread().getContextClassLoader()结合使用。

不幸的是,几个第三方库反序列化而没有考虑上下文类加载器。如果您发现此类问题,则需要向原始作者请求修复。

20.3 LiveReload

spring-boot-devtools模块包括一个嵌入式LiveReload服务器,可用于在更改资源时触发浏览器刷新。LiveReload浏览器扩展程序可从livereload.com免费用于Chrome,Firefox和Safari

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

[注意]注意

您一次只能运行一个LiveReload服务器。在启动应用程序之前,请确保没有其他LiveReload服务器正在运行。如果从IDE启动多个应用程序,则只有第一个具有LiveReload支持。

20.4全局设置

您可以通过将名为.spring-boot-devtools.properties的文件添加到$HOME文件夹来配置全局devtools设置(请注意,文件名以“。”开头)。添加到此文件的任何属性适用于计算机上使用devtools的所有 Spring Boot应用程序。例如,要将restart配置为始终使用 触发器文件,您需要添加以下属性:

〜/ .spring引导-devtools.properties。 

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

[注意]注意

.spring-boot-devtools.properties中激活的配置文件不会影响特定于配置文件的配置文件的加载

20.5远程应用程序

Spring Boot开发人员工具不仅限于本地开发。远程运行应用程序时,您还可以使用多个功能。远程支持是选择加入。要启用它,您需要确保重新打包的存档中包含devtools,如下面的清单所示:

<build>
	<plugins>
		<plugin>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-maven-plugin</artifactId>
			<configuration>
				<excludeDevtools>false</excludeDevtools>
			</configuration>
		</plugin>
	</plugins>
</build>

然后,您需要设置spring.devtools.remote.secret属性,如以下示例所示:

spring.devtools.remote.secret=mysecret
[警告]警告

在远程应用程序上启用spring-boot-devtools存在安全风险。您永远不应该在生产部署上启用支持。

远程devtools支持由两部分组成:一个接受连接的服务器端端点和一个在IDE中运行的客户端应用程序。设置spring.devtools.remote.secret属性后,将自动启用服务器组件。必须手动启动客户端组件。

20.5.1运行远程客户端应用程序

远程客户端应用程序旨在从IDE中运行。您需要使用与连接到的远程项目相同的类路径运行org.springframework.boot.devtools.RemoteSpringApplication应用程序的单个必需参数是它连接的远程URL。

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

  • Run菜单中选择Run Configurations…​
  • 创建一个新的Java Application“启动配置”。
  • 浏览my-app项目。
  • 使用org.springframework.boot.devtools.RemoteSpringApplication作为主类。
  • https://myapp.cfapps.io添加到Program arguments(或任何远程URL)。

正在运行的远程客户端可能类似于以下列表:

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

2015-06-10 18:25:06.632  INFO 14938 --- [           main] o.s.b.devtools.RemoteSpringApplication   : Starting RemoteSpringApplication on pwmbp with PID 14938 (/Users/pwebb/projects/spring-boot/code/spring-boot-devtools/target/classes started by pwebb in /Users/pwebb/projects/spring-boot/code/spring-boot-samples/spring-boot-sample-devtools)
2015-06-10 18:25:06.671  INFO 14938 --- [           main] s.c.a.AnnotationConfigApplicationContext : Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@2a17b7b6: startup date [Wed Jun 10 18:25:06 PDT 2015]; root of context hierarchy
2015-06-10 18:25:07.043  WARN 14938 --- [           main] o.s.b.d.r.c.RemoteClientConfiguration    : The connection to http://localhost:8080 is insecure. You should use a URL starting with 'https://'.
2015-06-10 18:25:07.074  INFO 14938 --- [           main] o.s.b.d.a.OptionalLiveReloadServer       : LiveReload server is running on port 35729
2015-06-10 18:25:07.130  INFO 14938 --- [           main] o.s.b.devtools.RemoteSpringApplication   : Started RemoteSpringApplication in 0.74 seconds (JVM running for 1.105)
[注意]注意

因为远程客户端使用与真实应用程序相同的类路径,所以它可以直接读取应用程序属性。这是spring.devtools.remote.secret属性的读取方式并传递给服务器进行身份验证。

[提示]提示

始终建议使用https://作为连接协议,以便加密流量并且不会截获密码。

[提示]提示

如果需要使用代理来访问远程应用程序,请配置spring.devtools.remote.proxy.hostspring.devtools.remote.proxy.port属性。

20.5.2远程更新

远程客户端以与本地重新启动相同的方式监视应用程序类路径以进行更改 任何更新的资源都会被推送到远程应用程序,并且(如果需要)会触发重新启动。如果您迭代使用本地没有的云服务的功能,这将非常有用。通常,远程更新和重新启动比完全重建和部署周期快得多。

[注意]注意

仅在远程客户端运行时监视文件。如果在启动远程客户端之前更改文件,则不会将其推送到远程服务器。

21.包装您的生产应用程序

可执行jar可用于生产部署。由于它们是独立的,因此它们也非常适合基于云的部署。

对于其他“生产就绪”功能,例如运行状况,审计和度量标准REST或JMX端点,请考虑添加spring-boot-actuator有关详细信息请参见 第V部分“Spring Boot Actuator:生产就绪功能”

22.接下来要阅读的内容

您现在应该了解如何使用Spring Boot和一些您应该遵循的最佳实践。您现在可以继续深入了解特定的 Spring Boot功能,或者您可以跳过并阅读Spring Boot 的“ 生产就绪 ”方面。

第四部分。Spring Boot功能

本节深入研究Spring Boot的细节。在这里,您可以了解您可能想要使用和自定义的主要功能。如果您还没有这样做,您可能需要阅读“ 第二部分,“入门 ”和“ 第三部分”,使用Spring Boot“ ”部分,以便您掌握基础知识。

23. SpringApplication

SpringApplication类提供了一种方便的方法来引导从main()方法启动的Spring应用程序。在许多情况下,您可以委托静态SpringApplication.run方法,如以下示例所示:

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

当您的应用程序启动时,您应该看到类似于以下输出的内容:

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::   v2.1.1.RELEASE

2013-07-31 00:08:16.117  INFO 56603 --- [           main] o.s.b.s.app.SampleApplication            : Starting SampleApplication v0.1.0 on mycomputer with PID 56603 (/apps/myapp.jar started by pwebb)
2013-07-31 00:08:16.166  INFO 56603 --- [           main] ationConfigServletWebServerApplicationContext : Refreshing org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext@6e5a8246: startup date [Wed Jul 31 00:08:16 PDT 2013]; root of context hierarchy
2014-03-04 13:09:54.912  INFO 41370 --- [           main] .t.TomcatServletWebServerFactory : Server initialized with port: 8080
2014-03-04 13:09:56.501  INFO 41370 --- [           main] o.s.b.s.app.SampleApplication            : Started SampleApplication in 2.992 seconds (JVM running for 3.658)

默认情况下,会显示INFO日志记录消息,包括一些相关的启动详细信息,例如启动应用程序的用户。如果您需要INFO以外的日志级别,可以进行设置,如第26.4节“日志级别”中所述

23.1启动失败

如果您的应用程序无法启动,则已注册FailureAnalyzers有机会提供专用错误消息和具体操作来解决问题。例如,如果您在端口8080上启动Web应用程序并且该端口已在使用中,您应该会看到类似于以下消息的内容:

***************************
APPLICATION FAILED TO START
***************************

Description:

Embedded servlet container failed to start. Port 8080 was already in use.

Action:

Identify and stop the process that's listening on port 8080 or configure this application to listen on another port.
[注意]注意

Spring Boot提供了许多FailureAnalyzer实现,您可以 添加自己的实现

如果没有故障分析器能够处理异常,您仍然可以显示完整的条件报告,以便更好地了解出现了什么问题。为此,您需要 启用debug属性org.springframework.boot.autoconfigure.logging.ConditionEvaluationReportLoggingListener 启用DEBUG日志记录

例如,如果使用java -jar运行应用程序,则可以启用debug属性,如下所示:

$ java -jar myproject-0.0.1-SNAPSHOT.jar --debug

23.2自定义横幅

通过将banner.txt文件添加到类路径或将spring.banner.location属性设置为此类文件的位置,可以更改启动时打印的横幅。如果文件的编码不是UTF-8,则可以设置spring.banner.charset除了文本文件,您还可以将banner.gifbanner.jpgbanner.png图像文件添加到类路径或设置spring.banner.image.location属性。图像将转换为ASCII艺术表示,并打印在任何文本横幅上方。

banner.txt文件中,您可以使用以下任何占位符:

表23.1。横幅变量

变量描述

${application.version}

应用程序的版本号,如MANIFEST.MF中声明的那样。例如,Implementation-Version: 1.0打印为1.0

${application.formatted-version}

应用程序的版本号,在MANIFEST.MF中声明并格式化以显示(用括号括起来并以v为前缀)。例如(v1.0)

${spring-boot.version}

您正在使用的Spring Boot版本。例如2.1.1.RELEASE

${spring-boot.formatted-version}

您正在使用的Spring Boot版本,格式化显示(用括号括起来并以v为前缀)。例如(v2.1.1.RELEASE)

${Ansi.NAME}(或${AnsiColor.NAME}${AnsiBackground.NAME}${AnsiStyle.NAME}

其中NAME是ANSI转义码的名称。详情 AnsiPropertySource请见。

${application.title}

申请的标题,如MANIFEST.MF中所述。例如Implementation-Title: MyApp打印为MyApp


[提示]提示

如果要以编程方式生成横幅,可以使用SpringApplication.setBanner(…​)方法。使用org.springframework.boot.Banner接口并实现您自己的printBanner()方法。

您还可以使用spring.main.banner-mode属性来确定是否必须在System.outconsole)上打印横幅,发送到配置的记录器(log),或者根本不产生横幅(off)。

打印的横幅以下列名称注册为单身bean:springBootBanner

[注意]注意

YAML将off映射到false,因此如果要在应用程序中禁用横幅,请务必添加引号,如以下示例所示:

spring:
	main:
		banner-mode: "off"

23.3自定义SpringApplication

如果SpringApplication默认值不符合您的口味,您可以改为创建本地实例并对其进行自定义。例如,要关闭横幅,您可以写:

public static void main(String[] args) {
	SpringApplication app = new SpringApplication(MySpringConfiguration.class);
	app.setBannerMode(Banner.Mode.OFF);
	app.run(args);
}
[注意]注意

传递给SpringApplication的构造函数参数是Spring beans的配置源。在大多数情况下,这些是对@Configuration类的引用,但它们也可以是对XML配置或应扫描的包的引用。

也可以使用application.properties文件配置SpringApplication有关详细信息请参见第24章,外部化配置

有关配置选项的完整列表,请参阅 SpringApplication Javadoc

23.4 Fluent Builder API

如果您需要构建ApplicationContext层次结构(具有父/子关系的多个上下文)或者您更喜欢使用“流畅”构建器API,则可以使用SpringApplicationBuilder

SpringApplicationBuilder允许您将多个方法调用链接在一起,并包含允许您创建层次结构的parentchild方法,如以下示例所示:

new SpringApplicationBuilder()
		.sources(Parent.class)
		.child(Application.class)
		.bannerMode(Banner.Mode.OFF)
		.run(args);
[注意]注意

创建ApplicationContext层次结构时存在一些限制。例如,Web组件必须包含在子上下文中,并且父/子上下文使用相同的Environment有关详细信息,请参阅 SpringApplicationBuilder Javadoc

23.5应用程序事件和监听器

除了通常的Spring框架事件之外,例如 ContextRefreshedEventSpringApplication还会发送一些其他应用程序事件。

[注意]注意

某些事件实际上是在创建ApplicationContext之前触发的,因此您无法在@Bean上注册侦听器。您可以使用SpringApplication.addListeners(…​)方法或SpringApplicationBuilder.listeners(…​)方法注册它们。

如果您希望自动注册这些侦听器,无论应用程序的创建方式如何,您都可以将META-INF/spring.factories文件添加到项目中并使用org.springframework.context.ApplicationListener键引用您的侦听器,如下所示:以下示例:

org.springframework.context.ApplicationListener=com.example.project.MyListener

应用程序运行时,应按以下顺序发送应用程序事件:

  1. 除了注册侦听器和初始化程序之外,在运行开始时但在任何处理之前发送ApplicationStartingEvent
  2. 当在上下文中使用的Environment已知但在创建上下文之前,将发送ApplicationEnvironmentPreparedEvent
  3. 在刷新开始之前但在加载bean定义之后发送ApplicationPreparedEvent
  4. 在刷新上下文之后但在调用任何应用程序和命令行运行程序之前发送ApplicationStartedEvent
  5. 在调用任何应用程序和命令行运行程序后发送ApplicationReadyEvent它表示应用程序已准备好为请求提供服务。
  6. 如果启动时发生异常,则会发送ApplicationFailedEvent
[提示]提示

您经常不需要使用应用程序事件,但知道它们存在可能很方便。在内部,Spring Boot使用事件来处理各种任务。

应用程序事件使用Spring Framework的事件发布机制发送。此机制的一部分确保在子上下文中发布给侦听器的事件也会在任何祖先上下文中发布给侦听器。因此,如果您的应用程序使用SpringApplication实例的层次结构,则侦听器可能会收到相同类型的应用程序事件的多个实例。

为了允许侦听器区分其上下文的事件和后代上下文的事件,它应该请求注入其应用程序上下文,然后将注入的上下文与事件的上下文进行比较。可以通过实现ApplicationContextAware或者如果监听器是bean,使用@Autowired来注入上下文。

23.6网络环境

SpringApplication试图代表您创建正确类型的ApplicationContext用于确定WebApplicationType的算法非常简单:

  • 如果存在Spring MVC,则使用AnnotationConfigServletWebServerApplicationContext
  • 如果Spring MVC不存在且存在Spring WebFlux,则使用AnnotationConfigReactiveWebServerApplicationContext
  • 否则,使用AnnotationConfigApplicationContext

这意味着如果您在同一个应用程序中使用Spring MVC和来自Spring WebFlux的新WebClient,默认情况下将使用Spring MVC。您可以通过调用setWebApplicationType(WebApplicationType)轻松覆盖它。

也可以通过调用setApplicationContextClass(…​)来完全控制使用的ApplicationContext类型。

[提示]提示

在JUnit测试中使用SpringApplication时,通常需要调用setWebApplicationType(WebApplicationType.NONE)

23.7访问应用程序参数

如果您需要访问传递给SpringApplication.run(…​)的应用程序参数,则可以注入org.springframework.boot.ApplicationArguments bean。ApplicationArguments接口提供对原始String[]参数以及解析的optionnon-option参数的访问,如以下示例所示:

import org.springframework.boot.*;
import org.springframework.beans.factory.annotation.*;
import org.springframework.stereotype.*;

@Component
public class MyBean {

	@Autowired
	public MyBean(ApplicationArguments args) {
		boolean debug = args.containsOption("debug");
		List<String> files = args.getNonOptionArgs();
		// if run with "--debug logfile.txt" debug=true, files=["logfile.txt"]
	}

}
[提示]提示

Spring Boot还注册CommandLinePropertySource和Spring Environment这使您还可以使用@Value注释注入单个应用程序参数。

23.8使用ApplicationRunner或CommandLineRunner

如果您需要在SpringApplication启动后运行某些特定代码,则可以实现ApplicationRunnerCommandLineRunner接口。两个接口以相同的方式工作,并提供单个run方法,该方法在SpringApplication.run(…​)完成之前调用。

CommandLineRunner接口提供对应用程序参数的访问,作为简单的字符串数组,而ApplicationRunner使用前面讨论的ApplicationArguments接口。以下示例显示CommandLineRunnerrun方法:

import org.springframework.boot.*;
import org.springframework.stereotype.*;

@Component
public class MyBean implements CommandLineRunner {

	public void run(String... args) {
		// Do something...
	}

}

如果定义了必须按特定顺序调用的多个CommandLineRunnerApplicationRunner beans,则可以另外实现org.springframework.core.Ordered接口或使用org.springframework.core.annotation.Order注释。

23.9申请退出

每个SpringApplication都会向JVM注册一个关闭钩子,以确保ApplicationContext在退出时正常关闭。可以使用所有标准Spring生命周期回调(例如DisposableBean接口或@PreDestroy注释)。

此外,beans如果希望在调用SpringApplication.exit()时返回特定的退出代码,则可以实现org.springframework.boot.ExitCodeGenerator接口。然后可以将此退出代码传递给System.exit()以将其作为状态代码返回,如以下示例所示:

@SpringBootApplication
public class ExitCodeApplication {

	@Bean
	public ExitCodeGenerator exitCodeGenerator() {
		return () -> 42;
	}

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

}

此外,ExitCodeGenerator接口可以通过例外来实现。遇到这样的异常时,Spring Boot返回实现的getExitCode()方法提供的退出代码。

23.10管理员功能

通过指定spring.application.admin.enabled属性,可以为应用程序启用与管理相关的功能。这暴露了 SpringApplicationAdminMXBean 平台MBeanServer您可以使用此功能远程管理您的Spring Boot应用程序。此功能对于任何服务包装器实现也很有用。

[提示]提示

如果您想知道应用程序正在运行的HTTP端口,请使用local.server.port的密钥获取该属性。

[警告]警告

启用此功能时要小心,因为MBean公开了一种关闭应用程序的方法。

24.外部配置

Spring Boot允许您外部化您的配置,以便您可以在不同的环境中使用相同的应用程序代码。您可以使用属性文件,YAML文件,环境变量和命令行参数来外部化配置。Property值可以通过使用@Value注释直接注入beans,通过Spring的Environment抽象访问,或 通过@ConfigurationProperties 绑定到结构化对象

Spring Boot使用非常特殊的PropertySource顺序,旨在允许合理地覆盖值。按以下顺序考虑属性:

  1. Devtools 主目录上的全局设置属性(当devtools处于活动状态时~/.spring-boot-devtools.properties)。
  2. @TestPropertySource 测试上的注释。
  3. properties属于您的测试。用于测试特定应用程序片段@SpringBootTest测试注释
  4. 命令行参数。
  5. 来自SPRING_APPLICATION_JSON的属性(嵌入在环境变量或系统属性中的内联JSON)。
  6. ServletConfig init参数。
  7. ServletContext init参数。
  8. JNDI来自java:comp/env
  9. Java系统属性(System.getProperties())。
  10. OS环境变量。
  11. RandomValuePropertySource仅在random.*中具有属性。
  12. 特定于配置文件的应用程序属性在打包的jar之外(application-{profile}.properties和YAML变体)。
  13. 打包在jar中的特定于配置文件的应用程序属性application-{profile}.properties和YAML变体)。
  14. 打包jar之外的应用程序属性(application.properties和YAML变体)。
  15. 打包在jar中的应用程序属性(application.properties和YAML变体)。
  16. @PropertySource @Configuration课程上的注释。
  17. 默认属性(通过设置SpringApplication.setDefaultProperties指定)。

为了提供一个具体示例,假设您开发了一个使用name属性的@Component,如以下示例所示:

import org.springframework.stereotype.*;
import org.springframework.beans.factory.annotation.*;

@Component
public class MyBean {

    @Value("${name}")
    private String name;

    // ...

}

在应用程序类路径上(例如,在jar中),您可以拥有一个application.properties文件,为name提供合理的默认属性值。在新环境中运行时,可以在jar之外提供覆盖nameapplication.properties文件。对于一次性测试,您可以使用特定的命令行开关启动(例如,java -jar app.jar --name="Spring")。

[提示]提示

可以在命令行上使用环境变量提供SPRING_APPLICATION_JSON属性。例如,您可以在UN * X shell中使用以下行:

$ SPRING_APPLICATION_JSON='{"acme":{"name":"test"}}' java -jar myapp.jar

在前面的示例中,您最终在Spring Environment中使用acme.name=test您还可以在System属性中将JSON提供为spring.application.json,如以下示例所示:

$ java -Dspring.application.json='{"name":"test"}' -jar myapp.jar

您还可以使用命令行参数提供JSON,如以下示例所示:

$ java -jar myapp.jar --spring.application.json='{"name":"test"}'

您还可以将JSON作为JNDI变量提供,如下所示:java:comp/env/spring.application.json

24.1配置随机值

RandomValuePropertySource对于注入随机值(例如,进入秘密或测试用例)非常有用。它可以生成整数,长整数,uuids或字符串,如以下示例所示:

my.secret=${random.value}
my.number=${random.int}
my.bignumber=${random.long}
my.uuid=${random.uuid}
my.number.less.than.ten=${random.int(10)}
my.number.in.range=${random.int[1024,65536]}

random.int*语法为OPEN value (,max) CLOSE,其中OPEN,CLOSE为任意字符,value,max为整数。如果提供max,那么value是最小值,max是最大值(不包括)。

24.2访问命令行属性

默认情况下,SpringApplication将任何命令行选项参数(即以--开头的参数,例如--server.port=9000)转换为property,并将它们添加到Spring Environment如前所述,命令行属性始终优先于其他属性源。

如果您不希望将命令行属性添加到Environment,则可以使用SpringApplication.setAddCommandLineProperties(false)禁用它们。

24.3应用程序Property文件

SpringApplication从以下位置的application.properties文件加载属性,并将它们添加到Spring Environment

  1. 当前目录的/config子目录
  2. 当前目录
  3. classpath /config
  4. 类路径根

列表按优先级排序(在列表中较高位置定义的属性将覆盖在较低位置中定义的属性)。

[注意]注意

您还可以使用YAML('。mil')文件替代'.properties'。

如果您不喜欢application.properties作为配置文件名,则可以通过指定spring.config.name环境属性来切换到另一个文件名。您还可以使用spring.config.location环境属性(以逗号分隔的目录位置或文件路径列表)来引用显式位置。以下示例显示如何指定其他文件名:

$ java -jar myproject.jar --spring.config.name=myproject

以下示例显示如何指定两个位置:

$ java -jar myproject.jar --spring.config.location=classpath:/default.properties,classpath:/override.properties
[警告]警告

很早就使用spring.config.namespring.config.location来确定必须加载哪些文件,因此必须将它们定义为环境属性(通常是OS环境变量,系统属性或命令行参数)。

如果spring.config.location包含目录(而不是文件),则它们应以/结束(并且在运行时,在加载之前附加从spring.config.name生成的名称,包括特定于配置文件的文件名) 。spring.config.location中指定的文件按原样使用,不支持特定于配置文件的变体,并且被任何特定于配置文件的属性覆盖。

以相反的顺序搜索配置位置。默认情况下,配置的位置为classpath:/,classpath:/config/,file:./,file:./config/生成的搜索顺序如下:

  1. file:./config/
  2. file:./
  3. classpath:/config/
  4. classpath:/

使用spring.config.location配置自定义配置位置时,它们会替换默认位置。例如,如果spring.config.location配置了值classpath:/custom-config/,file:./custom-config/,则搜索顺序将变为:

  1. file:./custom-config/
  2. classpath:custom-config/

或者,当使用spring.config.additional-location配置自定义配置位置时,除了默认位置外,还会使用它们。在默认位置之前搜索其他位置。例如,如果配置了classpath:/custom-config/,file:./custom-config/的其他位置,则搜索顺序将变为以下内容:

  1. file:./custom-config/
  2. classpath:custom-config/
  3. file:./config/
  4. file:./
  5. classpath:/config/
  6. classpath:/

此搜索顺序允许您在一个配置文件中指定默认值,然后有选择地覆盖另一个配置文件中的值。您可以在application.properties(或您使用spring.config.name选择的任何其他基本名称)中的某个默认位置为您的应用程序提供默认值。然后,可以在运行时使用位于其中一个自定义位置的不同文件覆盖这些默认值。

[注意]注意

如果使用环境变量而不是系统属性,则大多数操作系统都不允许使用句点分隔的键名称,但您可以使用下划线(例如,SPRING_CONFIG_NAME而不是spring.config.name)。

[注意]注意

如果应用程序在容器中运行,则可以使用JNDI属性(在java:comp/env中)或servlet上下文初始化参数来代替环境变量或系统属性。

24.4特定于配置文件的属性

除了application.properties文件之外,还可以使用以下命名约定来定义特定于配置文件的属性:application-{profile}.propertiesEnvironment有一组默认配置文件(默认情况下为[default]),如果未设置活动配置文件,则使用这些配置文件。换句话说,如果没有显式激活配置文件,则会加载application-default.properties中的属性。

特定于配置文件的属性从标准application.properties的相同位置加载,特定于配置文件的文件始终覆盖非特定文件,无论特定于配置文件的文件是在打包的jar内部还是外部。

如果指定了多个配置文件,则应用last-wins策略。例如,spring.profiles.active属性指定的配置文件将在通过SpringApplication API配置的配置文件之后添加,因此优先。

[注意]注意

如果您在spring.config.location中指定了任何文件,则不会考虑这些文件的特定于配置文件的变体。如果您还想使用特定于配置文件的属性,请使用spring.config.location中的目录。

24.5属性中的占位符

application.properties中的值在使用时通过现有的Environment进行过滤,因此您可以返回先前定义的值(例如,从系统属性中)。

app.name=MyApp
app.description=${app.name} is a Spring Boot application
[提示]提示

您还可以使用此技术创建现有Spring Boot属性的“短”变体。有关详细信息,请参见第77.4节“使用'短'命令行参数”方法。

24.6加密属性

Spring Boot没有为加密属性值提供任何内置支持,但是,它确实提供了修改Spring Environment中包含的值所必需的钩子点。EnvironmentPostProcessor界面允许您在应用程序启动之前操作Environment有关详细信息请参见第76.3节“在开始之前自定义环境或ApplicationContext”

如果您正在寻找一种存储凭据和密码的安全方法,那么 Spring Cloud Vault项目将支持在HashiCorp Vault中存储外部化配置

24.7使用YAML而不是属性

YAML是JSON的超集,因此是用于指定分层配置数据的便捷格式。只要在类路径上SnakeYAML库,SpringApplication类就会自动支持YAML作为属性的替代

[注意]注意

如果您使用“Starters”,则spring-boot-starter会自动提供SnakeYAML。

24.7.1加载YAML

Spring Framework提供了两个方便的类,可用于加载YAML文档。YamlPropertiesFactoryBean将YAML加载为PropertiesYamlMapFactoryBean将YAML加载为Map

例如,请考虑以下YAML文档:

environments:
	dev:
		url: http://dev.example.com
		name: Developer Setup
	prod:
		url: http://another.example.com
		name: My Cool App

前面的示例将转换为以下属性:

environments.dev.url=http://dev.example.com
environments.dev.name=Developer Setup
environments.prod.url=http://another.example.com
environments.prod.name=My Cool App

YAML列表表示为具有[index]解除引用的属性键。例如,考虑以下YAML:

my:
servers:
	- dev.example.com
	- another.example.com

前面的示例将转换为这些属性:

my.servers[0]=dev.example.com
my.servers[1]=another.example.com

要使用Spring Boot的Binder实用程序(这是@ConfigurationProperties所做的)绑定到这样的属性,你需要在java.util.List类型的目标bean中拥有一个属性(或Set)您需要提供一个setter或用可变值初始化它。例如,以下示例绑定到前面显示的属性:

@ConfigurationProperties(prefix="my")
public class Config {

	private List<String> servers = new ArrayList<String>();

	public List<String> getServers() {
		return this.servers;
	}
}

24.7.2在Spring环境中将YAML公开为属性

YamlPropertySourceLoader类可用于在Spring Environment中将YAML公开为PropertySource这样做可以使用带有占位符语法的@Value注释来访问YAML属性。

24.7.3多轮廓YAML文档

您可以使用spring.profiles键在单个文件中指定多个特定于配置文件的YAML文档,以指示文档何时应用,如以下示例所示:

server:
	address: 192.168.1.100
---
spring:
	profiles: development
server:
	address: 127.0.0.1
---
spring:
	profiles: production & eu-central
server:
	address: 192.168.1.120

在前面的示例中,如果development配置文件处于活动状态,则server.address属性为127.0.0.1同样,如果production eu-central配置文件处于活动状态,则server.address属性为192.168.1.120如果启用developmentproductioneu-central配置文件,则该属性的值为192.168.1.100

[注意]注意

因此,spring.profiles可以包含简单的配置文件名称(例如production)或配置文件表达式。概要表达式允许表达更复杂的概要逻辑,例如production & (eu-central | eu-west)有关详细信息,请查阅 参考指南

如果在应用程序上下文启动时没有显式激活,则激活默认配置文件。因此,在以下YAML中,我们设置spring.security.user.password的值,该值在“默认”配置文件中可用

server:
  port: 8000
---
spring:
  profiles: default
  security:
    user:
      password: weak

然而,在以下示例中,始终设置密码,因为它未附加到任何配置文件,并且必须在必要时在所有其他配置文件中显式重置:

server:
  port: 8000
spring:
  security:
    user:
      password: weak

使用spring.profiles元素指定的Spring配置文件可以选择使用!字符来否定。如果为单个文档指定了否定和非否定的配置文件,则至少一个非否定的配置文件必须匹配,并且没有否定的配置文件可以匹配。

24.7.4 YAML缺点

无法使用@PropertySource注释加载YAML文件。因此,如果您需要以这种方式加载值,则需要使用属性文件。

24.8类型安全配置属性

使用@Value("${property}")注释来注入配置属性有时会很麻烦,特别是如果您正在使用多个属性或者您的数据本质上是分层的。Spring Boot提供了一种使用属性的替代方法,该方法允许强类型beans管理和验证应用程序的配置,如以下示例所示:

package com.example;

import java.net.InetAddress;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import org.springframework.boot.context.properties.ConfigurationProperties;

@ConfigurationProperties("acme")
public class AcmeProperties {

	private boolean enabled;

	private InetAddress remoteAddress;

	private final Security security = new Security();

	public boolean isEnabled() { ... }

	public void setEnabled(boolean enabled) { ... }

	public InetAddress getRemoteAddress() { ... }

	public void setRemoteAddress(InetAddress remoteAddress) { ... }

	public Security getSecurity() { ... }

	public static class Security {

		private String username;

		private String password;

		private List<String> roles = new ArrayList<>(Collections.singleton("USER"));

		public String getUsername() { ... }

		public void setUsername(String username) { ... }

		public String getPassword() { ... }

		public void setPassword(String password) { ... }

		public List<String> getRoles() { ... }

		public void setRoles(List<String> roles) { ... }

	}
}

前面的POJO定义了以下属性:

  • acme.enabled,默认值为false
  • acme.remote-address,其类型可以从String强制执行。
  • acme.security.username,带有嵌套的“安全”对象,其名称由属性名称决定。特别是,那里根本没有使用返回类型,可能是SecurityProperties
  • acme.security.password.
  • acme.security.roles,收集String
[注意]注意

getter和setter通常是必需的,因为绑定是通过标准的Java Beans属性描述符,就像在Spring MVC中一样。在下列情况下可以省略setter:

  • 映射,只要它们被初始化,就需要一个getter但不一定是setter,因为它们可以被绑定器变异。
  • 可以通过索引(通常使用YAML)或使用单个逗号分隔值(属性)访问集合和数组。在后一种情况下,必须使用setter。我们建议始终为此类型添加setter。如果初始化集合,请确保它不是不可变的(如上例所示)。
  • 如果初始化嵌套的POJO属性(如前面示例中的Security字段),则不需要setter。如果您希望绑定器通过使用其默认构造函数动态创建实例,则需要一个setter。

有些人使用Project Lombok自动添加getter和setter。确保Lombok不为此类型生成任何特定构造函数,因为容器会自动使用它来实例化对象。

最后,仅考虑标准Java Bean属性,并且不支持对静态属性的绑定。

您还需要列出要在@EnableConfigurationProperties注释中注册的属性类,如以下示例所示:

@Configuration
@EnableConfigurationProperties(AcmeProperties.class)
public class MyConfiguration {
}
[注意]注意

@ConfigurationProperties bean以这种方式注册时,bean具有常规名称:<prefix>-<fqn>,其中<prefix>@ConfigurationProperties注释中指定的环境键前缀<fqn>是bean的完全限定名称。如果注释未提供任何前缀,则仅使用bean的完全限定名称。

上例中的bean名称为acme-com.example.AcmeProperties

即使前面的配置为AcmeProperties创建了常规bean,我们也建议@ConfigurationProperties仅处理环境,特别是不从上下文中注入其他beans。话虽如此,@EnableConfigurationProperties注释也会自动应用于您的项目,以便Environment配置任何现有 bean注释@ConfigurationProperties您可以通过确保AcmeProperties已经是bean来快捷MyConfiguration,如以下示例所示:

@Component
@ConfigurationProperties(prefix="acme")
public class AcmeProperties {

	// ... see the preceding example

}

这种配置风格与SpringApplication外部YAML配置特别有效,如以下示例所示:

# application.yml

acme:
	remote-address: 192.168.1.1
	security:
		username: admin
		roles:
		  - USER
		  - ADMIN

# additional configuration as required

要使用@ConfigurationProperties beans,您可以使用与任何其他bean相同的方式注入它们,如以下示例所示:

@Service
public class MyService {

	private final AcmeProperties properties;

	@Autowired
	public MyService(AcmeProperties properties) {
	    this.properties = properties;
	}

 	//...

	@PostConstruct
	public void openConnection() {
		Server server = new Server(this.properties.getRemoteAddress());
		// ...
	}

}
[提示]提示

使用@ConfigurationProperties还可以生成元数据文件,IDE可以使用这些文件为您自己的密钥提供自动完成功能。有关详细信息请参阅 附录B,配置元数据附录。

24.8.1第三方配置

除了使用@ConfigurationProperties注释类之外,您还可以在公共@Bean方法上使用它。当您想要将属性绑定到控件之外的第三方组件时,这样做会特别有用。

要从Environment属性配置bean,请在其bean注册中添加@ConfigurationProperties,如以下示例所示:

@ConfigurationProperties(prefix = "another")
@Bean
public AnotherComponent anotherComponent() {
	...
}

使用another前缀定义的任何属性都以与前面的AcmeProperties示例类似的方式映射到AnotherComponent bean。

24.8.2松弛结合

Spring Boot使用一些宽松的规则将Environment属性绑定到@ConfigurationProperties beans,因此不需要在Environment属性名称和bean属性之间进行精确匹配名称。这有用的常见示例包括破折号分隔的环境属性(例如,context-path绑定到contextPath)和大写环境属性(例如,PORT绑定到port)。

例如,考虑以下@ConfigurationProperties类:

@ConfigurationProperties(prefix="acme.my-project.person")
public class OwnerProperties {

	private String firstName;

	public String getFirstName() {
		return this.firstName;
	}

	public void setFirstName(String firstName) {
		this.firstName = firstName;
	}

}

在前面的示例中,可以使用以下属性名称:

表24.1。轻松绑定

Property注意

acme.my-project.person.first-name

Kebab案例,建议在.properties.yml文件中使用。

acme.myProject.person.firstName

标准的驼峰案例语法。

acme.my_project.person.first_name

下划线表示法,这是在.properties.yml文件中使用的替代格式。

ACME_MYPROJECT_PERSON_FIRSTNAME

大写格式,使用系统环境变量时建议使用。


[注意]注意

注释的prefix必须为kebab大小写(小写并以-分隔,例如acme.my-project.person)。

表24.2。每个属性源放宽绑定规则

Property来源简单名单

属性文件

骆驼案,烤肉串案例或下划线表示法

使用[ ]或逗号分隔值的标准列表语法

YAML文件

骆驼案,烤肉串案例或下划线表示法

标准YAML列表语法或逗号分隔值

环境变量

大写格式,下划线作为分隔符。_不应在属性名称中使用

由下划线包围的数字值,例如MY_ACME_1_OTHER = my.acme[1].other

系统属性

骆驼案,烤肉串案例或下划线表示法

使用[ ]或逗号分隔值的标准列表语法


[提示]提示

我们建议,在可能的情况下,属性以小写烤肉串格式存储,例如my.property-name=acme

绑定到Map属性时,如果key包含除小写字母数字字符或-以外的任何内容,则需要使用括号表示法以保留原始值。如果密钥未被[]包围,则删除任何非字母数字或-的字符。例如,考虑将以下属性绑定到Map

acme:
  map:
    "[/key1]": value1
    "[/key2]": value2
    /key3: value3

上面的属性将绑定到Map,其中/key1/key2key3作为地图中的键。

24.8.3合并复杂类型

当列表在多个位置配置时,覆盖通过替换整个列表来工作。

例如,假设一个MyPojo对象,其namedescription属性默认为null以下示例公开了来自AcmePropertiesMyPojo对象的列表:

@ConfigurationProperties("acme")
public class AcmeProperties {

	private final List<MyPojo> list = new ArrayList<>();

	public List<MyPojo> getList() {
		return this.list;
	}

}

请考虑以下配置:

acme:
  list:
    - name: my name
      description: my description
---
spring:
  profiles: dev
acme:
  list:
    - name: my another name

如果dev配置文件未激活,AcmeProperties.list包含一个MyPojo条目,如前所述。但是,如果启用了dev配置文件,则list 仍然 只包含一个条目(名称为my another name且描述为null)。此配置不会向列表添加第二个MyPojo实例,也不会合并项目。

在多个配置文件中指定List时,将使用具有最高优先级(并且仅具有该优先级)的配置文件。请考虑以下示例:

acme:
  list:
    - name: my name
      description: my description
    - name: another name
      description: another description
---
spring:
  profiles: dev
acme:
  list:
    - name: my another name

在前面的示例中,如果dev配置文件处于活动状态,则AcmeProperties.list包含 一个 MyPojo条目(名称为my another name,描述为null)。对于YAML,逗号分隔列表和YAML列表都可用于完全覆盖列表的内容。

对于Map属性,您可以绑定从多个源中提取的属性值。但是,对于多个源中的相同属性,使用具有最高优先级的属性。以下示例从AcmeProperties公开Map<String, MyPojo>

@ConfigurationProperties("acme")
public class AcmeProperties {

	private final Map<String, MyPojo> map = new HashMap<>();

	public Map<String, MyPojo> getMap() {
		return this.map;
	}

}

请考虑以下配置:

acme:
  map:
    key1:
      name: my name 1
      description: my description 1
---
spring:
  profiles: dev
acme:
  map:
    key1:
      name: dev name 1
    key2:
      name: dev name 2
      description: dev description 2

如果dev个人资料未激活,则AcmeProperties.map包含一个密钥为key1的条目(名称为my name 1,描述为my description 1)。但是,如果dev配置文件已启用,则map包含两个带有密钥key1的条目(名称为dev name 1且描述为my description 1)和key2(带有名称dev name 2和描述dev description 2)。

[注意]注意

前面的合并规则适用于所有属性源的属性,而不仅仅是YAML文件。

24.8.4属性转换

Spring Boot在绑定到@ConfigurationProperties beans时尝试将外部应用程序属性强制转换为正确的类型。如果您需要自定义类型转换,则可以提供ConversionService bean(bean名为conversionService)或自定义属性编辑器(通过CustomEditorConfigurer bean)或自定义Converters(bean定义注释为@ConfigurationPropertiesBinding)。

[注意]注意

由于在应用程序生命周期中很早就请求bean,因此请确保限制ConversionService正在使用的依赖项。通常,您在创建时可能无法完全初始化所需的任何依赖项。如果配置密钥强制不需要,您可能需要重命名自定义ConversionService,并且只依赖于使用@ConfigurationPropertiesBinding限定的自定义转换器。

转换持续时间

Spring Boot专门支持表达持续时间。如果公开java.time.Duration属性,则可以使用应用程序属性中的以下格式:

  • 常规long表示(使用毫秒作为默认单位,除非指定了@DurationUnit
  • java.util.Duration使用的标准ISO-8601格式
  • 更可读的格式,其中值和单位耦合(例如10s表示10秒)

请考虑以下示例:

@ConfigurationProperties("app.system")
public class AppSystemProperties {

	@DurationUnit(ChronoUnit.SECONDS)
	private Duration sessionTimeout = Duration.ofSeconds(30);

	private Duration readTimeout = Duration.ofMillis(1000);

	public Duration getSessionTimeout() {
		return this.sessionTimeout;
	}

	public void setSessionTimeout(Duration sessionTimeout) {
		this.sessionTimeout = sessionTimeout;
	}

	public Duration getReadTimeout() {
		return this.readTimeout;
	}

	public void setReadTimeout(Duration readTimeout) {
		this.readTimeout = readTimeout;
	}

}

要指定30秒的会话超时,30PT30S30s都是等效的。可以使用以下任何一种形式指定500ms的读取超时:500PT0.5S500ms

您也可以使用任何支持的单位。这些是:

  • 纳秒时间为ns
  • us微秒
  • ms毫秒
  • s
  • m分钟
  • h几个小时
  • d几天

默认单位是毫秒,可以使用@DurationUnit覆盖,如上面的示例所示。

[提示]提示

如果要从仅使用Long来表示持续时间的先前版本升级,请确保定义单位(使用@DurationUnit),如果它不是切换到Duration旁边的毫秒。这样做可以提供透明的升级路径,同时支持更丰富的格式。

转换数据大小

Spring Framework有一个DataSize值类型,允许以字节为单位表示大小。如果公开DataSize属性,则可以使用应用程序属性中的以下格式:

  • 常规long表示(使用字节作为默认单位,除非指定了@DataSizeUnit
  • 值和单元耦合的更易读的格式(例如10MB表示10兆字节)

请考虑以下示例:

@ConfigurationProperties("app.io")
public class AppIoProperties {

	@DataSizeUnit(DataUnit.MEGABYTES)
	private DataSize bufferSize = DataSize.ofMegabytes(2);

	private DataSize sizeThreshold = DataSize.ofBytes(512);

	public DataSize getBufferSize() {
		return this.bufferSize;
	}

	public void setBufferSize(DataSize bufferSize) {
		this.bufferSize = bufferSize;
	}

	public DataSize getSizeThreshold() {
		return this.sizeThreshold;
	}

	public void setSizeThreshold(DataSize sizeThreshold) {
		this.sizeThreshold = sizeThreshold;
	}

}

要指定10兆字节的缓冲区大小,1010MB是等效的。可以将大小阈值256字节指定为256256B

您也可以使用任何支持的单位。这些是:

  • B表示字节
  • 千字节KB
  • MB表示兆字节
  • GB为千兆字节
  • TB表示太字节

默认单位是字节,可以使用@DataSizeUnit覆盖,如上面的示例所示。

[提示]提示

如果要从仅使用Long来表示大小的先前版本升级,请确保定义单位(使用@DataSizeUnit),如果它不是切换到DataSize旁边的字节。这样做可以提供透明的升级路径,同时支持更丰富的格式。

24.8.5 @ConfigurationProperties验证

Spring Boot尝试使用Spring @Validated注释注释@ConfigurationProperties类。您可以直接在配置类上使用JSR-303 javax.validation约束注释。为此,请确保符合条件的JSR-303实现位于类路径上,然后将约束注释添加到字段中,如以下示例所示:

@ConfigurationProperties(prefix="acme")
@Validated
public class AcmeProperties {

	@NotNull
	private InetAddress remoteAddress;

	// ... getters and setters

}
[提示]提示

您还可以通过使用@Validated注释创建配置属性的@Bean方法来触发验证。

虽然嵌套属性也会在绑定时进行验证,但最好还是将关联字段注释为@Valid这可确保即使未找到嵌套属性也会触发验证。以下示例基于前面的AcmeProperties示例构建:

@ConfigurationProperties(prefix="acme")
@Validated
public class AcmeProperties {

	@NotNull
	private InetAddress remoteAddress;

	@Valid
	private final Security security = new Security();

	// ... getters and setters

	public static class Security {

		@NotEmpty
		public String username;

		// ... getters and setters

	}

}

您还可以通过创建名为configurationPropertiesValidator的bean定义来添加自定义Spring Validator应该声明@Bean方法static配置属性验证器是在应用程序生命周期的早期创建的,并且将@Bean方法声明为静态可以创建bean而无需实例化@Configuration类。这样做可以避免早期实例化可能导致的任何问题。有一个 属性验证示例,显示如何设置。

[提示]提示

spring-boot-actuator模块包含一个暴露所有@ConfigurationProperties beans的端点。将Web浏览器指向/actuator/configprops或使用等效的JMX端点。有关详细信息,请参阅“ 生产就绪功能 ”部分。

24.8.6 @ConfigurationProperties与@Value

@Value注释是核心容器功能,它不提供与类型安全配置属性相同的功能。下表总结了@ConfigurationProperties@Value支持的功能:

特征@ConfigurationProperties@Value

Relaxed binding

Yes

No

Meta-data support

Yes

No

SpEL evaluation

No

Yes

如果为自己的组件定义一组配置键,我们建议您将它们分组到带有@ConfigurationProperties注释的POJO中。您还应该知道,由于@Value不支持宽松绑定,因此如果您需要使用环境变量来提供值,则它不是一个好的候选者。

最后,虽然您可以在@Value中编写SpEL表达式,但不会从应用程序属性文件中处理此类表达式

25.简介

Spring Profiles提供了一种隔离应用程序配置部分并使其仅在特定环境中可用的方法。任何@Component@Configuration都可以用@Profile标记以限制何时加载,如以下示例所示:

@Configuration
@Profile("production")
public class ProductionConfiguration {

	// ...

}

您可以使用spring.profiles.active Environment属性指定哪些配置文件处于活动状态。您可以使用本章前面介绍的任何方法指定属性。例如,您可以将其包含在application.properties中,如以下示例所示:

spring.profiles.active=dev,hsqldb

您还可以使用以下开关在命令行上指定它:--spring.profiles.active=dev,hsqldb

25.1添加活动配置文件

spring.profiles.active属性遵循与其他属性相同的排序规则:最高PropertySource获胜。这意味着您可以在application.properties中指定活动配置文件,然后使用命令行开关替换它们。

有时,将特定于配置文件的属性添加到活动配置文件而不是替换它们是有用的spring.profiles.include属性可用于无条件地添加活动配置文件。SpringApplication入口点还有一个用于设置其他配置文件的Java API(即,在spring.profiles.active属性激活的配置文件之上)。请参阅SpringApplication中setAdditionalProfiles()方法

例如,当使用开关--spring.profiles.active=prod运行具有以下属性的应用程序时,proddbprodmq配置文件也会被激活:

---
my.property: fromyamlfile
---
spring.profiles: prod
spring.profiles.include:
  - proddb
  - prodmq
[注意]注意

请记住,可以在YAML文档中定义spring.profiles属性,以确定此特定文档何时包含在配置中。有关更多详细信息请参见 第77.7节“根据环境更改配置”

25.2以编程方式设置配置文件

您可以在应用程序运行之前通过调用SpringApplication.setAdditionalProfiles(…​)以编程方式设置活动配置文件。也可以使用Spring的ConfigurableEnvironment界面激活配置文件。

25.3特定于配置文件的配置文件

application.properties(或application.yml)的配置文件特定变体和通过@ConfigurationProperties引用的文件被视为文件并已加载。有关详细信息请参见“ 第24.4节”“特定配置文件的属性”

26.记录

Spring Boot使用Commons Logging进行所有内部日志记录,但保留底层日志实现。Java Util LoggingLog4J2Logback提供了默认配置 在每种情况下,记录器都预先配置为使用控制台输出,并且还提供可选的文件输出。

默认情况下,如果使用“Starters”,则使用Logback进行日志记录。还包括适当的Logback路由,以确保使用Java Util Logging,Commons Logging,Log4J或SLF4J的依赖库都能正常工作。

[提示]提示

Java有很多日志框架可供使用。如果以上列表看起来令人困惑,请不要担心。通常,您不需要更改日志记录依赖项,并且Spring Boot默认值可以正常工作。

26。1日志格式

Spring Boot的默认日志输出类似于以下示例:

2014-03-05 10:57:51.112  INFO 45469 --- [           main] org.apache.catalina.core.StandardEngine  : Starting Servlet Engine: Apache Tomcat/7.0.52
2014-03-05 10:57:51.253  INFO 45469 --- [ost-startStop-1] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2014-03-05 10:57:51.253  INFO 45469 --- [ost-startStop-1] o.s.web.context.ContextLoader            : Root WebApplicationContext: initialization completed in 1358 ms
2014-03-05 10:57:51.698  INFO 45469 --- [ost-startStop-1] o.s.b.c.e.ServletRegistrationBean        : Mapping servlet: 'dispatcherServlet' to [/]
2014-03-05 10:57:51.702  INFO 45469 --- [ost-startStop-1] o.s.b.c.embedded.FilterRegistrationBean  : Mapping filter: 'hiddenHttpMethodFilter' to: [/*]

输出以下项目:

  • 日期和时间:毫秒精度,易于排序。
  • 日志级别:ERRORWARNINFODEBUGTRACE
  • 进程ID。
  • 一个---分隔符,用于区分实际日志消息的开头。
  • 线程名称:括在方括号中(可能会截断控制台输出)。
  • 记录器名称:这通常是源类名称(通常缩写)。
  • 日志消息。
[注意]注意

Logback没有FATAL级别。它映射到ERROR

26.2控制台输出

默认日志配置会在写入时将消息回显到控制台。默认情况下,会记录ERROR - 级别,WARN - 级别和INFO级别的消息。您还可以通过使用--debug标志启动应用程序来启用“调试”模式。

$ java -jar myapp.jar --debug
[注意]注意

您还可以在application.properties中指定debug=true

启用调试模式后,将选择一些核心记录器(嵌入式容器,Hibernate和Spring Boot)以输出更多信息。启用调试模式并没有将应用程序配置为记录与DEBUG级别的所有消息。

或者,您可以通过使用--trace标志(或application.properties中的trace=true)启动应用程序来启用“跟踪”模式。这样做可以为选择的核心记录器(嵌入式容器,Hibernate模式生成和整个Spring组合)启用跟踪日志记录。

26.2.1彩色编码输出

如果您的终端支持ANSI,则使用颜色输出来提高可读性。您可以将spring.output.ansi.enabled设置为 支持的值以覆盖自动检测。

使用%clr转换字配置颜色编码。在最简单的形式中,转换器根据日志级别为输出着色,如以下示例所示:

%clr(%5p)

下表描述了日志级别到颜色的映射:

水平颜色

FATAL

Red

ERROR

Red

WARN

Yellow

INFO

Green

DEBUG

Green

TRACE

Green

或者,您可以通过将其作为转换选项指定应使用的颜色或样式。例如,要使文本变为黄色,请使用以下设置:

%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){yellow}

支持以下颜色和样式:

  • blue
  • cyan
  • faint
  • green
  • magenta
  • red
  • yellow

26.3文件输出

默认情况下,Spring Boot仅记录到控制台,不会写入日志文件。如果除了控制台输出之外还要编写日志文件,则需要设置logging.filelogging.path属性(例如,在application.properties中)。

下表显示了logging.*属性如何一起使用:

表26.1。记录属性

logging.filelogging.path描述

(没有)

(没有)

 

仅控制台记录。

具体文件

(没有)

my.log

写入指定的日志文件。名称可以是精确位置或相对于当前目录。

(没有)

具体目录

/var/log

spring.log写入指定的目录。名称可以是精确位置或相对于当前目录。


日志文件在达到10 MB时会轮换,与控制台输出一样,默认情况下会记录ERROR - 级别,WARN - 级别和INFO级别的消息。可以使用logging.file.max-size属性更改大小限制。除非已设置logging.file.max-history属性,否则以前轮换的文件将无限期归档。

[注意]注意

日志记录系统在应用程序生命周期的早期初始化。因此,在通过@PropertySource注释加载的属性文件中找不到日志记录属性。

[提示]提示

日志记录属性独立于实际的日志记录基础结构。因此,Spring Boot不管理特定的配置密钥(例如用于Logback的logback.configurationFile)。

26。4日志级别

所有受支持的日志记录系统都可以使用logging.level.<logger-name>=<level>在Spring Environment中设置记录器级别(例如,在application.properties中),其中level是TRACE,DEBUG,INFO之一,警告,错误,致命或关闭。可以使用logging.level.root配置root记录器。

以下示例显示application.properties中的潜在日志记录设置:

logging.level.root=WARN
logging.level.org.springframework.web=DEBUG
logging.level.org.hibernate=ERROR

26。5日志组

能够将相关记录器组合在一起以便可以同时配置它们通常很有用。例如,您通常可以更改所有 Tomcat相关记录器的日志记录级别 ,但您无法轻松记住顶级软件包。

为此,Spring Boot允许您在Spring Environment中定义日志记录组。例如,以下是如何通过将“tomcat”组添加到application.properties来定义它:

logging.group.tomcat=org.apache.catalina, org.apache.coyote, org.apache.tomcat

定义后,您可以使用一行更改组中所有记录器的级别:

logging.level.tomcat=TRACE

Spring Boot包括以下可以开箱即用的预定义日志记录组:

名称记录仪

web

org.springframework.core.codec, org.springframework.http, org.springframework.web

sql

org.springframework.jdbc.core, org.hibernate.SQL

26.6自定义日志配置

可以通过在类路径中包含相应的库来激活各种日志记录系统,并且可以通过在类路径的根目录中或在以下Spring Environment属性指定的位置提供合适的配置文件来进一步自定义: logging.config

您可以使用org.springframework.boot.logging.LoggingSystem系统属性强制Spring Boot使用特定的日志记录系统。该值应该是LoggingSystem实现的完全限定类名。您还可以使用值none完全禁用Spring Boot的日志记录配置。

[注意]注意

由于创建ApplicationContext 之前初始化日志记录,因此无法控制Spring @Configuration文件中@PropertySources的日志记录。更改日志记录系统或完全禁用它的唯一方法是通过系统属性。

根据您的日志记录系统,将加载以下文件:

记录系统定制

Logback

logback-spring.xml, logback-spring.groovy, logback.xml, or logback.groovy

Log4j2

log4j2-spring.xml or log4j2.xml

JDK (Java Util Logging)

logging.properties

[注意]注意

如果可能,我们建议您使用-spring变体进行日志记录配置(例如,logback-spring.xml而不是logback.xml)。如果使用标准配置位置,Spring无法完全控制日志初始化。

[警告]警告

Java Util Logging存在已知的类加载问题,这些问题在从“可执行jar”运行时会导致问题。如果可能的话,我们建议您在从“可执行jar”运行时避免使用它。

为了帮助进行自定义,一些其他属性从Spring Environment传输到系统属性,如下表所述:

Spring环境系统Property评论

logging.exception-conversion-word

LOG_EXCEPTION_CONVERSION_WORD

The conversion word used when logging exceptions.

logging.file

LOG_FILE

If defined, it is used in the default log configuration.

logging.file.max-size

LOG_FILE_MAX_SIZE

Maximum log file size (if LOG_FILE enabled). (Only supported with the default Logback setup.)

logging.file.max-history

LOG_FILE_MAX_HISTORY

Maximum number of archive log files to keep (if LOG_FILE enabled). (Only supported with the default Logback setup.)

logging.path

LOG_PATH

If defined, it is used in the default log configuration.

logging.pattern.console

CONSOLE_LOG_PATTERN

The log pattern to use on the console (stdout). (Only supported with the default Logback setup.)

logging.pattern.dateformat

LOG_DATEFORMAT_PATTERN

Appender pattern for log date format. (Only supported with the default Logback setup.)

logging.pattern.file

FILE_LOG_PATTERN

The log pattern to use in a file (if LOG_FILE is enabled). (Only supported with the default Logback setup.)

logging.pattern.level

LOG_LEVEL_PATTERN

The format to use when rendering the log level (default %5p). (Only supported with the default Logback setup.)

PID

PID

The current process ID (discovered if possible and when not already defined as an OS environment variable).

所有受支持的日志记录系统在解析其配置文件时都可以参考系统属性。有关示例,请参阅spring-boot.jar中的默认配置:

[提示]提示

如果要在日志记录属性中使用占位符,则应使用 Spring Boot的语法,而不是底层框架的语法。值得注意的是,如果使用Logback,则应使用:作为属性名称与其默认值之间的分隔符,而不是使用:-

[提示]提示

您可以通过仅覆盖LOG_LEVEL_PATTERN(或带有Logback的logging.pattern.level)将MDC和其他临时内容添加到日志行。例如,如果使用logging.pattern.level=user:%X{user} %5p,则默认日志格式包含“user”的MDC条目(如果存在),如以下示例所示。

2015-09-30 12:30:04.031 user:someone INFO 22174 --- [  nio-8080-exec-0] demo.Controller
Handling authenticated request

26.7 Logback Extensions

Spring Boot包含许多Logback扩展,可以帮助进行高级配置。您可以在logback-spring.xml配置文件中使用这些扩展名。

[注意]注意

由于标准logback.xml配置文件加载过早,因此无法在其中使用扩展。您需要使用logback-spring.xml或定义logging.config属性。

[警告]警告

扩展不能与Logback的 配置扫描一起使用如果尝试这样做,则更改配置文件会导致类似于以下记录之一的错误:

ERROR in ch.qos.logback.core.joran.spi.Interpreter@4:71 - no applicable action for [springProperty], current ElementPath is [[configuration][springProperty]]
ERROR in ch.qos.logback.core.joran.spi.Interpreter@4:71 - no applicable action for [springProfile], current ElementPath is [[configuration][springProfile]]

26.7.1特定于配置文件的配置

<springProfile>标记允许您根据活动的Spring配置文件选择性地包含或排除配置部分。<configuration>元素中的任何位置都支持配置文件节。使用name属性指定哪个配置文件接受配置。<springProfile>标记可以包含简单的配置文件名称(例如staging)或配置文件表达式。概要表达式允许表达更复杂的概要逻辑,例如production & (eu-central | eu-west)有关详细信息,请查阅 参考指南以下清单显示了三个示例配置文件:

<springProfile name="staging">
	<!-- configuration to be enabled when the "staging" profile is active -->
</springProfile>

<springProfile name="dev | staging">
	<!-- configuration to be enabled when the "dev" or "staging" profiles are active -->
</springProfile>

<springProfile name="!production">
	<!-- configuration to be enabled when the "production" profile is not active -->
</springProfile>

26.7.2环境属性

<springProperty>标记允许您公开Spring Environment中的属性,以便在Logback中使用。如果要在Logback配置中访问application.properties文件中的值,这样做非常有用。标签的工作方式与Logback的标准<property>标签类似。但是,不是指定直接value,而是指定属性的source(来自Environment)。如果您需要将属性存储在local范围以外的其他位置,则可以使用scope属性。如果需要回退值(如果未在Environment中设置该属性),则可以使用defaultValue属性。以下示例显示如何公开在Logback中使用的属性:

<springProperty scope="context" name="fluentHost" source="myapp.fluentd.host"
		defaultValue="localhost"/>
<appender name="FLUENT" class="ch.qos.logback.more.appenders.DataFluentAppender">
	<remoteHost>${fluentHost}</remoteHost>
	...
</appender>
[注意]注意

必须在烤肉串案例中指定source(例如my.property-name)。但是,可以使用宽松规则将属性添加到Environment

27. JSON

Spring Boot提供了与三个JSON映射库的集成:

  • GSON
  • Jackson
  • JSON-B

Jackson是首选的默认库。

27.1 Jackson

提供了Jackson的自动配置,Jackson是spring-boot-starter-json的一部分。当Jackson在类路径上时,会自动配置ObjectMapper bean。提供了几个配置属性来自 定义ObjectMapper的配置

27.2 Gson

提供Gson的自动配置。当Gson在类路径上时,会自动配置Gson bean。提供了几个spring.gson.*配置属性来自定义配置。为了获得更多控制,可以使用一个或多个GsonBuilderCustomizer beans。

27.3 JSON-B

提供了JSON-B的自动配置。当JSON-B API和实现在类路径上时,将自动配置Jsonb bean。首选的JSON-B实现是Apache Johnzon,它提供了依赖关系管理。

28.开发Web应用程序

Spring Boot非常适合Web应用程序开发。您可以使用嵌入式Tomcat,Jetty,Undertow或Netty创建自包含的HTTP服务器。大多数Web应用程序使用spring-boot-starter-web模块快速启动和运行。您还可以使用spring-boot-starter-webflux模块选择构建响应式Web应用程序。

如果您还没有开发Spring Boot Web应用程序,可以按照“Hello World!”进行操作。入门”部分中的示例

28.1“Spring Web MVC框架”

Spring Web框架(通常简称为“Spring MVC”)是一种富含“模型视图控制器” Web框架。Spring MVC允许您创建特殊的@Controller@RestController beans来处理传入的HTTP请求。控制器中的方法使用@RequestMapping注释映射到HTTP。

以下代码显示了为JSON数据提供服务的典型@RestController

@RestController
@RequestMapping(value="/users")
public class MyRestController {

	@RequestMapping(value="/{user}", method=RequestMethod.GET)
	public User getUser(@PathVariable Long user) {
		// ...
	}

	@RequestMapping(value="/{user}/customers", method=RequestMethod.GET)
	List<Customer> getUserCustomers(@PathVariable Long user) {
		// ...
	}

	@RequestMapping(value="/{user}", method=RequestMethod.DELETE)
	public User deleteUser(@PathVariable Long user) {
		// ...
	}

}

Spring MVC是核心Spring框架的一部分,详细信息可在参考文档中找到还有一些指南涵盖Spring MVC,可在spring.io/guides上找到

28.1.1 Spring MVC自动配置

Spring Boot为Spring MVC提供了自动配置,适用于大多数应用程序。

自动配置在Spring的默认值之上添加了以下功能:

如果你想保留Spring Boot MVC功能,并且你想添加额外的 MVC配置(拦截器,格式化程序,视图控制器和其他功能),你可以添加自己的@ConfigurationWebMvcConfigurer类但没有 @EnableWebMvc如果您希望提供RequestMappingHandlerMappingRequestMappingHandlerAdapterExceptionHandlerExceptionResolver的自定义实例,则可以声明WebMvcRegistrationsAdapter实例以提供此类组件。

如果您想完全控制Spring MVC,可以添加自己的@Configuration注释@EnableWebMvc

28.1.2 HttpMessageConverters

Spring MVC使用HttpMessageConverter接口转换HTTP请求和响应。明智的默认设置包含在开箱即用中。例如,对象可以自动转换为JSON(通过使用Jackson库)或XML(如果可用,使用Jackson XML扩展,或者如果Jackson XML扩展不是,则使用JAXB可用)。默认情况下,字符串以UTF-8编码。

如果您需要添加或自定义转换器,可以使用Spring Boot的HttpMessageConverters类,如下面的清单所示:

import org.springframework.boot.autoconfigure.web.HttpMessageConverters;
import org.springframework.context.annotation.*;
import org.springframework.http.converter.*;

@Configuration
public class MyConfiguration {

	@Bean
	public HttpMessageConverters customConverters() {
		HttpMessageConverter<?> additional = ...
		HttpMessageConverter<?> another = ...
		return new HttpMessageConverters(additional, another);
	}

}

上下文中存在的任何HttpMessageConverter bean都将添加到转换器列表中。您也可以以相同的方式覆盖默认转换器。

28.1.3自定义JSON序列化程序和反序列化程序

如果使用Jackson序列化和反序列化JSON数据,您可能需要编写自己的JsonSerializerJsonDeserializer类。自定义序列化程序通常 通过模块注册Jackson,但Spring Boot提供了另一种@JsonComponent注释,可以更容易地直接注册Spring Beans。

您可以直接在JsonSerializerJsonDeserializer实现上使用@JsonComponent注释。您还可以在包含序列化程序/反序列化程序作为内部类的类上使用它,如以下示例所示:

import java.io.*;
import com.fasterxml.jackson.core.*;
import com.fasterxml.jackson.databind.*;
import org.springframework.boot.jackson.*;

@JsonComponent
public class Example {

	public static class Serializer extends JsonSerializer<SomeObject> {
		// ...
	}

	public static class Deserializer extends JsonDeserializer<SomeObject> {
		// ...
	}

}

ApplicationContext中的所有@JsonComponent beans都会自动注册到Jackson。由于@JsonComponent使用@Component进行元注释,因此通常的组件扫描规则适用。

Spring Boot还提供 JsonObjectSerializerJsonObjectDeserializer该给标准提供有用的替代基类Jackson版本序列化对象时。JsonObjectSerializerJsonObjectDeserializer在Javadoc了解详情。

28.1.4 MessageCodesResolver

Spring MVC有一个生成错误代码的策略,用于从绑定错误中呈现错误消息:MessageCodesResolver如果设置spring.mvc.message-codes-resolver.format属性PREFIX_ERROR_CODEPOSTFIX_ERROR_CODE,则Spring Boot会为您创建一个(请参阅枚举 DefaultMessageCodesResolver.Format)。

28.1.5静态内容

默认情况下,Spring Boot从类路径中的/static(或/public/resources/META-INF/resources)目录或ServletContext的根目录中提供静态内容。它使用来自Spring MVC的ResourceHttpRequestHandler,以便您可以通过添加自己的WebMvcConfigurer并覆盖addResourceHandlers方法来修改该行为。

在独立的Web应用程序中,容器中的默认servlet也会启用,并作为后备,如果Spring决定不处理它,则从ServletContext的根目录提供内容。大多数情况下,这不会发生(除非您修改默认的MVC配置),因为Spring始终可以通过DispatcherServlet处理请求。

默认情况下,资源映射到/**,但您可以使用spring.mvc.static-path-pattern属性对其进行调整。例如,将所有资源重新定位到/resources/**可以实现如下:

spring.mvc.static-path-pattern=/resources/**

您还可以使用spring.resources.static-locations属性自定义静态资源位置(将默认值替换为目录位置列表)。根Servlet上下文路径"/"也会自动添加为位置。

除了前面提到的“标准”静态资源位置之外,还为Webjars内容制作了一个特例如果它们以Webjars格式打包,那么具有/webjars/**中路径的任何资源都将从jar文件中提供。

[提示]提示

如果您的应用程序打包为jar,请不要使用src/main/webapp目录。虽然这个目录是一个通用的标准,它的工作原理只是战争的包装,它是默默大多数构建工具忽略,如果你生成一个罐子。

Spring Boot还支持Spring MVC提供的高级资源处理功能,允许使用缓存破坏静态资源等用例或使用与Webjars无关的URL。

要为Webjars使用版本无关的URL,请添加webjars-locator-core依赖项。然后声明你的Webjar。以jQuery为例,添加"/webjars/jquery/jquery.min.js"会产生"/webjars/jquery/x.y.z/jquery.min.js"其中x.y.z是Webjar版本。

[注意]注意

如果使用JBoss,则需要声明webjars-locator-jboss-vfs依赖项而不是webjars-locator-core否则,所有Webjars都将解析为404

要使用缓存清除,以下配置会为所有静态资源配置缓存清除解决方案,从而在URL中有效添加内容哈希(例如<link href="/css/spring-2a2d595e6ed9a0b24f027f2b63b134d6.css"/>):

spring.resources.chain.strategy.content.enabled=true
spring.resources.chain.strategy.content.paths=/**
[注意]注意

由于为Thymeleaf和FreeMarker自动配置了ResourceUrlEncodingFilter,因此在运行时可以在模板中重写资源链接。您应该在使用JSP时手动声明此过滤器。其他模板引擎目前不是自动支持的,但可以使用自定义模板宏/帮助程序和使用 ResourceUrlProvider

使用(例如)JavaScript模块加载器动态加载资源时,不能重命名文件。这就是为什么其他策略也得到支持并可以合并的原因。“固定”策略在URL中添加静态版本字符串而不更改文件名,如以下示例所示:

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

使用此配置,位于"/js/lib/"下的JavaScript模块使用固定版本控制策略("/v12/js/lib/mymodule.js"),而其他资源仍使用内容1(<link href="/css/spring-2a2d595e6ed9a0b24f027f2b63b134d6.css"/>)。

有关ResourceProperties 更多支持选项,请参阅

[提示]提示

此功能已在专门的博客文章和Spring Framework的 参考文档中进行了详细描述

28.1.6欢迎页面

Spring Boot支持静态和模板化的欢迎页面。它首先在配置的静态内容位置中查找index.html文件。如果找不到,则会查找index模板。如果找到任何一个,它将自动用作应用程序的欢迎页面。

28.1.7自定义Favicon

Spring Boot在配置的静态内容位置和类路径的根(按此顺序)中查找favicon.ico如果存在这样的文件,它将自动用作应用程序的favicon。

28.1.8路径匹配和内容协商

Spring MVC可以通过查看请求路径并将其与应用程序中定义的映射相匹配(例如,关于Controller方法的@GetMapping注释),将传入的HTTP请求映射到处理程序。

Spring Boot默认情况下选择禁用后缀模式匹配,这意味着像"GET /projects/spring-boot.json"这样的请求将不会与@GetMapping("/projects/spring-boot")映射匹配。这被认为是Spring MVC应用程序最佳实践对于没有发送正确“接受”请求标头的HTTP客户端,此功能在过去主要有用; 我们需要确保将正确的内容类型发送给客户端。如今,内容协商更加可靠。

还有其他方法可以处理不一致发送正确“接受”请求标头的HTTP客户端。我们可以使用查询参数来确保"GET /projects/spring-boot?format=json"之类的请求映射到@GetMapping("/projects/spring-boot"),而不是使用后缀匹配:

spring.mvc.contentnegotiation.favor-parameter=true

# We can change the parameter name, which is "format" by default:
# spring.mvc.contentnegotiation.parameter-name=myparam

# We can also register additional file extensions/media types with:
spring.mvc.contentnegotiation.media-types.markdown=text/markdown

如果您了解警告并仍希望您的应用程序使用后缀模式匹配,则需要以下配置:

spring.mvc.contentnegotiation.favor-path-extension=true
spring.mvc.pathmatch.use-suffix-pattern=true

或者,不是打开所有后缀模式,而是仅支持已注册的后缀模式更安全:

spring.mvc.contentnegotiation.favor-path-extension=true
spring.mvc.pathmatch.use-registered-suffix-pattern=true

# You can also register additional file extensions/media types with:
# spring.mvc.contentnegotiation.media-types.adoc=text/asciidoc

28.1.9 ConfigurableWebBindingInitializer

Spring MVC使用WebBindingInitializer为特定请求初始化WebDataBinder如果您创建自己的ConfigurableWebBindingInitializer @Bean,Spring Boot会自动配置Spring MVC以使用它。

28.1.10模板引擎

除REST Web服务外,您还可以使用Spring MVC来提供动态HTML内容。Spring MVC支持各种模板技术,包括Thymeleaf,FreeMarker和JSP。此外,许多其他模板引擎包括他们自己的Spring MVC集成。

Spring Boot包括对以下模板引擎的自动配置支持:

[提示]提示

如果可能,应该避免使用JSP。将它们与嵌入式servlet容器一起使用时有几个 已知的限制

当您使用其中一个模板引擎和默认配置时,您的模板将从src/main/resources/templates自动获取。

[提示]提示

根据您运行应用程序的方式,IntelliJ IDEA以不同方式对类路径进行排序。从主方法在IDE中运行应用程序会产生与使用Maven或Gradle或其打包的jar运行应用程序时不同的顺序。这可能导致Spring Boot无法在类路径上找到模板。如果遇到此问题,可以在IDE中重新排序类路径,以便首先放置模块的类和资源。或者,您可以配置模板前缀以搜索类路径上的每个templates目录,如下所示:classpath*:/templates/

28.1.11错误处理

默认情况下,Spring Boot提供/error映射,以合理的方式处理所有错误,并在servlet容器中注册为“全局”错误页面。对于计算机客户端,它会生成一个JSON响应,其中包含错误,HTTP状态和异常消息的详细信息。对于浏览器客户端,有一个“whitelabel”错误视图,以HTML格式呈现相同的数据(要自定义它,添加一个解析为errorView)。要完全替换默认行为,您可以实现ErrorController并注册该类型的bean定义或添加bean类型ErrorAttributes以使用现有机制但替换内容。

[提示]提示

BasicErrorController可以用作自定义ErrorController的基类。如果要为新内容类型添加处理程序,则此功能特别有用(默认情况下,专门处理text/html并为其他所有内容提供后备)。为此,请扩展BasicErrorController,添加具有produces属性的@RequestMapping的公共方法,并创建新类型的bean。

您还可以定义使用@ControllerAdvice注释的类,以自定义要为特定控制器和/或异常类型返回的JSON文档,如以下示例所示:

@ControllerAdvice(basePackageClasses = AcmeController.class)
public class AcmeControllerAdvice extends ResponseEntityExceptionHandler {

	@ExceptionHandler(YourException.class)
	@ResponseBody
	ResponseEntity<?> handleControllerException(HttpServletRequest request, Throwable ex) {
		HttpStatus status = getStatus(request);
		return new ResponseEntity<>(new CustomErrorType(status.value(), ex.getMessage()), status);
	}

	private HttpStatus getStatus(HttpServletRequest request) {
		Integer statusCode = (Integer) request.getAttribute("javax.servlet.error.status_code");
		if (statusCode == null) {
			return HttpStatus.INTERNAL_SERVER_ERROR;
		}
		return HttpStatus.valueOf(statusCode);
	}

}

在前面的示例中,如果YourException在与AcmeController相同的包中定义的控制器抛出,则使用CustomErrorType POJO的JSON表示而不是ErrorAttributes表示。

自定义错误页面

如果要显示给定状态代码的自定义HTML错误页面,可以将文件添加到/error文件夹。错误页面可以是静态HTML(即,添加到任何静态资源文件夹下),也可以使用模板构建。文件名应该是确切的状态代码或系列掩码。

例如,要将404映射到静态HTML文件,您的文件夹结构将如下所示:

src/
 +- main/
     +- java/
     |   + <source code>
     +- resources/
         +- public/
             +- error/
             |   +- 404.html
             +- <other public assets>

要使用FreeMarker模板映射所有5xx错误,您的文件夹结构如下:

src/
 +- main/
     +- java/
     |   + <source code>
     +- resources/
         +- templates/
             +- error/
             |   +- 5xx.ftl
             +- <other templates>

对于更复杂的映射,您还可以添加实现ErrorViewResolver接口的beans,如以下示例所示:

public class MyErrorViewResolver implements ErrorViewResolver {

	@Override
	public ModelAndView resolveErrorView(HttpServletRequest request,
			HttpStatus status, Map<String, Object> model) {
		// Use the request or status to optionally return a ModelAndView
		return ...
	}

}

您还可以使用常规的Spring MVC功能,例如 @ExceptionHandler方法@ControllerAdviceErrorController然后选择任何未处理的异常。

将错误页面映射到Spring MVC之外

对于不使用Spring MVC的应用程序,可以使用ErrorPageRegistrar接口直接注册ErrorPages这种抽象直接与底层嵌入式servlet容器一起工作,即使你没有Spring MVC DispatcherServlet也可以工作。

@Bean
public ErrorPageRegistrar errorPageRegistrar(){
	return new MyErrorPageRegistrar();
}

// ...

private static class MyErrorPageRegistrar implements ErrorPageRegistrar {

	@Override
	public void registerErrorPages(ErrorPageRegistry registry) {
		registry.addErrorPages(new ErrorPage(HttpStatus.BAD_REQUEST, "/400"));
	}

}
[注意]注意

如果你注册ErrorPage的路径最终由Filter处理(如某些非Spring网页框架,如Jersey和Wicket),那么Filter必须显式注册为ERROR调度程序,如以下示例所示:

@Bean
public FilterRegistrationBean myFilter() {
	FilterRegistrationBean registration = new FilterRegistrationBean();
	registration.setFilter(new MyFilter());
	...
	registration.setDispatcherTypes(EnumSet.allOf(DispatcherType.class));
	return registration;
}

请注意,默认值FilterRegistrationBean不包括ERROR调度程序类型。

小心:当部署到servlet容器时,Spring Boot使用其错误页面过滤器将具有错误状态的请求转发到相应的错误页面。如果尚未提交响应,则只能将请求转发到正确的错误页面。缺省情况下,WebSphere Application Server 8.0及更高版本在成功完成servlet的服务方法后提交响应。您应该通过将com.ibm.ws.webcontainer.invokeFlushAfterService设置为false来禁用此行为。

28.1.12 Spring HATEOAS

如果您开发使用超媒体的RESTful API,Spring Boot为Spring HATEOAS提供了适用于大多数应用程序的自动配置。自动配置取代了使用@EnableHypermediaSupport并注册多个beans以简化基于超媒体的应用程序的需求,包括LinkDiscoverers(用于客户端支持)和ObjectMapper配置为正确地将响应编组到所需的表示中。ObjectMapper是通过设置各种spring.jackson.*属性或(如果存在)Jackson2ObjectMapperBuilder bean来自定义的。

您可以使用@EnableHypermediaSupport控制Spring HATEOAS的配置。请注意,这样做会禁用前面描述的ObjectMapper自定义。

28.1.13 CORS支持

跨源资源共享 (CORS)是大多数浏览器实现 W3C规范,允许您以灵活的方式指定授权何种跨域请求,而不是使用一些不太安全且功能较弱的方法,如IFRAME或JSONP。

从版本4.2开始,Spring MVC 支持CORS 在Spring Boot应用程序中使用带有 注释的控制器方法CORS配置@CrossOrigin不需要任何特定配置。 可以通过使用自定义的addCorsMappings(CorsRegistry)方法注册WebMvcConfigurer bean来定义全局CORS配置,如以下示例所示:

@Configuration
public class MyConfiguration {

	@Bean
	public WebMvcConfigurer corsConfigurer() {
		return new WebMvcConfigurer() {
			@Override
			public void addCorsMappings(CorsRegistry registry) {
				registry.addMapping("/api/**");
			}
		};
	}
}

28.2“Spring WebFlux框架”

Spring WebFlux是Spring Framework 5.0中引入的新的响应式Web框架。与Spring MVC不同,它不需要Servlet API,完全异步且无阻塞,并 通过Reactor项目实现Reactive Streams规范

Spring WebFlux有两种版本:功能和注释。基于注释的注释非常接近Spring MVC模型,如以下示例所示:

@RestController
@RequestMapping("/users")
public class MyRestController {

	@GetMapping("/{user}")
	public Mono<User> getUser(@PathVariable Long user) {
		// ...
	}

	@GetMapping("/{user}/customers")
	public Flux<Customer> getUserCustomers(@PathVariable Long user) {
		// ...
	}

	@DeleteMapping("/{user}")
	public Mono<User> deleteUser(@PathVariable Long user) {
		// ...
	}

}

“WebFlux.fn”是功能变体,它将路由配置与请求的实际处理分开,如以下示例所示:

@Configuration
public class RoutingConfiguration {

	@Bean
	public RouterFunction<ServerResponse> monoRouterFunction(UserHandler userHandler) {
		return route(GET("/{user}").and(accept(APPLICATION_JSON)), userHandler::getUser)
				.andRoute(GET("/{user}/customers").and(accept(APPLICATION_JSON)), userHandler::getUserCustomers)
				.andRoute(DELETE("/{user}").and(accept(APPLICATION_JSON)), userHandler::deleteUser);
	}

}

@Component
public class UserHandler {

	public Mono<ServerResponse> getUser(ServerRequest request) {
		// ...
	}

	public Mono<ServerResponse> getUserCustomers(ServerRequest request) {
		// ...
	}

	public Mono<ServerResponse> deleteUser(ServerRequest request) {
		// ...
	}
}

WebFlux是Spring框架的一部分,详细信息可在其 参考文档中找到

[提示]提示

您可以根据需要定义尽可能多的RouterFunction beans来模块化路由器的定义。如果您需要应用优先级,可以订购Beans。

要开始使用,请将spring-boot-starter-webflux模块添加到您的应用程序中。

[注意]注意

在您的应用程序中添加spring-boot-starter-webspring-boot-starter-webflux模块会导致Spring Boot自动配置Spring MVC,而不是WebFlux。选择此行为是因为许多Spring开发人员将spring-boot-starter-webflux添加到他们的Spring MVC应用程序以使用被动WebClient您仍然可以通过将所选应用程序类型设置为SpringApplication.setWebApplicationType(WebApplicationType.REACTIVE)来强制执行您的选择。

28.2.1 Spring WebFlux自动配置

Spring Boot为Spring WebFlux提供自动配置,适用于大多数应用程序。

自动配置在Spring的默认值之上添加了以下功能:

如果你想保留Spring Boot WebFlux功能,并且想要添加额外的 WebFlux配置,你可以添加自己的@ConfigurationWebFluxConfigurer没有 @EnableWebFlux

如果您想完全控制Spring WebFlux,可以使用@EnableWebFlux添加自己的@Configuration注释。

28.2.2带有HttpMessageReaders和HttpMessageWriters的HTTP编解码器

Spring WebFlux使用HttpMessageReaderHttpMessageWriter接口转换HTTP请求和响应。通过查看类路径中可用的库,它们配置为CodecConfigurer以具有合理的默认值。

Spring Boot通过使用CodecCustomizer实例进一步自定义。例如,spring.jackson.*配置密钥应用于Jackson编解码器。

如果需要添加或自定义编解码器,可以创建自定义CodecCustomizer组件,如以下示例所示:

import org.springframework.boot.web.codec.CodecCustomizer;

@Configuration
public class MyConfiguration {

	@Bean
	public CodecCustomizer myCodecCustomizer() {
		return codecConfigurer -> {
			// ...
		}
	}

}

您还可以利用Boot的自定义JSON序列化程序和反序列化程序

28.2.3静态内容

默认情况下,Spring Boot从类路径中名为/static(或/public/resources/META-INF/resources)的目录中提供静态内容。它使用来自Spring WebFlux的ResourceWebHandler,以便您可以通过添加自己的WebFluxConfigurer并覆盖addResourceHandlers方法来修改该行为。

默认情况下,资源映射到/**,但您可以通过设置spring.webflux.static-path-pattern属性来调整它。例如,将所有资源重新定位到/resources/**可以实现如下:

spring.webflux.static-path-pattern=/resources/**

您还可以使用spring.resources.static-locations自定义静态资源位置。这样做会将默认值替换为目录位置列表。如果这样做,默认的欢迎页面检测会切换到您的自定义位置。因此,如果您在启动时的任何位置都有index.html,那么它就是应用程序的主页。

除了前面列出的“标准”静态资源位置之外,还为Webjars内容制作了一个特例如果文件以Webjars格式打包,那么具有/webjars/**中路径的任何资源都将从jar文件中提供。

[提示]提示

Spring WebFlux应用程序并不严格依赖于Servlet API,因此它们不能作为war文件部署,也不能使用src/main/webapp目录。

28.2.4模板引擎

除REST Web服务外,您还可以使用Spring WebFlux来提供动态HTML内容。Spring WebFlux支持各种模板技术,包括Thymeleaf,FreeMarker和Mustache。

Spring Boot包括对以下模板引擎的自动配置支持:

当您使用其中一个模板引擎和默认配置时,您的模板将从src/main/resources/templates自动获取。

28.2.5错误处理

Spring Boot提供WebExceptionHandler以合理的方式处理所有错误。它在处理顺序中的位置紧接在WebFlux提供的处理程序之前,这被认为是最后的。对于计算机客户端,它会生成一个JSON响应,其中包含错误,HTTP状态和异常消息的详细信息。对于浏览器客户端,有一个“whitelabel”错误处理程序,它以HTML格式呈现相同的数据。您还可以提供自己的HTML模板来显示错误(请参阅 下一节)。

自定义此功能的第一步通常涉及使用现有机制,但替换或扩充错误内容。为此,您可以添加bean类型ErrorAttributes

要更改错误处理行为,您可以实现ErrorWebExceptionHandler并注册该类型的bean定义。因为WebExceptionHandler非常低级,Spring Boot还提供了一个方便的AbstractErrorWebExceptionHandler来让你以WebFlux函数方式处理错误,如下例所示:

public class CustomErrorWebExceptionHandler extends AbstractErrorWebExceptionHandler {

	// Define constructor here

	@Override
	protected RouterFunction<ServerResponse> getRoutingFunction(ErrorAttributes errorAttributes) {

		return RouterFunctions
				.route(aPredicate, aHandler)
				.andRoute(anotherPredicate, anotherHandler);
	}

}

要获得更完整的图片,您还可以直接继承DefaultErrorWebExceptionHandler并覆盖特定方法。

自定义错误页面

如果要显示给定状态代码的自定义HTML错误页面,可以将文件添加到/error文件夹。错误页面可以是静态HTML(即,添加到任何静态资源文件夹下)或使用模板构建。文件名应该是确切的状态代码或系列掩码。

例如,要将404映射到静态HTML文件,您的文件夹结构将如下所示:

src/
 +- main/
     +- java/
     |   + <source code>
     +- resources/
         +- public/
             +- error/
             |   +- 404.html
             +- <other public assets>

要使用Mustache模板映射所有5xx错误,您的文件夹结构如下:

src/
 +- main/
     +- java/
     |   + <source code>
     +- resources/
         +- templates/
             +- error/
             |   +- 5xx.mustache
             +- <other templates>

28.2.6 Web过滤器

Spring WebFlux提供了一个WebFilter接口,可以实现过滤HTTP请求 - 响应交换。在应用程序上下文中找到的WebFilter beans将自动用于过滤每个交换。

如果过滤器的顺序很重要,则可以实现Ordered或使用@Order进行注释。Spring Boot自动配置可以为您配置Web过滤器。执行此操作时,将使用下表中显示的订单:

网络过滤器订购

MetricsWebFilter

Ordered.HIGHEST_PRECEDENCE + 1

WebFilterChainProxy (Spring Security)

-100

HttpTraceWebFilter

Ordered.LOWEST_PRECEDENCE - 10

28.3 JAX-RS和Jersey

如果您更喜欢REST端点的JAX-RS编程模型,则可以使用其中一个可用的实现而不是Spring MVC。JerseyApache CXF开箱即用。CXF要求您在应用程序上下文中将ServletFilter注册为@BeanJersey具有一些本地Spring支持,因此我们还在Spring Boot中为其提供了自动配置支持以及启动器。

要开始使用Jersey,请将spring-boot-starter-jersey作为依赖项包含在内,然后需要一个@Bean类型ResourceConfig,在其中注册所有端点,如以下示例所示:

@Component
public class JerseyConfig extends ResourceConfig {

	public JerseyConfig() {
		register(Endpoint.class);
	}

}
[警告]警告

Jersey对扫描可执行档案的支持相当有限。例如,它无法扫描完全可执行jar文件中的包中的端点,也无法在运行可执行war文件时扫描WEB-INF/classes中的端点为避免此限制,不应使用packages方法,并且应使用register方法单独注册端点,如上例所示。

对于更高级的自定义,您还可以注册实现ResourceConfigCustomizer的任意数量的beans。

所有已注册的端点都应为@Components,并带有HTTP资源注释(@GET和其他),如以下示例所示:

@Component
@Path("/hello")
public class Endpoint {

	@GET
	public String message() {
		return "Hello";
	}

}

由于Endpoint是Spring @Component,其生命周期由Spring管理,您可以使用@Autowired注释注入依赖项并使用@Value注释注入外部组态。默认情况下,Jersey servlet已注册并映射到/*您可以通过将@ApplicationPath添加到ResourceConfig来更改映射。

默认情况下,Jersey设置为名为jerseyServletRegistrationServletRegistrationBean类型的@Bean中的Servlet。默认情况下,servlet是懒惰地初始化的,但您可以通过设置spring.jersey.servlet.load-on-startup来自定义该行为。您可以通过创建一个具有相同名称的自己来禁用或覆盖bean。您也可以通过设置spring.jersey.type=filter来使用过滤器而不是servlet(在这种情况下,要替换或覆盖的@BeanjerseyFilterRegistration)。过滤器的@Order,您可以使用spring.jersey.filter.order进行设置。通过使用spring.jersey.init.*指定属性映射,可以为servlet和过滤器注册提供init参数。

有一个Jersey样本,以便您可以看到如何设置。

28.4嵌入式Servlet容器支持

Spring Boot包括对嵌入式TomcatJettyUndertow服务器的支持。大多数开发人员使用适当的“Starter”来获取完全配置的实例。默认情况下,嵌入式服务器侦听端口8080上的HTTP请求。

[警告]警告

如果您选择在CentOS上使用Tomcat ,请注意,默认情况下,临时目录用于存储已编译的JSP,文件上载等。当您的应用程序运行时,tmpwatch可能会删除此目录,从而导致失败。要避免此行为,您可能希望自定义tmpwatch配置,以便不删除tomcat.*目录或配置server.tomcat.basedir,以便嵌入式Tomcat使用不同的位置。

28.4.1 Servlet,过滤器和监听器

使用嵌入式servlet容器时,可以使用Spring beans或扫描Servlet组件,从Servlet规范中注册servlet,过滤器和所有侦听器(例如HttpSessionListener)。

注册Servlet,过滤器和监听器Spring Beans

在嵌入式容器中注册了Spring bean的任何ServletFilter或servlet *Listener实例。如果要在配置期间引用application.properties中的值,这可能特别方便。

默认情况下,如果上下文仅包含一个Servlet,则它将映射到/在多个servlet beans的情况下,bean名称用作路径前缀。过滤器映射到/*

如果基于约定的映射不够灵活,您可以使用ServletRegistrationBeanFilterRegistrationBeanServletListenerRegistrationBean类进行完全控制。

Spring Boot附带了许多可以定义Filter beans的自动配置。以下是过滤器及其各自顺序的一些示例(较低的顺序值表示较高的优先级):

Servlet过滤器订购

OrderedCharacterEncodingFilter

Ordered.HIGHEST_PRECEDENCE

WebMvcMetricsFilter

Ordered.HIGHEST_PRECEDENCE + 1

ErrorPageFilter

Ordered.HIGHEST_PRECEDENCE + 1

HttpTraceFilter

Ordered.LOWEST_PRECEDENCE - 10

将Filter beans无序放置通常是安全的。

如果需要特定订单,则应避免在Ordered.HIGHEST_PRECEDENCE处配置读取请求正文的筛选器,因为它可能违反应用程序的字符编码配置。如果Servlet过滤器包装请求,则应使用小于或等于OrderedFilter.REQUEST_WRAPPER_FILTER_MAX_ORDER的顺序进行配置。

28.4.2 Servlet上下文初始化

嵌入式servlet容器不直接执行Servlet 3.0+ javax.servlet.ServletContainerInitializer接口或Spring的org.springframework.web.WebApplicationInitializer接口。这是一项有意的设计决策,旨在降低设计在战争中运行的第三方图书馆可能会破坏Spring Boot应用程序的风险。

如果需要在Spring Boot应用程序中执行servlet上下文初始化,则应注册实现org.springframework.boot.web.servlet.ServletContextInitializer接口的bean。onStartup方法提供对ServletContext的访问,如果需要,可以很容易地用作现有WebApplicationInitializer的适配器。

扫描Servlet,过滤器和侦听器

使用嵌入式容器时,可以使用@ServletComponentScan启用使用@WebServlet@WebFilter@WebListener注释的类的自动注册。

[提示]提示

@ServletComponentScan对独立容器没有影响,其中使用容器的内置发现机制。

28.4.3 ServletWebServerApplicationContext

在引擎盖下,Spring Boot使用不同类型的ApplicationContext来支持嵌入式servlet容器。ServletWebServerApplicationContextWebApplicationContext的一种特殊类型,它通过搜索单个ServletWebServerFactory bean来引导自己。通常会自动配置TomcatServletWebServerFactoryJettyServletWebServerFactoryUndertowServletWebServerFactory

[注意]注意

您通常不需要了解这些实现类。大多数应用程序都是自动配置的,并且代表您创建了相应的ApplicationContextServletWebServerFactory

28.4.4自定义嵌入式Servlet容器

可以使用Spring Environment属性配置公共servlet容器设置。通常,您将在application.properties文件中定义属性。

常用服务器设置包括:

  • 网络设置:侦听传入HTTP请求的端口(server.port),绑定到server.address的接口地址,依此类推。
  • 会话设置:会话是持久的(server.servlet.session.persistence),会话超时(server.servlet.session.timeout),会话数据的位置(server.servlet.session.store-dir)和会话cookie配置(server.servlet.session.cookie.*)。
  • 错误管理:错误页面的位置(server.error.path)等。
  • SSL
  • HTTP压缩

Spring Boot尝试尽可能多地暴露常见设置,但这并非总是可行。对于这些情况,专用命名空间提供特定于服务器的自定义(请参阅server.tomcatserver.undertow)。例如, 可以使用嵌入式servlet容器的特定功能配置访问日志

[提示]提示

请参阅 ServerProperties课程以获取完整列表。

程序化定制

如果需要以编程方式配置嵌入式servlet容器,可以注册实现WebServerFactoryCustomizer接口的Spring bean。WebServerFactoryCustomizer提供对ConfigurableServletWebServerFactory的访问,其中包括许多自定义setter方法。以下示例以编程方式设置端口:

import org.springframework.boot.web.server.WebServerFactoryCustomizer;
import org.springframework.boot.web.servlet.server.ConfigurableServletWebServerFactory;
import org.springframework.stereotype.Component;

@Component
public class CustomizationBean implements WebServerFactoryCustomizer<ConfigurableServletWebServerFactory> {

	@Override
	public void customize(ConfigurableServletWebServerFactory server) {
		server.setPort(9000);
	}

}
[注意]注意

TomcatServletWebServerFactoryJettyServletWebServerFactoryUndertowServletWebServerFactoryConfigurableServletWebServerFactory的专用变体,分别为Tomcat,Jetty和Undertow提供了额外的自定义setter方法。

直接自定义ConfigurableServletWebServerFactory

如果前面的自定义技术太有限,您可以自己注册TomcatServletWebServerFactoryJettyServletWebServerFactoryUndertowServletWebServerFactory bean。

@Bean
public ConfigurableServletWebServerFactory webServerFactory() {
	TomcatServletWebServerFactory factory = new TomcatServletWebServerFactory();
	factory.setPort(9000);
	factory.setSessionTimeout(10, TimeUnit.MINUTES);
	factory.addErrorPages(new ErrorPage(HttpStatus.NOT_FOUND, "/notfound.html"));
	return factory;
}

为许多配置选项提供了Setter。如果您需要做一些更具异国情调的事情,还会提供一些受保护的方法“挂钩”。有关详细信息,请参阅 源代码文档

28.4.5 JSP限制

运行使用嵌入式servlet容器的Spring Boot应用程序(并打包为可执行存档)时,JSP支持存在一些限制。

  • 使用Jetty和Tomcat,如果使用war包装,它应该可以工作。使用java -jar启动时,可执行战争将起作用,并且还可以部署到任何标准容器。使用可执行jar时不支持JSP。
  • Undertow不支持JSP。
  • 创建自定义error.jsp页面不会覆盖错误处理的默认视图 应该使用自定义错误页面

有一个JSP示例,以便您可以看到如何设置。

28.5嵌入式Reactive Server支持

Spring Boot包括对以下嵌入式响应式Web服务器的支持:Reactor Netty,Tomcat,Jetty和Undertow。大多数开发人员使用适当的“Starter”来获取完全配置的实例。默认情况下,嵌入式服务器在端口8080上侦听HTTP请求。

28.6 Reactive Server资源配置

在自动配置Reactor Netty或Jetty服务器时,Spring Boot将创建特定的beans,它将为服务器实例提供HTTP资源:ReactorResourceFactoryJettyResourceFactory

默认情况下,这些资源也将与Reactor Netty和Jetty客户端共享以获得最佳性能,具体如下:

  • 相同的技术用于服务器和客户端
  • 客户端实例使用由Spring Boot自动配置的WebClient.Builder bean构建

开发人员可以通过提供自定义ReactorResourceFactoryJettyResourceFactory bean覆盖Jetty和Reactor Netty的资源配置 - 这将应用于客户端和服务器。

您可以在WebClient Runtime部分中了解有关客户端资源配置的更多信息

29.安全

如果Spring安全性在类路径上,则默认情况下Web应用程序是安全的。Spring Boot依赖于Spring安全性的内容协商策略来确定是使用httpBasic还是formLogin要向Web应用程序添加方法级安全性,您还可以使用所需设置添加@EnableGlobalMethodSecurity其他信息可在 Spring安全参考指南中找到

默认UserDetailsService只有一个用户。用户名为user,密码是随机的,在应用程序启动时以INFO级别打印,如以下示例所示:

Using generated security password: 78fa095d-3f4c-48b1-ad50-e24c31d5cf35
[注意]注意

如果您对日志记录配置进行微调,请确保将org.springframework.boot.autoconfigure.security类别设置为记录INFO级别的消息。否则,不会打印默认密码。

您可以通过提供spring.security.user.namespring.security.user.password来更改用户名和密码。

您在Web应用程序中默认获得的基本功能包括:

  • UserDetailsService(对于WebFlux应用程序,为ReactiveUserDetailsService)bean具有内存存储,单个用户具有生成的密码(请参阅 SecurityProperties.User 用户的属性)。
  • 基于表单的登录或HTTP基本安全性(取决于Content-Type),用于整个应用程序(如果执行器在类路径上,则包括执行器端点)。
  • 用于发布身份验证事件的DefaultAuthenticationEventPublisher

您可以为其添加bean来提供不同的AuthenticationEventPublisher

29.1 MVC安全性

默认安全配置在SecurityAutoConfigurationUserDetailsServiceAutoConfiguration中实现。SecurityAutoConfiguration导入用于Web安全的SpringBootWebSecurityConfiguration和用于配置身份验证的UserDetailsServiceAutoConfiguration,这在非Web应用程序中也是相关的。要完全关闭默认Web应用程序安全配置,您可以添加bean类型WebSecurityConfigurerAdapter(这样做不会禁用UserDetailsService配置或Actuator的安全性)。

要同时关闭UserDetailsService配置,您可以添加bean类型UserDetailsServiceAuthenticationProviderAuthenticationManagerSpring Boot示例中有几个安全应用程序可以帮助您开始使用常见用例。

可以通过添加自定义WebSecurityConfigurerAdapter来覆盖访问规则。Spring Boot提供了便捷方法,可用于覆盖执行器端点和静态资源的访问规则。EndpointRequest可用于创建基于management.endpoints.web.base-path属性的RequestMatcherPathRequest可用于为常用位置的资源创建RequestMatcher

29.2 WebFlux安全性

与Spring MVC应用程序类似,您可以通过添加spring-boot-starter-security依赖项来保护WebFlux应用程序。默认安全配置在ReactiveSecurityAutoConfigurationUserDetailsServiceAutoConfiguration中实现。ReactiveSecurityAutoConfiguration导入用于Web安全的WebFluxSecurityConfiguration和用于配置身份验证的UserDetailsServiceAutoConfiguration,这在非Web应用程序中也是相关的。要完全关闭默认Web应用程序安全配置,您可以添加bean类型WebFilterChainProxy(这样做不会禁用UserDetailsService配置或执行器的安全性)。

要同时关闭UserDetailsService配置,您可以添加bean类型ReactiveUserDetailsServiceReactiveAuthenticationManager

可以通过添加自定义SecurityWebFilterChain来配置访问规则。Spring Boot提供了便捷方法,可用于覆盖执行器端点和静态资源的访问规则。EndpointRequest可用于创建基于management.endpoints.web.base-path属性的ServerWebExchangeMatcher

PathRequest可用于为常用位置的资源创建ServerWebExchangeMatcher

例如,您可以通过添加以下内容来自定义安全配置:

@Bean
public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {
	return http
		.authorizeExchange()
			.matchers(PathRequest.toStaticResources().atCommonLocations()).permitAll()
			.pathMatchers("/foo", "/bar")
				.authenticated().and()
			.formLogin().and()
		.build();
}

29.3 OAuth2

OAuth2是Spring支持的广泛使用的授权框架。

29.3.1客户

如果您的类路径上有spring-security-oauth2-client,则可以利用一些自动配置来轻松设置OAuth2 / Open ID Connect客户端。此配置使用OAuth2ClientProperties下的属性。相同的属性适用于servlet和反应应用程序。

您可以在spring.security.oauth2.client前缀下注册多个OAuth2客户端和提供商,如以下示例所示:

spring.security.oauth2.client.registration.my-client-1.client-id=abcd
spring.security.oauth2.client.registration.my-client-1.client-secret=password
spring.security.oauth2.client.registration.my-client-1.client-name=Client for user scope
spring.security.oauth2.client.registration.my-client-1.provider=my-oauth-provider
spring.security.oauth2.client.registration.my-client-1.scope=user
spring.security.oauth2.client.registration.my-client-1.redirect-uri-template=http://my-redirect-uri.com
spring.security.oauth2.client.registration.my-client-1.client-authentication-method=basic
spring.security.oauth2.client.registration.my-client-1.authorization-grant-type=authorization_code

spring.security.oauth2.client.registration.my-client-2.client-id=abcd
spring.security.oauth2.client.registration.my-client-2.client-secret=password
spring.security.oauth2.client.registration.my-client-2.client-name=Client for email scope
spring.security.oauth2.client.registration.my-client-2.provider=my-oauth-provider
spring.security.oauth2.client.registration.my-client-2.scope=email
spring.security.oauth2.client.registration.my-client-2.redirect-uri-template=http://my-redirect-uri.com
spring.security.oauth2.client.registration.my-client-2.client-authentication-method=basic
spring.security.oauth2.client.registration.my-client-2.authorization-grant-type=authorization_code

spring.security.oauth2.client.provider.my-oauth-provider.authorization-uri=http://my-auth-server/oauth/authorize
spring.security.oauth2.client.provider.my-oauth-provider.token-uri=http://my-auth-server/oauth/token
spring.security.oauth2.client.provider.my-oauth-provider.user-info-uri=http://my-auth-server/userinfo
spring.security.oauth2.client.provider.my-oauth-provider.user-info-authentication-method=header
spring.security.oauth2.client.provider.my-oauth-provider.jwk-set-uri=http://my-auth-server/token_keys
spring.security.oauth2.client.provider.my-oauth-provider.user-name-attribute=name

对于支持OpenID Connect发现的 OpenID Connect提供程序,可以进一步简化配置。提供程序需要配置issuer-uri,这是它声明为其颁发者标识符的URI。例如,如果提供的issuer-uri为“https://example.com”,则会将OpenID Provider Configuration Request设置为“https://example.com/.well-known/openid-configuration”。结果预计为OpenID Provider Configuration Response以下示例显示如何使用issuer-uri配置OpenID Connect Provider:

spring.security.oauth2.client.provider.oidc-provider.issuer-uri=https://dev-123456.oktapreview.com/oauth2/default/

默认情况下,Spring安全性OAuth2LoginAuthenticationFilter仅处理与/login/oauth2/code/*匹配的网址。如果要自定义redirect-uri以使用其他模式,则需要提供配置以处理该自定义模式。例如,对于servlet应用程序,您可以添加类似于以下内容的WebSecurityConfigurerAdapter

public class OAuth2LoginSecurityConfig extends WebSecurityConfigurerAdapter {

	@Override
	protected void configure(HttpSecurity http) throws Exception {
		http
			.authorizeRequests()
				.anyRequest().authenticated()
				.and()
			.oauth2Login()
				.redirectionEndpoint()
					.baseUri("/custom-callback");
	}
}

OAuth2共同提供者的客户注册

对于常见的OAuth2和OpenID提供商,包括Google,Github,Facebook和Okta,我们提供了一组提供商默认值(分别为googlegithubfacebookokta )。

如果您不需要自定义这些提供程序,则可以将provider属性设置为您需要推断默认值的属性。此外,如果客户端注册的密钥与默认支持的提供者匹配,则Spring Boot也会推断出。

换句话说,以下示例中的两个配置使用Google提供程序:

spring.security.oauth2.client.registration.my-client.client-id=abcd
spring.security.oauth2.client.registration.my-client.client-secret=password
spring.security.oauth2.client.registration.my-client.provider=google

spring.security.oauth2.client.registration.google.client-id=abcd
spring.security.oauth2.client.registration.google.client-secret=password

29.3.2资源服务器

如果类路径上有spring-security-oauth2-resource-server,只要指定了JWK Set URI或OIDC Issuer URI,Spring Boot就可以设置OAuth2资源服务器,如以下示例所示:

spring.security.oauth2.resourceserver.jwt.jwk-set-uri=https://example.com/oauth2/default/v1/keys
spring.security.oauth2.resourceserver.jwt.issuer-uri=https://dev-123456.oktapreview.com/oauth2/default/

相同的属性适用于servlet和反应应用程序。

或者,您可以为servlet应用程序定义自己的JwtDecoder bean,或者为响应式应用程序定义ReactiveJwtDecoder

29.3.3授权服务器

目前,Spring安全性不支持实施OAuth 2.0授权服务器。但是,此功能可从Spring安全OAuth项目获得,该项目最终将完全被Spring安全性取代。在此之前,您可以使用spring-security-oauth2-autoconfigure模块轻松设置OAuth 2.0授权服务器; 请参阅其文档以获取说明

29.4执行器安全性

出于安全考虑,默认情况下禁用/health/info以外的所有执行器。management.endpoints.web.exposure.include属性可用于启用执行器。

如果Spring安全性在类路径上且没有其他WebSecurityConfigurerAdapter存在,则/health/info以外的所有执行器都由Spring Boot自动配置保护。如果您定义自定义WebSecurityConfigurerAdapter,则Spring Boot自动配置将退回,您将完全控制执行器访问规则。

[注意]注意

在设置management.endpoints.web.exposure.include之前,请确保暴露的执行器不包含敏感信息和/或通过将它们放在防火墙后面或通过Spring安全性等方式进行保护。

29.4.1跨站点请求伪造保护

由于Spring Boot依赖于Spring安全性的默认值,因此默认情况下会启用CSRF保护。这意味着当使用默认安全配置时,需要POST(关闭和记录器端点),PUTDELETE的执行器端点将获得403禁止错误。

[注意]注意

我们建议仅在创建非浏览器客户端使用的服务时才完全禁用CSRF保护。

有关CSRF保护的其他信息,请参阅 Spring安全参考指南

30.使用SQL数据库

Spring框架提供用于使用JdbcTemplate完成“对象关系映射”的技术,如休眠使用SQL数据库,从直接JDBC访问广泛的支持。Spring数据提供了更多级别的功能:直接从接口创建Repository实现,并使用约定从方法名称生成查询。

30.1配置数据源

Java的javax.sql.DataSource接口提供了一种使用数据库连接的标准方法。传统上,'DataSource'使用URL以及一些凭据来建立数据库连接。

[提示]提示

有关更多高级示例,请参阅“操作方法”部分,通常是为了完全控制DataSource的配置。

30.1.1嵌入式数据库支持

通过使用内存中嵌入式数据库来开发应用程序通常很方便。显然,内存数据库不提供持久存储。您需要在应用程序启动时填充数据库,并准备在应用程序结束时丢弃数据。

[提示]提示

“操作方法”部分包含有关如何初始化数据库的部分

Spring Boot可以自动配置嵌入式H2HSQLDerby数据库。您无需提供任何连接URL。您只需要包含要使用的嵌入式数据库的构建依赖项。

[注意]注意

如果您在测试中使用此功能,您可能会注意到整个测试套件都会重复使用相同的数据库,无论您使用的应用程序上下文的数量如何。如果要确保每个上下文都有一个单独的嵌入式数据库,则应将spring.datasource.generate-unique-name设置为true

例如,典型的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禁用数据库的自动关闭允许Spring Boot控制数据库何时关闭,从而确保在不再需要访问数据库时发生这种情况。

30.1.2连接到生产数据库

也可以使用池DataSource自动配置生产数据库连接。Spring Boot使用以下算法选择特定实现:

  1. 我们更喜欢HikariCP的性能和并发性。如果HikariCP可用,我们总是选择它。
  2. 否则,如果Tomcat池DataSource可用,我们将使用它。
  3. 如果HikariCP和Tomcat池化数据源都不可用,并且 Commons DBCP2可用,我们就会使用它。

如果您使用spring-boot-starter-jdbcspring-boot-starter-data-jpa“starters”,则会自动获得HikariCP的依赖关系。

[注意]注意

您可以完全绕过该算法,并通过设置spring.datasource.type属性指定要使用的连接池。如果您在Tomcat容器中运行应用程序,这一点尤为重要,因为默认情况下会提供tomcat-jdbc

[提示]提示

始终可以手动配置其他连接池。如果您定义自己的DataSource bean,则不会进行自动配置。

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。否则,Spring Boot会尝试自动配置嵌入式数据库。

[提示]提示

您通常不需要指定driver-class-name,因为Spring Boot可以从url中为大多数数据库推断出它。

[注意]注意

对于要创建的池DataSource,我们需要能够验证有效的Driver类是否可用,因此我们在执行任何操作之前检查它。换句话说,如果设置spring.datasource.driver-class-name=com.mysql.jdbc.Driver,那么该类必须是可加载的。

有关DataSourceProperties 更多支持的选项,请参阅 无论实际实施如何,这些都是标准选项。还可以使用各自的前缀(spring.datasource.hikari.*spring.datasource.tomcat.*spring.datasource.dbcp2.*)来微调特定于实现的设置。有关更多详细信息,请参阅您正在使用的连接池实现的文档。

例如,如果使用 Tomcat连接池,则可以自定义许多其他设置,如以下示例所示:

# Number of ms to wait before throwing an exception if no connection is available.
spring.datasource.tomcat.max-wait=10000

# Maximum number of active connections that can be allocated from this pool at the same time.
spring.datasource.tomcat.max-active=50

# Validate the connection before borrowing it from the pool.
spring.datasource.tomcat.test-on-borrow=true

30.1.3连接到JNDI数据源

如果将Spring Boot应用程序部署到Application Server,则可能希望使用Application Server的内置功能配置和管理DataSource,并使用JNDI访问它。

spring.datasource.jndi-name属性可用作spring.datasource.urlspring.datasource.usernamespring.datasource.password属性的替代,以从特定JNDI位置访问DataSource例如,application.properties中的以下部分显示了如何访问定义的DataSource JBoss AS:

spring.datasource.jndi-name=java:jboss/datasources/customers

30.2使用JdbcTemplate

Spring的JdbcTemplateNamedParameterJdbcTemplate类是自动配置的,您可以@Autowire直接将它们放入您自己的beans中,如以下示例所示:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;

@Component
public class MyBean {

	private final JdbcTemplate jdbcTemplate;

	@Autowired
	public MyBean(JdbcTemplate jdbcTemplate) {
		this.jdbcTemplate = jdbcTemplate;
	}

	// ...

}

您可以使用spring.jdbc.template.*属性自定义模板的某些属性,如以下示例所示:

spring.jdbc.template.max-rows=500
[注意]注意

NamedParameterJdbcTemplate在幕后重用了相同的JdbcTemplate实例。如果定义了多个JdbcTemplate并且不存在主要候选者,则不会自动配置NamedParameterJdbcTemplate

30.3 JPA和Spring数据JPA

Java Persistence API是一种标准技术,可让您将对象“映射”到关系数据库。spring-boot-starter-data-jpa POM提供了一种快速入门方式。它提供以下关键依赖项:

  • Hibernate:最受欢迎的JPA实现之一。
  • Spring Data JPA:使实现基于JPA的存储库变得容易。
  • Spring ORM:来自Spring框架的核心ORM支持。
[提示]提示

我们不会在这里详细介绍JPA或Spring数据您可以按照“访问数据与JPA” 从指导spring.io和读取Spring数据JPAHibernate的参考文档。

30.3.1实体类

传统上,JPA“实体”类在persistence.xml文件中指定。使用Spring Boot时,不需要此文件,而是使用“实体扫描”。默认情况下,将搜索主配置类(注释为@EnableAutoConfiguration@SpringBootApplication)下的所有包。

任何注明@Entity@Embeddable@MappedSuperclass的类都会被考虑。典型的实体类类似于以下示例:

package com.example.myapp.domain;

import java.io.Serializable;
import javax.persistence.*;

@Entity
public class City implements Serializable {

	@Id
	@GeneratedValue
	private Long id;

	@Column(nullable = false)
	private String name;

	@Column(nullable = false)
	private String state;

	// ... additional members, often include @OneToMany mappings

	protected City() {
		// no-args constructor required by JPA spec
		// this one is protected since it shouldn't be used directly
	}

	public City(String name, String state) {
		this.name = name;
		this.state = state;
	}

	public String getName() {
		return this.name;
	}

	public String getState() {
		return this.state;
	}

	// ... etc

}
[提示]提示

您可以使用@EntityScan注释自定义实体扫描位置。请参阅“ 第84.4节,“Spring配置”中的@Entity定义“ ”操作方法。

30.3.2 Spring数据JPA存储库

Spring数据JPA存储库是您可以定义以访问数据的接口。JPA查询是从您的方法名称自动创建的。例如,CityRepository接口可能会声明findAllByState(String state)方法来查找给定状态中的所有城市。

对于更复杂的查询,您可以使用Spring Data的Query注释来注释您的方法

Spring数据存储库通常从RepositoryCrudRepository 接口扩展 如果使用自动配置,则会从包含主配置类(使用@EnableAutoConfiguration@SpringBootApplication注释的包)的包中搜索存储库。

以下示例显示了典型的Spring数据存储库接口定义:

package com.example.myapp.domain;

import org.springframework.data.domain.*;
import org.springframework.data.repository.*;

public interface CityRepository extends Repository<City, Long> {

	Page<City> findAll(Pageable pageable);

	City findByNameAndStateAllIgnoringCase(String name, String state);

}

Spring数据JPA存储库支持三种不同的引导模式:default,deferred和lazy。要启用延迟或延迟引导,请将spring.data.jpa.repositories.bootstrap-mode分别设置为deferredlazy使用延迟或延迟引导时,自动配置的EntityManagerFactoryBuilder将使用上下文的异步任务执行程序(如果有)作为引导程序执行程序。

[提示]提示

我们几乎没有触及Spring Data JPA的表面。有关完整的详细信息,请参阅Spring Data JPA参考文档

30.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本机属性。以下行显示了为Hibernate设置JPA属性的示例:

spring.jpa.properties.hibernate.globally_quoted_identifiers=true

前面示例中的行将hibernate.globally_quoted_identifiers属性的值true传递给Hibernate实体管理器。

默认情况下,DDL执行(或验证)将延迟到ApplicationContext开始。还有一个spring.jpa.generate-ddl标志,但如果Hibernate自动配置处于活动状态,则不会使用它,因为ddl-auto设置更精细。

30.3.4在View中打开EntityManager

如果您正在运行Web应用程序,则默认情况下Spring Boot会注册 OpenEntityManagerInViewInterceptor 以应用“在视图中打开EntityManager”模式,以允许在Web视图中进行延迟加载。如果您不想要此行为,则应在application.properties中将spring.jpa.open-in-view设置为false

30.4 Spring数据JDBC

Spring数据包括JDBC的存储库支持,并将自动为CrudRepository上的方法生成SQL。对于更高级的查询,提供了@Query注释。

当必要的依赖项在类路径上时,Spring Boot将自动配置Spring数据的JDBC存储库。可以使用spring-boot-starter-data-jdbc上的单个依赖项将它们添加到项目中。如有必要,您可以通过向应用程序添加@EnableJdbcRepositories注释或JdbcConfiguration子类来控制Spring Data JDBC的配置。

[提示]提示

有关Spring数据JDBC的完整详细信息,请参阅 参考文档

30.5使用H2的Web控制台

H2数据库提供了一个 基于浏览器的控制台是Spring Boot可以自动为您配置。满足以下条件时,将自动配置控制台:

[提示]提示

如果您没有使用Spring Boot的开发人员工具但仍想使用H2的控制台,则可以使用值true配置spring.h2.console.enabled属性。

[注意]注意

H2控制台仅用于开发期间,因此您应该注意确保生产中spring.h2.console.enabled未设置为true

30.5.1更改H2控制台的路径

默认情况下,控制台位于/h2-console您可以使用spring.h2.console.path属性自定义控制台的路径。

30.6使用jOOQ

Java面向对象查询(jOOQ)是Data Geekery的一个流行产品, 它从您的数据库生成Java代码,并允许您通过其流畅的API构建类型安全的SQL查询。商业版和开源版都可以与Spring Boot一起使用。

30.6.1代码生成

要使用jOOQ类型安全查询,您需要从数据库模式生成Java类。您可以按照jOOQ用户手册中的说明进行 操作如果您使用jooq-codegen-maven插件并且还使用spring-boot-starter-parent“父POM”,则可以安全地省略插件的<version>标记。您还可以使用Spring引导定义的版本变量(例如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>

30.6.2使用DSLContext

jOOQ提供的流畅API通过org.jooq.DSLContext接口启动。Spring Boot将DSLContext自动配置为Spring Bean并将其连接到您的应用DataSource要使用DSLContext,您可以@Autowire,如下例所示:

@Component
public class JooqExample implements CommandLineRunner {

	private final DSLContext create;

	@Autowired
	public JooqExample(DSLContext dslContext) {
		this.create = dslContext;
	}

}
[提示]提示

jOOQ手册倾向于使用名为create的变量来保存DSLContext

然后,您可以使用DSLContext构建查询,如以下示例所示:

public List<GregorianCalendar> authorsBornAfter1980() {
	return this.create.selectFrom(AUTHOR)
		.where(AUTHOR.DATE_OF_BIRTH.greaterThan(new GregorianCalendar(1980, 0, 1)))
		.fetch(AUTHOR.DATE_OF_BIRTH);
}

30.6.3 jOOQ SQL方言

除非已配置spring.jooq.sql-dialect属性,否则Spring Boot将确定用于数据源的SQL方言。如果Spring Boot无法检测到方言,则使用DEFAULT

[注意]注意

Spring Boot只能自动配置开源版本的jOOQ支持的方言。

30.6.4自定义jOOQ

通过定义自己的@Bean定义可以实现更高级的自定义,这些定义在创建jOOQ Configuration时使用。您可以为以下jOOQ类型定义beans:

  • ConnectionProvider
  • ExecutorProvider
  • TransactionProvider
  • RecordMapperProvider
  • RecordUnmapperProvider
  • RecordListenerProvider
  • ExecuteListenerProvider
  • VisitListenerProvider
  • TransactionListenerProvider

如果您想完全控制jOOQ配置,也可以创建自己的org.jooq.Configuration @Bean

31.使用NoSQL Technologies

Spring数据提供了其他项目,可帮助您访问各种NoSQL技术,包括: MongoDBNeo4JElasticsearchSolrRedisGemfireCassandraCouchbaseLDAPSpring Boot为Redis,MongoDB,Neo4j,Elasticsearch,Solr Cassandra,Couchbase和LDAP提供自动配置。您可以使用其他项目,但必须自己配置它们。请参阅projects.spring.io/spring-data上的相应参考文档

31.1 Redis

Redis是一个缓存,消息代理和功能丰富的键值存储。Spring Boot为LettuceJedis客户端库提供了基本的自动配置, 并为Spring数据Redis提供了它们之外的抽象

有一个spring-boot-starter-data-redis“Starter”用于以方便的方式收集依赖项。默认情况下,它使用 Lettuce该启动器处理传统和反应应用程序。

[提示]提示

我们还提供spring-boot-starter-data-redis-reactive“Starter”以与其他具有反应支持的商店保持一致。

31.1.1连接到Redis

您可以像注射任何其他Spring Bean一样注入自动配置的RedisConnectionFactoryStringRedisTemplate或vanilla RedisTemplate实例。默认情况下,实例尝试在localhost:6379连接到Redis服务器。以下列表显示了此类bean的示例:

@Component
public class MyBean {

	private StringRedisTemplate template;

	@Autowired
	public MyBean(StringRedisTemplate template) {
		this.template = template;
	}

	// ...

}
[提示]提示

您还可以注册实现LettuceClientConfigurationBuilderCustomizer的任意数量的beans以进行更高级的自定义。如果您使用Jedis,也可以使用JedisClientConfigurationBuilderCustomizer

如果您添加自己配置的任何类型的@Bean,它将替换默认值(RedisTemplate除外,当排除基于bean名称时,redisTemplate ,而不是它的类型)。默认情况下,如果类路径上有commons-pool2,则会出现池连接工厂。

31.2 MongoDB

MongoDB是一个开源的NoSQL文档数据库,它使用类似JSON的模式而不是传统的基于表的关系数据。Spring Boot提供了一些使用MongoDB的便利,包括spring-boot-starter-data-mongodbspring-boot-starter-data-mongodb-reactive“Starters”。

31.2.1连接MongoDB数据库

要访问Mongo数据库,您可以注入自动配置的org.springframework.data.mongodb.MongoDbFactory默认情况下,实例尝试在mongodb://localhost/test连接到MongoDB服务器。以下示例显示如何连接到MongoDB数据库:

import org.springframework.data.mongodb.MongoDbFactory;
import com.mongodb.DB;

@Component
public class MyBean {

	private final MongoDbFactory mongo;

	@Autowired
	public MyBean(MongoDbFactory mongo) {
		this.mongo = mongo;
	}

	// ...

	public void example() {
		DB db = mongo.getDb();
		// ...
	}

}

您可以设置spring.data.mongodb.uri属性以更改URL并配置其他设置,例如副本集,如以下示例所示:

spring.data.mongodb.uri=mongodb://user:[email protected]:12345,mongo2.example.com:23456/test

或者,只要您使用Mongo 2.x,就可以指定host / port例如,您可以在application.properties中声明以下设置:

spring.data.mongodb.host=mongoserver
spring.data.mongodb.port=27017

如果您已经定义了自己的MongoClient,它将用于自动配置合适的MongoDbFactory支持com.mongodb.MongoClientcom.mongodb.client.MongoClient

[注意]注意

如果您使用Mongo 3.0 Java驱动程序,则不支持spring.data.mongodb.hostspring.data.mongodb.port在这种情况下,spring.data.mongodb.uri应该用于提供所有配置。

[提示]提示

如果未指定spring.data.mongodb.port,则使用默认值27017您可以从前面显示的示例中删除此行。

[提示]提示

如果您不使用Spring Data Mongo,则可以注入com.mongodb.MongoClient beans而不是MongoDbFactory如果您想完全控制建立MongoDB连接,您也可以声明自己的MongoDbFactoryMongoClient bean。

[注意]注意

如果您使用的是反应式驱动程序,则SSL需要Netty。如果Netty可用且自己的工厂尚未自定义,则自动配置会自动配置此工厂。

31.2.2 MongoTemplate

Spring数据MongoDB提供了一个MongoTemplate与Spring JdbcTemplate设计非常相似类。JdbcTemplate一样,Spring Boot为您自动配置bean以注入模板,如下所示:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.stereotype.Component;

@Component
public class MyBean {

	private final MongoTemplate mongoTemplate;

	@Autowired
	public MyBean(MongoTemplate mongoTemplate) {
		this.mongoTemplate = mongoTemplate;
	}

	// ...

}

有关完整的详细信息,请参阅 MongoOperations Javadoc

31.2.3 Spring数据MongoDB存储库

Spring数据包括MongoDB的存储库支持。与前面讨论的JPA存储库一样,基本原则是基于方法名称自动构造查询。

实际上,Spring Data JPA和Spring Data MongoDB共享相同的公共基础结构。您可以从前面获取JPA示例,假设City现在是Mongo数据类而不是JPA @Entity,它的工作方式相同,如下例所示:

package com.example.myapp.domain;

import org.springframework.data.domain.*;
import org.springframework.data.repository.*;

public interface CityRepository extends Repository<City, Long> {

	Page<City> findAll(Pageable pageable);

	City findByNameAndStateAllIgnoringCase(String name, String state);

}
[提示]提示

您可以使用@EntityScan注释自定义文档扫描位置。

[提示]提示

有关Spring Data MongoDB的完整详细信息,包括其丰富的对象映射技术,请参阅其参考文档

31.2.4嵌入式Mongo

Spring Boot为Embedded Mongo提供自动配置 要在Spring Boot应用程序中使用它,请在de.flapdoodle.embed:de.flapdoodle.embed.mongo上添加依赖项。

可以通过设置spring.data.mongodb.port属性来配置Mongo侦听的端口。要使用随机分配的空闲端口,请使用值0. MongoAutoConfiguration创建的MongoClient将自动配置为使用随机分配的端口。

[注意]注意

如果未配置自定义端口,则嵌入式支持默认使用随机端口(而不是27017)。

如果类路径上有SLF4J,则Mongo生成的输出会自动路由到名为org.springframework.boot.autoconfigure.mongo.embedded.EmbeddedMongo的记录器。

您可以声明自己的IMongodConfigIRuntimeConfig beans来控制Mongo实例的配置和日志路由。

31.3 Neo4j

Neo4j是一个开源的NoSQL图形数据库,它使用由一级关系连接的节点的丰富数据模型,与传统的RDBMS方法相比,它更适合于连接的大数据。Spring Boot为使用Neo4j提供了一些便利,包括spring-boot-starter-data-neo4j“Starter”。

31.3.1连接到Neo4j数据库

要访问Neo4j服务器,您可以注入自动配置的org.neo4j.ogm.session.Session默认情况下,实例尝试使用Bolt协议连接到localhost:7687的Neo4j服务器。以下示例显示了如何注入Neo4j Session

@Component
public class MyBean {

	private final Session session;

	@Autowired
	public MyBean(Session session) {
		this.session = session;
	}

	// ...

}

您可以通过设置spring.data.neo4j.*属性来配置要使用的URI和凭据,如以下示例所示:

spring.data.neo4j.uri=bolt://my-server:7687
spring.data.neo4j.username=neo4j
spring.data.neo4j.password=secret

您可以通过添加org.neo4j.ogm.config.Configuration @Bean来完全控制会话创建。此外,添加@Bean类型SessionFactory会禁用自动配置并为您提供完全控制权。

31.3.2使用嵌入模式

如果将org.neo4j:neo4j-ogm-embedded-driver添加到应用程序的依赖项中,Spring Boot会自动配置Neo4j的进程内嵌入式实例,该应用程序在应用程序关闭时不会保留任何数据。

[注意]注意

由于嵌入式Neo4j OGM驱动程序本身不提供Neo4j内核,因此您必须自己声明org.neo4j:neo4j为依赖项。有关兼容版本的列表,请参阅 Neo4j OGM文档

当类路径上有多个驱动程序时,嵌入式驱动程序优先于其他驱动程序。您可以通过设置spring.data.neo4j.embedded.enabled=false来明确禁用嵌入模式。

如果嵌入式驱动程序和Neo4j内核如上所述位于类路径上,则数据Neo4j测试会自动使用嵌入式Neo4j实例。

[注意]注意

您可以通过在配置中提供数据库文件的路径来为嵌入模式启用持久性,例如spring.data.neo4j.uri=file://var/tmp/graph.db

31.3.3 Neo4jSession

默认情况下,如果您正在运行Web应用程序,则会话将绑定到该线程以进行整个请求处理(即,它使用“在视图中打开会话”模式)。如果您不想要此行为,请将以下行添加到您的application.properties文件中:

spring.data.neo4j.open-in-view=false

31.3.4 Spring数据Neo4j存储库

Spring数据包括Neo4j的存储库支持。

Spring数据Neo4j与Spring Data JPA共享公共基础架构,正如许多其他Spring数据模块那样。您可以从之前的JPA示例中将City定义为Neo4j OGM @NodeEntity而不是JPA @Entity,并且存储库抽象以相同的方式工作,如以下示例所示:

package com.example.myapp.domain;

import java.util.Optional;

import org.springframework.data.neo4j.repository.*;

public interface CityRepository extends Neo4jRepository<City, Long> {

	Optional<City> findOneByNameAndState(String name, String state);

}

spring-boot-starter-data-neo4j“Starter”启用存储库支持以及事务管理。您可以在@Configuration - bean上分别使用@EnableNeo4jRepositories@EntityScan来自定义位置以查找存储库和实体。

[提示]提示

有关Spring Data Neo4j的完整详细信息,包括其对象映射技术,请参阅参考文档

31.4 Gemfire

Spring数据Gemfire为访问Pivotal Gemfire数据管理平台提供了方便的Spring友好工具 有一个spring-boot-starter-data-gemfire“Starter”用于以方便的方式收集依赖项。目前没有Gemfire的自动配置支持,但您可以使用单个注释启用Spring数据存储库 @EnableGemfireRepositories

31.5 Solr

Apache Solr是一个搜索引擎。Spring Boot为Solr 5客户端库提供了基本的自动配置,并在Spring Data Solr提供了它上面的抽象有一个spring-boot-starter-data-solr“Starter”用于以方便的方式收集依赖项。

31.5.1连接到Solr

您可以像注射任何其他Spring bean一样注入自动配置的SolrClient实例。默认情况下,实例尝试连接到localhost:8983/solr的服务器。以下示例显示了如何注入Solr bean:

@Component
public class MyBean {

	private SolrClient solr;

	@Autowired
	public MyBean(SolrClient solr) {
		this.solr = solr;
	}

	// ...

}

如果您添加SolrClient类型的@Bean,它将替换默认值。

31.5.2 Spring数据Solr存储库

Spring数据包括Apache Solr的存储库支持。与前面讨论的JPA存储库一样,基本原则是根据方法名称自动构建查询。

实际上,Spring Data JPA和Spring Data Solr共享相同的公共基础结构。您可以从前面获取JPA示例,假设City现在是@SolrDocument类而不是JPA @Entity,它的工作方式相同。

[提示]提示

有关Spring Data Solr的完整详细信息,请参阅 参考文档

31.6 Elasticsearch

Elasticsearch是一个开源,分布式,RESTful搜索和分析引擎。Spring Boot为Elasticsearch提供基本的自动配置。

Spring Boot支持多个HTTP客户端:

  • 官方Java“低级”和“高级”REST客户端
  • 笑话

Spring Data Elasticsearch仍在使用传输客户端 ,您可以使用spring-boot-starter-data-elasticsearch“Starter”开始使用它。

31.6.1 REST客户端连接到Elasticsearch

Elasticsearch提供了 两个 可用于查询集群的REST客户端:“低级”客户端和“高级”客户端。

如果您对类路径具有org.elasticsearch.client:elasticsearch-rest-client依赖关系,Spring Boot将自动配置并注册默认目标为localhost:9200RestClient bean。您可以进一步调整RestClient的配置方式,如以下示例所示:

spring.elasticsearch.rest.uris=http://search.example.com:9200
spring.elasticsearch.rest.username=user
spring.elasticsearch.rest.password=secret

您还可以注册实现RestClientBuilderCustomizer的任意数量的beans以进行更高级的自定义。要完全控制注册,请定义RestClient bean。

如果您对类路径具有org.elasticsearch.client:elasticsearch-rest-high-level-client依赖关系,Spring Boot将自动配置RestHighLevelClient,其包装任何现有的RestClient bean,重用其HTTP配置。

31.6.2使用Jest连接到Elasticsearch

如果类路径上有Jest,则可以注入一个自动配置的JestClient,默认情况下为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

您还可以注册实现HttpClientConfigBuilderCustomizer的任意数量的beans以进行更高级的自定义。以下示例调整其他HTTP设置:

static class HttpSettingsCustomizer implements HttpClientConfigBuilderCustomizer {

	@Override
	public void customize(HttpClientConfig.Builder builder) {
		builder.maxTotalConnection(100).defaultMaxTotalConnectionPerRoute(5);
	}

}

要完全控制注册,请定义JestClient bean。

31.6.3使用Spring数据连接到Elasticsearch

要连接到Elasticsearch,您必须提供一个或多个群集节点的地址。可以通过将spring.data.elasticsearch.cluster-nodes属性设置为逗号分隔的host:port列表来指定地址。有了这种配置,ElasticsearchTemplateTransportClient可以像任何其他Spring bean一样注入,如下例所示:

spring.data.elasticsearch.cluster-nodes=localhost:9300
@Component
public class MyBean {

	private final ElasticsearchTemplate template;

	public MyBean(ElasticsearchTemplate template) {
		this.template = template;
	}

	// ...

}

如果您添加自己的ElasticsearchTemplateTransportClient @Bean,则会替换默认值。

31.6.4 Spring数据Elasticsearch存储库

Spring数据包括Elasticsearch的存储库支持。与前面讨论的JPA存储库一样,基本原则是根据方法名称自动为您构建查询。

事实上,Spring Data JPA和Spring Data Elasticsearch共享相同的通用基础架构。您可以从之前获取JPA示例,假设City现在是Elasticsearch @Document类而不是JPA @Entity,它的工作方式相同。

[提示]提示

有关Spring Data Elasticsearch的完整详细信息,请参阅 参考文档

31.7 Cassandra

Cassandra是一个开源的分布式数据库管理系统,旨在处理许多商用服务器上的大量数据。Spring Boot提供Cassandra的自动配置以及Spring数据Cassandra提供的摘要有一个spring-boot-starter-data-cassandra“Starter”用于以方便的方式收集依赖项。

31.7.1连接到Cassandra

您可以像对待任何其他Spring Bean一样注入自动配置的CassandraTemplate或Cassandra Session实例。spring.data.cassandra.*属性可用于自定义连接。通常,您提供keyspace-namecontact-points属性,如以下示例所示:

spring.data.cassandra.keyspace-name=mykeyspace
spring.data.cassandra.contact-points=cassandrahost1,cassandrahost2

您还可以注册实现ClusterBuilderCustomizer的任意数量的beans以进行更高级的自定义。

以下代码清单显示了如何注入Cassandra bean:

@Component
public class MyBean {

	private CassandraTemplate template;

	@Autowired
	public MyBean(CassandraTemplate template) {
		this.template = template;
	}

	// ...

}

如果您添加CassandraTemplate类型的@Bean,它将替换默认值。

31.7.2 Spring数据Cassandra存储库

Spring数据包括Cassandra的基本存储库支持。目前,这比前面讨论的JPA存储库更有限,需要使用@Query来注释finder方法。

[提示]提示

有关Spring数据Cassandra的完整详细信息,请参阅 参考文档

31.8 Couchbase

Couchbase是一个开源的,分布式的,多模型的NoSQL面向文档的数据库,针对交互式应用程序进行了优化。Spring Boot提供了Couchbase的自动配置以及Spring Data Couchbase提供的抽象 spring-boot-starter-data-couchbasespring-boot-starter-data-couchbase-reactive“Starters”用于以方便的方式收集依赖项。

31.8.1连接Couchbase

您可以通过添加Couchbase SDK和一些配置来获得BucketClusterspring.couchbase.*属性可用于自定义连接。通常,您提供引导主机,存储桶名称和密码,如以下示例所示:

spring.couchbase.bootstrap-hosts=my-host-1,192.168.1.123
spring.couchbase.bucket.name=my-bucket
spring.couchbase.bucket.password=secret
[提示]提示

您需要至少提供引导主机,在这种情况下,存储桶名称为default,密码为空字符串。或者,您可以定义自己的org.springframework.data.couchbase.config.CouchbaseConfigurer @Bean来控制整个配置。

也可以自定义一些CouchbaseEnvironment设置。例如,以下配置更改用于打开新Bucket的超时并启用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.*属性以获取更多详细信息。

31.8.2 Spring数据Couchbase存储库

Spring数据包括Couchbase的存储库支持。有关Spring Data Couchbase的完整详细信息,请参阅 参考文档

您可以像使用任何其他Spring Bean一样注入自动配置的CouchbaseTemplate实例,前提是默认 CouchbaseConfigurer可用(当您启用Couchbase支持时会发生这种情况,如前所述)。

以下示例显示了如何注入Couchbase bean:

@Component
public class MyBean {

	private final CouchbaseTemplate template;

	@Autowired
	public MyBean(CouchbaseTemplate template) {
		this.template = template;
	}

	// ...

}

您可以在自己的配置中定义一些beans来覆盖自动配置提供的内容:

  • CouchbaseTemplate @Bean,名称为couchbaseTemplate
  • IndexManager @Bean,名称为couchbaseIndexManager
  • CustomConversions @Bean,名称为couchbaseCustomConversions

为避免在您自己的配置中对这些名称进行硬编码,您可以重用Spring Data Couchbase提供的BeanNames例如,您可以自定义要使用的转换器,如下所示:

@Configuration
public class SomeConfiguration {

	@Bean(BeanNames.COUCHBASE_CUSTOM_CONVERSIONS)
	public CustomConversions myCustomConversions() {
		return new CustomConversions(...);
	}

	// ...

}
[提示]提示

如果您想完全绕过Spring Data Couchbase的自动配置,请提供您自己的org.springframework.data.couchbase.config.AbstractCouchbaseDataConfiguration实现。

31.9 LDAP

LDAP(轻量级目录访问协议)是一种开放的,与供应商无关的行业标准应用程序协议,用于通过IP网络访问和维护分布式目录信息服务。Spring Boot为任何兼容的LDAP服务器提供自动配置,并为UnboundID支持嵌入式内存中LDAP服务器

LDAP抽象由 Spring数据LDAP提供有一个spring-boot-starter-data-ldap“Starter”用于以方便的方式收集依赖项。

31.9.1连接LDAP服务器

要连接到LDAP服务器,请确保声明对spring-boot-starter-data-ldap“Starter”或spring-ldap-core的依赖关系,然后在application.properties中声明服务器的URL,如以下示例所示:

spring.ldap.urls=ldap://myserver:1235
spring.ldap.username=admin
spring.ldap.password=secret

如果需要自定义连接设置,可以使用spring.ldap.basespring.ldap.base-environment属性。

根据这些设置自动配置LdapContextSource如果您需要自定义它,例如使用PooledContextSource,您仍然可以注入自动配置的LdapContextSource请务必将自定义的ContextSource标记为@Primary,以便自动配置的LdapTemplate使用它。

31.9.2 Spring数据LDAP存储库

Spring数据包括LDAP的存储库支持。有关Spring数据LDAP的完整详细信息,请参阅 参考文档

您也可以像对待任何其他Spring Bean一样注入自动配置的LdapTemplate实例,如以下示例所示:

@Component
public class MyBean {

	private final LdapTemplate template;

	@Autowired
	public MyBean(LdapTemplate template) {
		this.template = template;
	}

	// ...

}

31.9.3嵌入式内存LDAP服务器

出于测试目的,Spring Boot支持从UnboundID自动配置内存中LDAP服务器要配置服务器,请向com.unboundid:unboundid-ldapsdk添加依赖项并声明base-dn属性,如下所示:

spring.ldap.embedded.base-dn=dc=spring,dc=io
[注意]注意

可以定义多个base-dn值,但是,由于可分辨名称通常包含逗号,因此必须使用正确的符号来定义它们。

在yaml文件中,您可以使用yaml列表表示法:

spring.ldap.embedded.base-dn:
  - dc=spring,dc=io
  - dc=pivotal,dc=io

在属性文件中,必须包含索引作为属性名称的一部分:

spring.ldap.embedded.base-dn[0]=dc=spring,dc=io
spring.ldap.embedded.base-dn[1]=dc=pivotal,dc=io

默认情况下,服务器在随机端口上启动并触发常规LDAP支持。无需指定spring.ldap.urls属性。

如果类路径上有schema.ldif文件,则用于初始化服务器。如果要从其他资源加载初始化脚本,还可以使用spring.ldap.embedded.ldif属性。

默认情况下,标准模式用于验证LDIF文件。您可以通过设置spring.ldap.embedded.validation.enabled属性完全关闭验证。如果您有自定义属性,则可以使用spring.ldap.embedded.validation.schema来定义自定义属性类型或对象类。

31.10 InfluxDB

InfluxDB是一个开源时间序列数据库,针对运营监控,应用程序指标,物联网传感器数据和实时分析等领域中的时间序列数据的快速,高可用性存储和检索进行了优化。

31.10.1连接到InfluxDB

Spring Boot自动配置InfluxDB实例,前提是influxdb-java客户端在类路径上并且设置了数据库的URL,如以下示例所示:

spring.influx.url=http://172.0.0.1:8086

如果与InfluxDB的连接需要用户和密码,则可以相应地设置spring.influx.userspring.influx.password属性。

InfluxDB依赖于OkHttp。如果您需要在后台调整http客户端InfluxDB,则可以注册InfluxDbOkHttpClientBuilderProvider bean。

32.缓存

Spring框架支持透明地向应用程序添加缓存。从本质上讲,抽象将缓存应用于方法,从而根据缓存中可用的信息减少执行次数。缓存逻辑应用透明,不会对调用者造成任何干扰。只要通过@EnableCaching注释启用了缓存支持,Spring Boot就会自动配置缓存基础结构。

[注意]注意

有关详细信息,请查看Spring框架参考相关部分

简而言之,将缓存添加到服务操作就像在其方法中添加相关注释一样简单,如以下示例所示:

import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Component;

@Component
public class MathService {

	@Cacheable("piDecimals")
	public int computePiDecimal(int i) {
		// ...
	}

}

此示例演示了如何在可能代价高昂的操作上使用缓存。在调用computePiDecimal之前,抽象在piDecimals缓存中查找与i参数匹配的条目。如果找到条目,则缓存中的内容会立即返回给调用者,并且不会调用该方法。否则,将调用该方法,并在返回值之前更新缓存。

[警告]警告

您还可以透明地使用标准JSR-107(JCache)注释(例如@CacheResult)。但是,我们强烈建议您不要混用和匹配Spring Cache和JCache注释。

如果您不添加任何特定的缓存库,Spring Boot会自动配置在内存中使用并发映射简单提供程序当需要缓存时(例如前面示例中的piDecimals),此提供程序会为您创建缓存。简单的提供程序并不是真正推荐用于生产用途,但它非常适合入门并确保您了解这些功能。当您决定使用缓存提供程序时,请务必阅读其文档以了解如何配置应用程序使用的缓存。几乎所有提供程序都要求您显式配置在应用程序中使用的每个缓存。有些提供了一种自定义spring.cache.cache-names属性定义的默认缓存的方法。

[提示]提示

还可以透明地 更新逐出缓存中的数据。

32.1支持的缓存提供程序

缓存抽象不提供实际存储,并依赖于org.springframework.cache.Cacheorg.springframework.cache.CacheManager接口实现的抽象。

如果您尚未定义类型为CacheManager的bean或名为cacheResolverCacheResolver(请参阅参考资料 CachingConfigurer),则Spring Boot会尝试检测以下提供程序(按指示顺序):

[提示]提示

也可以通过设置spring.cache.type属性强制特定的缓存提供程序。如果您需要在某些环境(例如测试)中完全禁用缓存,请使用此属性

[提示]提示

使用spring-boot-starter-cache“Starter”快速添加基本缓存依赖项。首发进入spring-context-support如果手动添加依赖项,则必须包含spring-context-support才能使用JCache,EhCache 2.x或Guava支持。

如果Wavefront自动配置CacheManager,则可以通过公开实现CacheManagerCustomizer接口的bean来完全初始化之前调整其配置。以下示例设置一个标志,表示应将null值传递给底层映射:

@Bean
public CacheManagerCustomizer<ConcurrentMapCacheManager> cacheManagerCustomizer() {
	return new CacheManagerCustomizer<ConcurrentMapCacheManager>() {
		@Override
		public void customize(ConcurrentMapCacheManager cacheManager) {
			cacheManager.setAllowNullValues(false);
		}
	};
}
[注意]注意

在前面的示例中,预计会自动配置ConcurrentMapCacheManager如果不是这种情况(您提供了自己的配置或自动配置了不同的缓存提供程序),则根本不会调用自定义程序。您可以拥有任意数量的自定义程序,也可以使用@OrderOrdered订购它们。

32.1.1通用

如果上下文定义至少一个org.springframework.cache.Cache bean,则使用通用缓存创建了包含该类型的所有beans的CacheManager

32.1.2 JCache(JSR-107)

JCache通过类路径上的javax.cache.spi.CachingProvider进行自举(即类路径上存在符合JSR-107的缓存库),spring-boot-starter-cachespring-boot-starter-cache“Starter”提供。可以使用各种兼容库,Spring Boot为Ehcache 3,Hazelcast和Infinispan提供依赖关系管理。还可以添加任何其他兼容库。

可能会出现多个提供程序,在这种情况下必须明确指定提供程序。即使JSR-107标准没有强制使用标准化方法来定义配置文件的位置,Spring Boot也会尽力适应使用实现细节设置缓存,如以下示例所示:

   # Only necessary if more than one provider is present
spring.cache.jcache.provider=com.acme.MyCachingProvider
spring.cache.jcache.config=classpath:acme.xml
[注意]注意

当缓存库同时提供本机实现和JSR-107支持时,Spring Boot更喜欢JSR-107支持,因此如果切换到不同的JSR-107实现,则可以使用相同的功能。

[提示]提示

Spring Boot 普遍支持Hazelcast如果单个HazelcastInstance可用,它也会自动重用于CacheManager,除非指定了spring.cache.jcache.config属性。

有两种方法可以自定义基础javax.cache.cacheManager

  • 可以通过设置spring.cache.cache-names属性在启动时创建缓存。如果定义了自定义javax.cache.configuration.Configuration bean,则会使用它来自定义它们。
  • 使用CacheManager的引用调用org.springframework.boot.autoconfigure.cache.JCacheManagerCustomizer beans进行完全自定义。
[提示]提示

如果定义了标准javax.cache.CacheManager bean,它将自动包装在抽象所需的org.springframework.cache.CacheManager实现中。没有进一步的自定义。

32.1.3 EhCache 2.x

如果可以在类路径的根目录中找到名为ehcache.xml的文件,则使用EhCache 2.x. 如果找到EhCache 2.x,则spring-boot-starter-cache“Starter”提供的EhCacheCacheManager用于引导缓存管理器。还可以提供备用配置文件,如以下示例所示:

spring.cache.ehcache.config=classpath:config/another-config.xml

32.1.4 Hazelcast

Spring Boot 普遍支持Hazelcast如果已自动配置HazelcastInstance,则会自动将其包装在CacheManager中。

32.1.5 Infinispan

Infinispan没有默认配置文件位置,因此必须明确指定。否则,使用默认引导程序。

spring.cache.infinispan.config=infinispan.xml

可以通过设置spring.cache.cache-names属性在启动时创建缓存。如果定义了自定义ConfigurationBuilder bean,则它用于自定义缓存。

[注意]注意

Spring Boot中Infinispan的支持仅限于嵌入模式,并且非常基础。如果您想要更多选项,则应使用官方Infinispan Spring Boot启动器。有关更多详细信息,请参阅 Infinispan的文档

32.1.6 Couchbase

如果Couchbase Java客户端和couchbase-spring-cache实现可用并且已配置 Couchbase ,则会自动配置CouchbaseCacheManager通过设置spring.cache.cache-names属性,还可以在启动时创建其他缓存。这些缓存在自动配置的Bucket上运行。您可以通过使用定制创建另一个Bucket额外的缓存。假设你需要两个缓存(cache1cache2)在“主”Bucket和一个(cache3)缓存上,自定义时间为2秒,“另一个”Bucket您可以通过配置创建前两个缓存,如下所示:

spring.cache.cache-names=cache1,cache2

然后,您可以定义@Configuration类来配置额外的Bucketcache3缓存,如下所示:

@Configuration
public class CouchbaseCacheConfiguration {

	private final Cluster cluster;

	public CouchbaseCacheConfiguration(Cluster cluster) {
		this.cluster = cluster;
	}

	@Bean
	public Bucket anotherBucket() {
		return this.cluster.openBucket("another", "secret");
	}

	@Bean
	public CacheManagerCustomizer<CouchbaseCacheManager> cacheManagerCustomizer() {
		return c -> {
			c.prepareCache("cache3", CacheBuilder.newInstance(anotherBucket())
					.withExpiration(2));
		};
	}

}

此示例配置重用通过自动配置创建的Cluster

32.1.7 Redis

如果Redis可用且已配置,则会自动配置RedisCacheManager通过设置spring.cache.cache-names属性可以在启动时创建其他缓存,并且可以使用spring.cache.redis.*属性配置缓存默认值。例如,以下配置创建cache1cache2缓存,生存时间为 10分钟:

spring.cache.cache-names=cache1,cache2
spring.cache.redis.time-to-live=600000
[注意]注意

默认情况下,会添加一个键前缀,以便在两个单独的缓存使用相同的键时,Redis没有重叠的键,并且不能返回无效值。如果您创建自己的RedisCacheManager,我们强烈建议您启用此设置。

[提示]提示

您可以通过添加自己的RedisCacheConfiguration @Bean来完全控制配置。如果您正在寻找自定义序列化策略,这可能很有用。

32.1.8 Caffeine

Caffeine是Java 8重写的Guava缓存,取代了对Guava的支持。如果存在Caffeine,则自动配置CaffeineCacheManager(由spring-boot-starter-cache“Starter”提供)。可以通过设置spring.cache.cache-names属性在启动时创建缓存,并且可以通过以下之一(按指示的顺序)自定义缓存:

  1. spring.cache.caffeine.spec定义的缓存规范
  2. 定义了com.github.benmanes.caffeine.cache.CaffeineSpec bean
  3. 定义了com.github.benmanes.caffeine.cache.Caffeine bean

例如,以下配置创建cache1cache2缓存,最大大小为500,生存时间为 10分钟

spring.cache.cache-names=cache1,cache2
spring.cache.caffeine.spec=maximumSize=500,expireAfterAccess=600s

如果定义了com.github.benmanes.caffeine.cache.CacheLoader bean,它将自动与CaffeineCacheManager相关联。由于CacheLoader将与缓存管理器管理的所有缓存关联,因此必须将其定义为CacheLoader<Object, Object>自动配置忽略任何其他泛型类型。

32.1.9简单

如果找不到其他提供程序,则配置使用ConcurrentHashMap作为缓存存储的简单实现。如果您的应用程序中没有缓存库,则这是默认值。默认情况下,会根据需要创建缓存,但您可以通过设置cache-names属性来限制可用缓存列表。例如,如果您只想要cache1cache2缓存,请按如下所示设置cache-names属性:

spring.cache.cache-names=cache1,cache2

如果这样做并且您的应用程序使用未列出的缓存,则在需要缓存时它会在运行时失败,但在启动时则不会。这类似于“真实”缓存提供程序在使用未声明的缓存时的行为方式。

32.1.10 None

当配置中存在@EnableCaching时,也需要合适的缓存配置。如果需要在某些环境中完全禁用缓存,请将缓存类型强制为none以使用no-op实现,如以下示例所示:

spring.cache.type=none

33.消息传递

Spring框架为与消息传递系统的集成提供了广泛的支持,从使用JmsTemplate的JMS API的简化使用到异步接收消息的完整基础结构。Spring AMQP为高级消息队列协议提供了类似的功能集。Spring Boot还为RabbitTemplate和RabbitMQ提供了自动配置选项。Spring WebSocket本身包含对STOMP消息传递的支持,Spring Boot通过启动器和少量自动配置支持。Spring Boot也支持Apache Kafka。

33.1 JMS

javax.jms.ConnectionFactory接口提供了一种创建javax.jms.Connection的标准方法,用于与JMS代理进行交互。虽然Spring需要ConnectionFactory来使用JMS,但您通常不需要自己直接使用它,而是可以依赖更高级别的消息传递抽象。(有关详细信息,请参阅Spring框架参考文档相关部分。)Spring Boot还自动配置发送和接收消息所需的基础结构。

33.1.1 ActiveMQ支持

ActiveMQ在类路径上可用时,Spring Boot也可以配置ConnectionFactory如果代理存在,则会自动启动并配置嵌入式代理(前提是未通过配置指定代理URL)。

[注意]注意

如果使用spring-boot-starter-activemq,则提供连接或嵌入ActiveMQ实例的必要依赖项,以及与JMS集成的Spring基础结构。

ActiveMQ配置由spring.activemq.*中的外部配置属性控制。例如,您可以在application.properties中声明以下部分:

spring.activemq.broker-url=tcp://192.168.1.210:9876
spring.activemq.user=admin
spring.activemq.password=secret

默认情况下,CachingConnectionFactory使用spring.jms.*中的外部配置属性可以控制的合理设置包装本机ConnectionFactory

spring.jms.cache.session-cache-size=5

如果您更愿意使用本机池,则可以通过向org.messaginghub:pooled-jms添加依赖项并相应地配置JmsPoolConnectionFactory来实现,如以下示例所示:

spring.activemq.pool.enabled=true
spring.activemq.pool.max-connections=50
[提示]提示

有关ActiveMQProperties 更多支持的选项,请参阅 您还可以注册实现ActiveMQConnectionFactoryCustomizer的任意数量的beans以进行更高级的自定义。

默认情况下,ActiveMQ会创建一个目标(如果它尚不存在),以便根据提供的名称解析目标。

33.1.2阿耳忒弥斯支持

Spring Boot可以在检测到类路径上的Artemis可用时自动配置ConnectionFactory 如果存在代理,则会自动启动并配置嵌入式代理(除非已明确设置mode属性)。支持的模式是embedded(以明确表示需要嵌入式代理,如果代理路径在类路径上不可用则发生错误)和native(使用{11 /连接到代理)传输协议)。配置后者时,Spring Boot使用默认设置配置连接到本地计算机上运行的代理的ConnectionFactory

[注意]注意

如果使用spring-boot-starter-artemis,则会提供连接到现有Artemis实例的必要依赖项,以及与JMS集成的Spring基础结构。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.JMSQueueConfigurationorg.apache.activemq.artemis.jms.server.config.TopicConfiguration类型的bean。

默认情况下,CachingConnectionFactory使用spring.jms.*中的外部配置属性可以控制的合理设置包装本机ConnectionFactory

spring.jms.cache.session-cache-size=5

如果您更愿意使用本机池,则可以通过向org.messaginghub:pooled-jms添加依赖关系并相应地配置JmsPoolConnectionFactory来实现,如以下示例所示:

spring.artemis.pool.enabled=true
spring.artemis.pool.max-connections=50

有关ArtemisProperties 更多支持选项,请参阅

不使用JNDI查找,并使用Artemis配置中的name属性或通过配置提供的名称来解析目标名称。

33.1.3使用JNDI ConnectionFactory

如果您在应用程序服务器中运行应用程序,Spring Boot会尝试使用JNDI找到JMS ConnectionFactory默认情况下,会检查java:/JmsXAjava:/XAConnectionFactory位置。如果需要指定备用位置,可以使用spring.jms.jndi-name属性,如以下示例所示:

spring.jms.jndi-name=java:/MyConnectionFactory

33.1.4发送消息

Spring的JmsTemplate是自动配置的,您可以将其直接自动装入您自己的beans,如以下示例所示:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jms.core.JmsTemplate;
import org.springframework.stereotype.Component;

@Component
public class MyBean {

	private final JmsTemplate jmsTemplate;

	@Autowired
	public MyBean(JmsTemplate jmsTemplate) {
		this.jmsTemplate = jmsTemplate;
	}

	// ...

}
[注意]注意

JmsMessagingTemplate可以以类似的方式注射。如果定义了DestinationResolverMessageConverter bean,则会自动将其与自动配置的JmsTemplate相关联。

33.1.5接收消息

当存在JMS基础结构时,可以使用@JmsListener注释任何bean以创建侦听器端点。如果未定义JmsListenerContainerFactory,则会自动配置默认值。如果定义了DestinationResolverMessageConverter beans,它将自动关联到默认工厂。

默认情况下,默认工厂是事务性的。如果您在存在JtaTransactionManager的基础结构中运行,则默认情况下它与侦听器容器关联。如果不是,则启用sessionTransacted标志。在后一种情况下,您可以通过在侦听器方法(或其委托)上添加@Transactional,将本地数据存储事务与传入消息的处理相关联。这确保了在本地事务完成后确认传入消息。这还包括发送已在同一JMS会话上执行的响应消息。

以下组件在someQueue目标上创建一个侦听器端点:

@Component
public class MyBean {

	@JmsListener(destination = "someQueue")
	public void processMessage(String content) {
		// ...
	}

}
[提示]提示

有关 更多详细信息,请参阅@EnableJms的Javadoc

如果您需要创建更多JmsListenerContainerFactory实例,或者如果要覆盖默认值,Spring Boot提供DefaultJmsListenerContainerFactoryConfigurer,您可以使用DefaultJmsListenerContainerFactoryConfigurer来初始化DefaultJmsListenerContainerFactory,其设置与自动配置。

例如,以下示例公开了另一个使用特定MessageConverter的工厂:

@Configuration
static class JmsConfiguration {

	@Bean
	public DefaultJmsListenerContainerFactory myFactory(
			DefaultJmsListenerContainerFactoryConfigurer configurer) {
		DefaultJmsListenerContainerFactory factory =
				new DefaultJmsListenerContainerFactory();
		configurer.configure(factory, connectionFactory());
		factory.setMessageConverter(myMessageConverter());
		return factory;
	}

}

然后您可以在任何@JmsListener - 注释方法中使用工厂,如下所示:

@Component
public class MyBean {

	@JmsListener(destination = "someQueue", containerFactory="myFactory")
	public void processMessage(String content) {
		// ...
	}

}

33.2 AMQP

高级消息队列协议(AMQP)是面向消息的中间件的平台中立的线级协议。Spring AMQP项目将核心Spring概念应用于基于AMQP的消息传递解决方案的开发。Spring Boot为通过RabbitMQ使用AMQP提供了一些便利,包括spring-boot-starter-amqp“Starter”。

33.2.1 RabbitMQ支持

RabbitMQ是一个基于AMQP协议的轻量级,可靠,可扩展且可移植的消息代理。Spring使用RabbitMQ通过AMQP协议进行通信。

RabbitMQ配置由spring.rabbitmq.*中的外部配置属性控制。例如,您可以在application.properties中声明以下部分:

spring.rabbitmq.host=localhost
spring.rabbitmq.port=5672
spring.rabbitmq.username=admin
spring.rabbitmq.password=secret

如果上下文中存在ConnectionNameStrategy bean,它将自动用于命名由自动配置的ConnectionFactory创建的连接。有关RabbitProperties更多支持的选项,请参阅

[提示]提示

有关详细信息请参阅 了解AMQP,RabbitMQ使用的协议

33.2.2发送消息

Spring的AmqpTemplateAmqpAdmin是自动配置的,您可以将它们直接自动装入您自己的beans,如以下示例所示:

import org.springframework.amqp.core.AmqpAdmin;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class MyBean {

	private final AmqpAdmin amqpAdmin;
	private final AmqpTemplate amqpTemplate;

	@Autowired
	public MyBean(AmqpAdmin amqpAdmin, AmqpTemplate amqpTemplate) {
		this.amqpAdmin = amqpAdmin;
		this.amqpTemplate = amqpTemplate;
	}

	// ...

}
[注意]注意

RabbitMessagingTemplate 可以以类似的方式注射。如果定义了MessageConverter bean,它将自动关联到自动配置的AmqpTemplate

如有必要,任何定义为bean的org.springframework.amqp.core.Queue都将自动用于在RabbitMQ实例上声明相应的队列。

要重试操作,可以在AmqpTemplate上启用重试(例如,在代理连接丢失的情况下):

spring.rabbitmq.template.retry.enabled=true
spring.rabbitmq.template.retry.initial-interval=2s

默认情况下禁用重试。您还可以通过声明RabbitRetryTemplateCustomizer bean以编程方式自定义RetryTemplate

33.2.3接收消息

当Rabbit基础结构存在时,任何bean都可以使用@RabbitListener进行注释以创建侦听器端点。如果未定义RabbitListenerContainerFactory,则会自动配置默认值SimpleRabbitListenerContainerFactory,您可以使用spring.rabbitmq.listener.type属性切换到直接容器。如果定义了MessageConverterMessageRecoverer bean,它将自动与默认工厂关联。

以下示例组件在someQueue队列上创建一个侦听器端点:

@Component
public class MyBean {

	@RabbitListener(queues = "someQueue")
	public void processMessage(String content) {
		// ...
	}

}
[提示]提示

有关详细信息,请参阅@EnableRabbit的Javadoc

如果您需要创建更多RabbitListenerContainerFactory个实例,或者如果要覆盖默认值,Spring Boot会提供SimpleRabbitListenerContainerFactoryConfigurerDirectRabbitListenerContainerFactoryConfigurer,您可以使用它来初始化SimpleRabbitListenerContainerFactoryDirectRabbitListenerContainerFactory具有与自动配置使用的工厂相同的设置。

[提示]提示

您选择的容器类型无关紧要。这两个beans由自动配置公开。

例如,以下配置类公开了另一个使用特定MessageConverter的工厂:

@Configuration
static class RabbitConfiguration {

	@Bean
	public SimpleRabbitListenerContainerFactory myFactory(
			SimpleRabbitListenerContainerFactoryConfigurer configurer) {
		SimpleRabbitListenerContainerFactory factory =
				new SimpleRabbitListenerContainerFactory();
		configurer.configure(factory, connectionFactory);
		factory.setMessageConverter(myMessageConverter());
		return factory;
	}

}

然后你可以在任何@RabbitListener - 注释方法中使用工厂,如下所示:

@Component
public class MyBean {

	@RabbitListener(queues = "someQueue", containerFactory="myFactory")
	public void processMessage(String content) {
		// ...
	}

}

您可以启用重试来处理侦听器抛出异常的情况。默认情况下,使用RejectAndDontRequeueRecoverer,但您可以定义自己的MessageRecoverer当重试耗尽时,如果代理配置了这样做,则拒绝该消息并将其丢弃或路由到死信交换。默认情况下,禁用重试。您还可以通过声明RabbitRetryTemplateCustomizer bean以编程方式自定义RetryTemplate

[重要]重要

默认情况下,如果禁用重试并且侦听器抛出异常,则会无限期地重试传递。您可以通过两种方式修改此行为:将defaultRequeueRejected属性设置为false,以便尝试零重新传递或抛出AmqpRejectAndDontRequeueException以表示应拒绝该消息。后者是启用重试并且达到最大传递尝试次数时使用的机制。

33.3 Apache Kafka支持

通过提供spring-kafka项目的自动配置来支持Apache Kafka

Kafka配置由spring.kafka.*中的外部配置属性控制。例如,您可以在application.properties中声明以下部分:

spring.kafka.bootstrap-servers=localhost:9092
spring.kafka.consumer.group-id=myGroup
[提示]提示

要在启动时创建主题,请添加bean类型NewTopic如果主题已存在,则忽略bean。

有关KafkaProperties 更多支持选项,请参阅

33.3.1发送消息

Spring的KafkaTemplate是自动配置的,您可以直接在自己的beans中自动装配它,如下例所示:

@Component
public class MyBean {

	private final KafkaTemplate kafkaTemplate;

	@Autowired
	public MyBean(KafkaTemplate kafkaTemplate) {
		this.kafkaTemplate = kafkaTemplate;
	}

	// ...

}
[注意]注意

如果定义了属性spring.kafka.producer.transaction-id-prefix,则会自动配置KafkaTransactionManager此外,如果定义了RecordMessageConverter bean,它将自动与自动配置的KafkaTemplate相关联。

33.3.2接收消息

当存在Apache Kafka基础结构时,可以使用@KafkaListener注释任何bean以创建侦听器端点。如果未定义KafkaListenerContainerFactory,则会使用spring.kafka.listener.*中定义的键自动配置默认值。

以下组件在someTopic主题上创建一个侦听器端点:

@Component
public class MyBean {

	@KafkaListener(topics = "someTopic")
	public void processMessage(String content) {
		// ...
	}

}

如果定义了KafkaTransactionManager bean,它将自动关联到容器工厂。同样,如果定义了RecordMessageConverterErrorHandlerAfterRollbackProcessor bean,它将自动与默认工厂相关联。

[提示]提示

自定义ChainedKafkaTransactionManager必须标记为@Primary,因为它通常会引用自动配置的KafkaTransactionManager bean。

33.3.3卡夫卡流

Apache Kafka的Spring提供了一个工厂bean来创建一个StreamsBuilder对象并管理其流的生命周期。Spring Boot只要kafka-streams在类路径上,并且通过@EnableKafkaStreams注释启用Kafka Streams,就会自动配置所需的KafkaStreamsConfiguration bean。

启用Kafka Streams意味着必须设置应用程序ID和引导程序服务器。可以使用spring.kafka.streams.application-id配置前者,如果未设置,则默认为spring.application.name后者可以全局设置或专门为流而重写。

使用专用属性可以使用其他几个属性; 可以使用spring.kafka.streams.properties命名空间设置其他任意Kafka属性。有关更多信息另请参见第33.3.4节“其他Kafka属性”

要使用工厂bean,只需将StreamsBuilder连接到@Bean,如下例所示:

@Configuration
@EnableKafkaStreams
static class KafkaStreamsExampleConfiguration {

	@Bean
	public KStream<Integer, String> kStream(StreamsBuilder streamsBuilder) {
		KStream<Integer, String> stream = streamsBuilder.stream("ks1In");
		stream.map((k, v) -> new KeyValue<>(k, v.toUpperCase())).to("ks1Out",
				Produced.with(Serdes.Integer(), new JsonSerde<>()));
		return stream;
	}

}

默认情况下,由其创建的StreamBuilder对象管理的流将自动启动。您可以使用spring.kafka.streams.auto-startup属性自定义此行为。

33.3.4附加Kafka属性

自动配置支持的属性显示在 附录A,常见应用程序属性中请注意,在大多数情况下,这些属性(连字符或camelCase)直接映射到Apache Kafka点状属性。有关详细信息,请参阅Apache Kafka文档。

这些属性中的前几个适用于所有组件(生产者,使用者,管理员和流),但如果您希望使用不同的值,则可以在组件级别指定。Apache Kafka指定重要性为HIGH,MEDIUM或LOW的属性。Spring Boot auto-configuration支持所有HIGH重要性属性,一些选定的MEDIUM和LOW属性,以及任何没有默认值的属性。

只有Kafka支持的属性的一部分可以通过KafkaProperties类直接获得。如果您希望使用不直接支持的其他属性配置生产者或使用者,请使用以下属性:

spring.kafka.properties.prop.one=first
spring.kafka.admin.properties.prop.two=second
spring.kafka.consumer.properties.prop.three=third
spring.kafka.producer.properties.prop.four=fourth
spring.kafka.streams.properties.prop.five=fifth

这将常见的prop.one Kafka属性设置为first(适用于生产者,消费者和管理员),将prop.two admin属性设置为second,将prop.three使用者属性设置为thirdprop.four生产者属性为fourthprop.five流属性为fifth

您还可以按如下方式配置Spring Kafka JsonDeserializer

spring.kafka.consumer.value-deserializer=org.springframework.kafka.support.serializer.JsonDeserializer
spring.kafka.consumer.properties.spring.json.value.default.type=com.example.Invoice
spring.kafka.consumer.properties.spring.json.trusted.packages=com.example,org.acme

同样,您可以禁用在标头中发送类型信息的JsonSerializer默认行为:

spring.kafka.producer.value-serializer=org.springframework.kafka.support.serializer.JsonSerializer
spring.kafka.producer.properties.spring.json.add.type.headers=false
[重要]重要

以这种方式设置的属性会覆盖Spring Boot明确支持的任何配置项。

34.使用RestTemplate调用REST服务

如果需要从应用程序调用远程REST服务,可以使用Spring Framework的RestTemplate类。由于RestTemplate实例在使用之前通常需要进行自定义,因此Spring Boot不提供任何单个自动配置RestTemplate bean。但是,它会自动配置RestTemplateBuilder,可在需要时用于创建RestTemplate实例。自动配置的RestTemplateBuilder确保将合理的HttpMessageConverters应用于RestTemplate实例。

以下代码显示了一个典型示例:

@Service
public class MyService {

	private final RestTemplate restTemplate;

	public MyService(RestTemplateBuilder restTemplateBuilder) {
		this.restTemplate = restTemplateBuilder.build();
	}

	public Details someRestCall(String name) {
		return this.restTemplate.getForObject("/{name}/details", Details.class, name);
	}

}
[提示]提示

RestTemplateBuilder包含许多可用于快速配置RestTemplate的有用方法。例如,要添加BASIC auth支持,可以使用builder.basicAuthentication("user", "password").build()

34.1 RestTemplate自定义

RestTemplate自定义有三种主要方法,具体取决于您希望自定义应用的广泛程度。

要使任何自定义的范围尽可能窄,请注入自动配置的RestTemplateBuilder,然后根据需要调用其方法。每个方法调用都返回一个新的RestTemplateBuilder实例,因此自定义只会影响构建器的这种使用。

要进行应用程序范围的附加自定义,请使用RestTemplateCustomizer bean。所有这些beans都会自动注册到自动配置的RestTemplateBuilder,并应用于使用它构建的任何模板。

以下示例显示了一个自定义程序,它为除192.168.0.5之外的所有主机配置代理的使用:

static class ProxyCustomizer implements RestTemplateCustomizer {

	@Override
	public void customize(RestTemplate restTemplate) {
		HttpHost proxy = new HttpHost("proxy.example.com");
		HttpClient httpClient = HttpClientBuilder.create()
				.setRoutePlanner(new DefaultProxyRoutePlanner(proxy) {

					@Override
					public HttpHost determineProxy(HttpHost target,
							HttpRequest request, HttpContext context)
							throws HttpException {
						if (target.getHostName().equals("192.168.0.5")) {
							return null;
						}
						return super.determineProxy(target, request, context);
					}

				}).build();
		restTemplate.setRequestFactory(
				new HttpComponentsClientHttpRequestFactory(httpClient));
	}

}

最后,最极端(也很少使用)的选项是创建自己的RestTemplateBuilder bean。这样做会关闭RestTemplateBuilder的自动配置,并阻止使用任何RestTemplateCustomizer beans。

35.使用WebClient调用REST服务

如果您的类路径上有Spring WebFlux,您还可以选择使用WebClient来调用远程REST服务。RestTemplate相比,该客户端具有更多功能感并且完全被动。您可以在Spring框架文档的专用部分中了解有关WebClient的更多信息

Spring Boot为您创建并预先配置WebClient.Builder; 强烈建议将其注入您的组件并使用它来创建WebClient实例。Spring Boot正在配置该构建器以共享HTTP资源,以与服务器相同的方式反映编解码器设置(请参阅 WebFlux HTTP编解码器自动配置)等。

以下代码显示了一个典型示例:

@Service
public class MyService {

	private final WebClient webClient;

	public MyService(WebClient.Builder webClientBuilder) {
		this.webClient = webClientBuilder.baseUrl("http://example.org").build();
	}

	public Mono<Details> someRestCall(String name) {
		return this.webClient.get().uri("/{name}/details", name)
						.retrieve().bodyToMono(Details.class);
	}

}

35.1 WebClient运行时

Spring Boot将自动检测用于驱动WebClientClientHttpConnector,具体取决于应用程序类路径上可用的库。目前,支持Reactor Netty和Jetty RS客户端。

spring-boot-starter-webflux启动程序默认依赖于io.projectreactor.netty:reactor-netty,它带来了服务器和客户端实现。如果您选择将Jetty用作反应式服务器,则应该在Jetty Reactive HTTP客户端库org.eclipse.jetty:jetty-reactive-httpclient上添加依赖项。对服务器和客户端使用相同的技术具有优势,因为它将自动在客户端和服务器之间共享HTTP资源。

开发人员可以通过提供自定义ReactorResourceFactoryJettyResourceFactory bean覆盖Jetty和Reactor Netty的资源配置 - 这将应用于客户端和服务器。

如果您希望覆盖客户端的该选项,您可以定义自己的ClientHttpConnector bean并完全控制客户端配置。

您可以在Spring框架参考文档中了解有关WebClient配置选项的更多信息

35.2 WebClient自定义

WebClient自定义有三种主要方法,具体取决于您希望自定义应用的广泛程度。

要使任何自定义的范围尽可能窄,请注入自动配置的WebClient.Builder,然后根据需要调用其方法。WebClient.Builder实例是有状态的:构建器上的任何更改都会反映在随后使用它创建的所有客户端中。如果要使用相同的构建器创建多个客户端,还可以考虑使用WebClient.Builder other = builder.clone();克隆构建器。

要对所有WebClient.Builder实例进行应用程序范围的附加自定义,您可以声明WebClientCustomizer beans并在注入点本地更改WebClient.Builder

最后,您可以回退到原始API并使用WebClient.create()在这种情况下,不应用自动配置或WebClientCustomizer

36.验证

只要JSR-303实现(例如Hibernate验证器)在类路径上,Bean验证1.1支持的方法验证功能就会自动启用。这使得bean方法可以使用javax.validation对其参数和/或返回值的约束进行注释。具有此类带注释方法的目标类需要在类型级别使用@Validated注释进行注释,以便搜索其内联约束注释的方法。

例如,以下服务触发第一个参数的验证,确保其大小在8到10之间:

@Service
@Validated
public class MyBean {

	public Archive findByCodeAndAuthor(@Size(min = 8, max = 10) String code,
			Author author) {
		...
	}

}

37.发送电子邮件

Spring框架提供了使用JavaMailSender界面发送电子邮件的简单抽象,Spring Boot为其提供了自动配置以及启动器模块。

[提示]提示

有关如何使用JavaMailSender的详细说明,请参阅参考文档

如果spring.mail.host和相关库(由spring-boot-starter-mail定义)可用,则创建默认值JavaMailSender(如果不存在)。可以通过spring.mail命名空间中的配置项进一步自定义发件人。有关MailProperties详细信息,请参阅

特别是,某些默认超时值是无限的,您可能希望更改它以避免线程被无响应的邮件服务器阻塞,如以下示例所示:

spring.mail.properties.mail.smtp.connectiontimeout=5000
spring.mail.properties.mail.smtp.timeout=3000
spring.mail.properties.mail.smtp.writetimeout=5000

也可以使用JNDI中的现有Session配置JavaMailSender

spring.mail.jndi-name=mail/Session

设置jndi-name时,它优先于所有其他与会话相关的设置。

38.使用JTA的分布式事务

Spring Boot通过使用AtomikosBitronix 嵌入式事务管理器支持跨多个XA资源的分布式JTA事务部署到合适的Java EE Application Server时,也支持JTA事务。

检测到JTA环境时,Spring的JtaTransactionManager用于管理事务。自动配置的JMS,DataSource和JPA beans已升级为支持XA事务。您可以使用标准Spring惯用语(例如@Transactional)来参与分布式事务。如果您在JTA环境中并且仍想使用本地事务,则可以将spring.jta.enabled属性设置为false以禁用JTA自动配置。

38.1使用Atomikos事务管理器

Atomikos是一个流行的开源事务管理器,可以嵌入到您的Spring Boot应用程序中。您可以使用spring-boot-starter-jta-atomikos Starter引入相应的Atomikos库。Spring Boot自动配置Atomikos并确保将适当的depends-on设置应用于Spring beans以正确启动和关闭顺序。

默认情况下,Atomikos事务日志将写入应用程序主目录(应用程序jar文件所在的目录)中的transaction-logs目录。您可以通过在application.properties文件中设置spring.jta.log-dir属性来自定义此目录的位置。spring.jta.atomikos.properties开头的属性也可用于自定义Atomikos UserTransactionServiceImp有关 完整的详细信息,请参阅 AtomikosProperties Javadoc

[注意]注意

为确保多个事务管理器可以安全地协调相同的资源管理器,必须为每个Atomikos实例配置唯一ID。默认情况下,此ID是运行Atomikos的计算机的IP地址。要确保生产中的唯一性,应为应用程序的每个实例配置具有不同值的spring.jta.transaction-manager-id属性。

38.2使用Bitronix事务管理器

Bitronix是一种流行的开源JTA事务管理器实现。您可以使用spring-boot-starter-jta-bitronix启动程序将适当的Bitronix依赖项添加到项目中。与Atomikos一样,Spring Boot自动配置Bitronix并对beans进行后处理,以确保启动和关闭顺序正确。

默认情况下,Bitronix事务日志文件(part1.btmpart2.btm)将写入应用程序主目录中的transaction-logs目录。您可以通过设置spring.jta.log-dir属性来自定义此目录的位置。spring.jta.bitronix.properties开头的属性也绑定到bitronix.tm.Configuration bean,允许完全自定义。有关详细信息,请参阅 Bitronix文档

[注意]注意

为确保多个事务管理器可以安全地协调相同的资源管理器,必须为每个Bitronix实例配置唯一的ID。默认情况下,此ID是运行Bitronix的计算机的IP地址。为了确保生产的唯一性,您应该为应用程序的每个实例配置不同值的spring.jta.transaction-manager-id属性。

38.3使用Java EE托管事务管理器

如果将Spring Boot应用程序打包为warear文件并将其部署到Java EE应用程序服务器,则可以使用应用程序服务器的内置事务管理器。Spring Boot尝试通过查看常见的JNDI位置(java:comp/UserTransactionjava:comp/TransactionManager等)来自动配置事务管理器。如果使用应用程序服务器提供的事务服务,通常还需要确保所有资源都由服务器管理并通过JNDI公开。Spring Boot尝试通过在JNDI路径(java:/JmsXAjava:/XAConnectionFactory)查找ConnectionFactory来自动配置JMS,并且可以使用spring.datasource.jndi-name属性来配置DataSourcespring.datasource.jndi-name属性 配置{1801 } /}。

38.4混合XA和非XA JMS连接

使用JTA时,主JMS ConnectionFactory bean可识别XA并参与分布式事务。在某些情况下,您可能希望使用非XA ConnectionFactory处理某些JMS消息。例如,您的JMS处理逻辑可能需要比XA超时更长的时间。

如果你想使用非XA ConnectionFactory,你可以注入nonXaJmsConnectionFactory bean而不是@Primary jmsConnectionFactory bean。为了保持一致性,使用bean别名xaJmsConnectionFactory也提供了jmsConnectionFactory bean。

以下示例显示如何注入ConnectionFactory实例:

// Inject the primary (XA aware) ConnectionFactory
@Autowired
private ConnectionFactory defaultConnectionFactory;

// Inject the XA aware ConnectionFactory (uses the alias and injects the same as above)
@Autowired
@Qualifier("xaJmsConnectionFactory")
private ConnectionFactory xaConnectionFactory;

// Inject the non-XA aware ConnectionFactory
@Autowired
@Qualifier("nonXaJmsConnectionFactory")
private ConnectionFactory nonXaConnectionFactory;

38.5支持替代嵌入式事务管理器

XAConnectionFactoryWrapperXADataSourceWrapper接口可用于支持替代嵌入式事务经理。接口负责包装XAConnectionFactoryXADataSource beans并将它们公开为常规ConnectionFactoryDataSource beans,它们透明地注册分布式事务。如果您在ApplicationContext中注册了JtaTransactionManager bean和相应的XA包装beans,则DataSource和JMS自动配置将使用JTA变体。

BitronixXAConnectionFactoryWrapperBitronixXADataSourceWrapper 提供了如何编写XA包装很好的例子。

39. Hazelcast

如果Hazelcast在类路径上并找到合适的配置,Spring Boot会自动配置您可以在应用程序中注入的HazelcastInstance

如果你定义com.hazelcast.config.Config bean,Spring Boot使用它。如果您的配置定义了实例名称,Spring Boot会尝试查找现有实例而不是创建新实例。

您还可以指定要通过配置使用的hazelcast.xml配置文件,如以下示例所示:

spring.hazelcast.config=classpath:config/my-hazelcast.xml

否则,Spring Boot会尝试从默认位置找到Hazelcast配置:工作目录中的hazelcast.xml或类路径的根目录。我们还检查是否设置了hazelcast.config系统属性。有关更多详细信息,请参阅 Hazelcast文档

如果类路径中存在hazelcast-client,则Spring Boot首先尝试通过检查以下配置选项来创建客户端:

  • 存在com.hazelcast.client.config.ClientConfig bean。
  • spring.hazelcast.config属性定义的配置文件。
  • hazelcast.client.config系统属性的存在。
  • 工作目录中的hazelcast-client.xml或类路径的根目录。
[注意]注意

Spring Boot还为Hazelcast提供了 明确的缓存支持如果启用了缓存,HazelcastInstance将自动包含在CacheManager实现中。

40. Quartz Scheduler

Spring Boot为使用Quartz调度程序提供了一些便利 ,包括spring-boot-starter-quartz“Starter”。如果Quartz可用,则自动配置Scheduler(通过SchedulerFactoryBean抽象)。

自动选取以下类型的Beans并与Scheduler相关联:

  • JobDetail:定义一个特定的工作。可以使用JobBuilder API构建JobDetail个实例。
  • Calendar.
  • Trigger:定义何时触发特定作业。

默认情况下,使用内存中的JobStore但是,如果应用程序中有DataSource bean并且相应地配置了spring.quartz.job-store-type属性,则可以配置基于JDBC的存储,如以下示例所示:

spring.quartz.job-store-type=jdbc

使用JDBC存储时,可以在启动时初始化架构,如以下示例所示:

spring.quartz.jdbc.initialize-schema=always
[警告]警告

默认情况下,使用Quartz库提供的标准脚本检测并初始化数据库。这些脚本删除现有表,在每次重启时删除所有触发器。也可以通过设置spring.quartz.jdbc.schema属性来提供自定义脚本。

要让Quartz使用DataSource而不是应用程序的主DataSource,请声明DataSource bean,用@QuartzDataSource注释其@Bean方法。这样做可确保SchedulerFactoryBean和架构初始化都使用特定于Quartz的DataSource

默认情况下,配置创建的作业不会覆盖已从永久性作业存储区读取的已注册作业。要启用覆盖现有作业定义,请设置spring.quartz.overwrite-existing-jobs属性。

可以使用spring.quartz属性和SchedulerFactoryBeanCustomizer beans自定义Quartz Scheduler配置,这允许程序化SchedulerFactoryBean自定义。可以使用spring.quartz.properties.*自定义高级Quartz配置属性。

[注意]注意

特别是,Executor bean与调度程序无关,因为Quartz提供了一种通过spring.quartz.properties配置调度程序的方法。如果需要自定义任务执行程序,请考虑实现SchedulerFactoryBeanCustomizer

作业可以定义setter以注入数据映射属性。常规beans也可以以类似的方式注入,如以下示例所示:

public class SampleJob extends QuartzJobBean {

	private MyService myService;

	private String name;

	// Inject "MyService" bean
	public void setMyService(MyService myService) { ... }

	// Inject the "name" job data property
	public void setName(String name) { ... }

	@Override
	protected void executeInternal(JobExecutionContext context)
			throws JobExecutionException {
		...
	}

}

41.任务执行和调度

在上下文中没有TaskExecutor bean的情况下,Spring Boot使用合理的默认值自动配置ThreadPoolTaskExecutor,这些默认值可以自动与异步任务执行相关联(@EnableAsync)和Spring MVC异步请求处理。

线程池使用8个核心线程,可根据负载增长和缩小。可以使用spring.task.execution命名空间对这些默认设置进行微调,如以下示例所示:

spring.task.execution.pool.max-threads=16
spring.task.execution.pool.queue-capacity=100
spring.task.execution.pool.keep-alive=10s

这会将线程池更改为使用有界队列,以便在队列满(100个任务)时,线程池增加到最多16个线程。当线程在闲置10秒(而不是默认为60秒)时回收线程时,池的收缩会更加激进。

如果需要与计划任务执行(@EnableScheduling)相关联,也可以自动配置ThreadPoolTaskScheduler默认情况下,线程池使用一个线程,并且可以使用spring.task.scheduling命名空间对这些设置进行微调。

如果需要创建自定义执行程序或调度程序,则在上下文中可以使用TaskExecutorBuilder bean和TaskSchedulerBuilder bean。

42. Spring Integration

Spring Boot为使用Spring集成提供了一些便利,包括spring-boot-starter-integration“Starter”。Spring集成提供了有关消息传递以及其他传输(如HTTP,TCP等)的抽象。如果类路径上有Spring Integration,则通过@EnableIntegration注释初始化它。

Spring Boot还配置由附加Spring Integration模块的存在触发的一些功能。如果spring-integration-jmx也在类路径上,则通过JMX发布消息处理统计信息。如果spring-integration-jdbc可用,则可以在启动时创建默认数据库模式,如以下行所示:

spring.integration.jdbc.initialize-schema=always

有关 详细信息,请参阅 IntegrationAutoConfigurationIntegrationProperties类。

默认情况下,如果存在千分尺meterRegistry bean,则千分尺将管理Spring Integration指标。如果您希望使用旧版Spring Integration指标,请在应用程序上下文中添加DefaultMetricsFactory bean。

43. Spring Session

Spring Boot为各种数据存储提供Spring Session自动配置。构建Servlet Web应用程序时,可以自动配置以下存储:

  • JDBC
  • Redis
  • Hazelcast
  • MongoDB的

构建响应式Web应用程序时,可以自动配置以下存储:

  • Redis
  • MongoDB的

如果类路径中存在单个Spring Session模块,则Spring Boot会自动使用该存储实现。如果您有多个实现,则必须选择StoreType要用于存储会话的实现。例如,要使用JDBC作为后端存储,您可以按如下方式配置应用程序:

spring.session.store-type=jdbc
[提示]提示

您可以通过将store-type设置为none来禁用Spring Session。

每个商店都有特定的附加设置。例如,可以为JDBC存储定制表的名称,如以下示例所示:

spring.session.jdbc.table-name=SESSIONS

要设置会话超时,可以使用spring.session.timeout属性。如果未设置该属性,则自动配置将回退到server.servlet.session.timeout的值。

44.对JMX的监测和管理

Java Management Extensions(JMX)提供了一种监视和管理应用程序的标准机制。默认情况下,Spring Boot会创建一个ID为mbeanServerMBeanServer bean,并公开使用Spring JMX注释(@ManagedResource注释的任何beans, @ManagedAttribute@ManagedOperation)。

有关JmxAutoConfiguration 详细信息,请参阅 课程。

45.测试

Spring Boot提供了许多实用程序和注释来帮助您测试应用程序。测试支持由两个模块提供:spring-boot-test包含核心项,spring-boot-test-autoconfigure支持测试的自动配置。

大多数开发人员使用spring-boot-starter-test“Starter”,它导入Spring Boot测试模块以及JUnit,AssertJ,Hamcrest和许多其他有用的库。

45.1测试范围依赖性

spring-boot-starter-test“Starter”(在test scope中)包含以下提供的库:

  • JUnit:单元测试Java应用程序的事实标准。
  • Spring测试和Spring Boot测试:Spring Boot应用程序的实用程序和集成测试支持。
  • AssertJ:一个流畅的断言库。
  • Hamcrest:匹配器对象库(也称为约束或谓词)。
  • Mockito:一个Java 模拟框架。
  • JSONassert:JSON的断言库。
  • JsonPath:JSON的XPath。

我们通常发现这些常用库在编写测试时很有用。如果这些库不适合您的需求,您可以添加自己的其他测试依赖项。

45.2测试Spring应用程序

依赖注入的一个主要优点是它应该使您的代码更容易进行单元测试。您可以使用new运算符实例化对象,甚至不涉及Spring。您还可以使用模拟对象而不是真正的依赖项。

通常,您需要超越单元测试并开始集成测试(使用Spring ApplicationContext)。能够在不需要部署应用程序或需要连接到其他基础架构的情况下执行集成测试非常有用。

Spring框架包括用于此类集成测试的专用测试模块。您可以直接向org.springframework:spring-test声明依赖关系,或使用spring-boot-starter-test“Starter”将其传递给它。

如果您之前未使用过spring-test模块,则应首先阅读Spring框架参考文档相关部分

45.3测试Spring Boot应用程序

Spring Boot应用程序是Spring ApplicationContext,因此除了通常使用vanilla Spring上下文所做的测试之外,没有什么特别的要做。

[注意]注意

仅当您使用SpringApplication创建外部属性,日志记录和Spring Boot的其他功能时,才会默认安装在上下文中。

Spring Boot提供了@SpringBootTest注释,当您需要Spring引导功能时,可以将其用作标准spring-test @ContextConfiguration注释的替代。注释的工作原理是 通过SpringApplication创建测试中使用的ApplicationContext除了@SpringBootTest之外,还提供了许多其他注释来 测试应用程序的更具体的切片

[提示]提示

如果您使用的是JUnit 4,请不要忘记在测试中添加@RunWith(SpringRunner.class),否则注释将被忽略。如果您正在使用JUnit 5,则无需将等效的@ExtendWith(SpringExtension)添加为@SpringBootTest,而其他@…Test注释已经使用它进行注释。

默认情况下,@SpringBootTest将无法启动服务器。您可以使用@SpringBootTestwebEnvironment属性来进一步优化测试的运行方式:

  • MOCK(默认):加载网络ApplicationContext并提供模拟网络环境。使用此批注时,不会启动嵌入式服务器。如果您的类路径上没有Web环境,则此模式将透明地回退到创建常规非Web ApplicationContext它可以与 @AutoConfigureMockMvc@AutoConfigureWebTestClient一起用于基于模拟的Web应用程序测试。
  • RANDOM_PORT:加载WebServerApplicationContext并提供真实的网络环境。嵌入式服务器启动并在随机端口上侦听。
  • DEFINED_PORT:加载WebServerApplicationContext并提供真实的网络环境。嵌入式服务器启动并侦听定义的端口(来自您的application.properties)或默认端口8080
  • NONE:使用SpringApplication加载ApplicationContext但不提供 任何网络环境(模拟或其他)。
[注意]注意

如果您的测试是@Transactional,则默认情况下会在每个测试方法的末尾回滚事务。但是,当使用RANDOM_PORTDEFINED_PORT的这种安排隐式地提供真正的servlet环境时,HTTP客户端和服务器在单独的线程中运行,因此在单独的事务中运行。在这种情况下,在服务器上启动的任何事务都不会回滚。

[注意]注意

如果您的应用程序使用不同的管理服务器端口,@SpringBootTestwebEnvironment = WebEnvironment.RANDOM_PORT也将在单独的随机端口上启动管理服务器。

45.3.1检测Web应用程序类型

如果Spring MVC可用,则配置基于MVC的常规应用程序上下文。如果您只有Spring WebFlux,我们将检测到并配置基于WebFlux的应用程序上下文。

如果两者都存在,Spring MVC优先。如果要在此方案中测试响应式Web应用程序,则必须设置spring.main.web-application-type属性:

@RunWith(SpringRunner.class)
@SpringBootTest(properties = "spring.main.web-application-type=reactive")
public class MyWebFluxTests { ... }

45.3.2检测测试配置

如果您熟悉Spring测试框架,则可能习惯使用@ContextConfiguration(classes=…​)来指定要加载的Spring @Configuration或者,您可能经常在测试中使用嵌套的@Configuration类。

在测试Spring Boot应用程序时,通常不需要这样做。只要您没有明确定义一个,Spring Boot的@*Test注释就会自动搜索您的主要配置。

搜索算法从包含测试的包开始工作,直到找到使用@SpringBootApplication@SpringBootConfiguration注释的类。只要您以合理的方式构建代码,通常就会找到主要配置。

[注意]注意

如果使用 测试批注来测试应用程序的更具体的片段,则应避免在main方法的应用程序类中添加特定于特定区域的配置设置

@SpringBootApplication的基础组件扫描配置定义了排除过滤器,用于确保切片按预期工作。如果您在@SpringBootApplication - 带注释的类上使用明确的@ComponentScan指令,请注意这些过滤器将被禁用。如果您正在使用切片,则应再次定义它们。

如果要自定义主要配置,可以使用嵌套的@TestConfiguration类。与嵌套的@Configuration类不同,它将用于代替应用程序的主要配置,除了应用程序的主要配置之外,还使用嵌套的@TestConfiguration类。

[注意]注意

Spring的测试框架在测试之间缓存应用程序上下文。因此,只要您的测试共享相同的配置(无论如何发现),加载上下文的潜在耗时过程只发生一次。

45.3.3排除测试配置

如果您的应用程序使用组件扫描(例如,如果您使用@SpringBootApplication@ComponentScan),您可能会发现仅为特定测试创建的顶级配置类会意外地在任何地方进行检索。

如前所述,@TestConfiguration可用于测试的内部类以自定义主要配置。前面所看到的,1941年{/}可以在一个内部类的测试的用于定制的主配置。当放置在顶级类时,@TestConfiguration表示不应通过扫描拾取src/test/java中的类。然后,您可以在需要的位置显式导入该类,如以下示例所示:

@RunWith(SpringRunner.class)
@SpringBootTest
@Import(MyTestsConfiguration.class)
public class MyTests {

	@Test
	public void exampleTest() {
		...
	}

}
[注意]注意

如果您直接使用@ComponentScan(即不通过@SpringBootApplication),则需要使用TypeExcludeFilter注册。有关详细信息,请参阅 Javadoc

45.3.4使用模拟环境进行测试

默认情况下,@SpringBootTest无法启动服务器。如果您要针对此模拟环境测试Web端点,则可以另外进行配置 MockMvc,如以下示例所示:

import org.junit.Test;
import org.junit.runner.RunWith;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;

import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

@RunWith(SpringRunner.class)
@SpringBootTest
@AutoConfigureMockMvc
public class MockMvcExampleTests {

	@Autowired
	private MockMvc mvc;

	@Test
	public void exampleTest() throws Exception {
		this.mvc.perform(get("/")).andExpect(status().isOk())
				.andExpect(content().string("Hello World"));
	}

}
[提示]提示

如果您只想关注网络层而不是开始一个完整的ApplicationContext,请考虑 使用@WebMvcTest

或者,您可以配置a WebTestClient,如以下示例所示:

import org.junit.Test;
import org.junit.runner.RunWith;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.reactive.AutoConfigureWebTestClient;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.reactive.server.WebTestClient;

@RunWith(SpringRunner.class)
@SpringBootTest
@AutoConfigureWebTestClient
public class MockWebTestClientExampleTests {

	@Autowired
	private WebTestClient webClient;

	@Test
	public void exampleTest() {
		this.webClient.get().uri("/").exchange().expectStatus().isOk()
				.expectBody(String.class).isEqualTo("Hello World");
	}

}

45.3.5使用正在运行的服务器进行测试

如果您需要启动完整运行的服务器,我们建议您使用随机端口。如果使用@SpringBootTest(webEnvironment=WebEnvironment.RANDOM_PORT),则每次测试运行时随机选择一个可用端口。

@LocalServerPort注释可用于 注入测试中使用的实际端口为方便起见,需要对启动的服务器进行REST调用的测试还可以@Autowire a WebTestClient,它解析了与正在运行的服务器的相对链接,并附带了用于验证响应的专用API,如以下示例所示:

import org.junit.Test;
import org.junit.runner.RunWith;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.reactive.server.WebTestClient;

@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
public class RandomPortWebTestClientExampleTests {

	@Autowired
	private WebTestClient webClient;

	@Test
	public void exampleTest() {
		this.webClient.get().uri("/").exchange().expectStatus().isOk()
				.expectBody(String.class).isEqualTo("Hello World");
	}

}

此设置在类路径上需要spring-webflux如果您不能或不会添加webflux,Spring Boot还提供TestRestTemplate设施:

import org.junit.Test;
import org.junit.runner.RunWith;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.test.context.junit4.SpringRunner;

import static org.assertj.core.api.Assertions.assertThat;

@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
public class RandomPortTestRestTemplateExampleTests {

	@Autowired
	private TestRestTemplate restTemplate;

	@Test
	public void exampleTest() {
		String body = this.restTemplate.getForObject("/", String.class);
		assertThat(body).isEqualTo("Hello World");
	}

}

45.3.6使用JMX

当测试上下文框架缓存上下文时,默认情况下禁用JMX以防止相同的组件在同一域上注册。如果此类测试需要访问MBeanServer,请考虑将其标记为脏:

@RunWith(SpringRunner.class)
@SpringBootTest(properties = "spring.jmx.enabled=true")
@DirtiesContext
public class SampleJmxTests {

	@Autowired
	private MBeanServer mBeanServer;

	@Test
	public void exampleTest() {
		// ...
	}

}

45.3.7嘲弄和间谍活动Beans

运行测试时,有时需要在应用程序上下文中模拟某些组件。例如,您可能拥有在开发期间不可用的某些远程服务的外观。当您想要模拟在真实环境中可能难以触发的故障时,模拟也很有用。

Spring Boot包含@MockBean注释,可用于为ApplicationContext内的bean定义Mockito模拟。您可以使用注释添加新的beans或替换单个现有的bean定义。注释可以直接用于测试类,测试中的字段或@Configuration类和字段。在字段上使用时,也会注入创建的模拟的实例。模拟beans在每种测试方法后自动重置。

[注意]注意

如果您的测试使用Spring Boot的测试注释之一(例如@SpringBootTest),则会自动启用此功能。要以不同的排列方式使用此功能,必须显式添加侦听器,如以下示例所示:

@TestExecutionListeners(MockitoTestExecutionListener.class)

以下示例使用模拟实现替换现有的RemoteService bean:

import org.junit.*;
import org.junit.runner.*;
import org.springframework.beans.factory.annotation.*;
import org.springframework.boot.test.context.*;
import org.springframework.boot.test.mock.mockito.*;
import org.springframework.test.context.junit4.*;

import static org.assertj.core.api.Assertions.*;
import static org.mockito.BDDMockito.*;

@RunWith(SpringRunner.class)
@SpringBootTest
public class MyTests {

	@MockBean
	private RemoteService remoteService;

	@Autowired
	private Reverser reverser;

	@Test
	public void exampleTest() {
		// RemoteService has been injected into the reverser bean
		given(this.remoteService.someCall()).willReturn("mock");
		String reverse = reverser.reverseSomeCall();
		assertThat(reverse).isEqualTo("kcom");
	}

}

此外,您可以使用@SpyBean将任何现有的bean与Mockito spy包装在一起。有关详细信息,请参阅Javadoc

[注意]注意

虽然Spring的测试框架在测试之间缓存应用程序上下文并重用共享相同配置的测试的上下文,但使用@MockBean@SpyBean会影响缓存密钥,这很可能会增加缓存密钥的数量。上下文。

[提示]提示

如果您使用@SpyBean监视bean并使用@Cacheable方法按名称引用参数,则必须使用-parameters编译应用程序。这可以确保在bean被监视后,参数名称可用于缓存基础结构。

45.3.8自动配置的测试

Spring Boot的自动配置系统适用于应用程序,但有时对于测试来说有点太多了。通常,只需加载测试应用程序“切片”所需的配置部分。例如,您可能希望测试Spring MVC控制器是否正确映射URL,并且您不希望在这些测试中涉及数据库调用,或者您可能想要测试JPA实体,并且您对Web不感兴趣这些测试运行时的图层。

spring-boot-test-autoconfigure模块包括许多可用于自动配置这种“切片”的注释。它们中的每一个都以类似的方式工作,提供@…​Test注释,用于加载ApplicationContext和一个或多个@AutoConfigure…​注释,可用于自定义自动配置设置。

[注意]注意

每个切片都将组件扫描限制为适当的组件,并加载一组非常有限的自动配置类。如果您需要排除其中一个,则大多数@…​Test注释都会提供excludeAutoConfiguration属性。或者,您可以使用@ImportAutoConfiguration#exclude

[注意]注意

不支持在一次测试中使用多个@…​Test注释包含多个“切片”。如果您需要多个“切片”,请选择@…​Test注释之一并手动包含其他“切片”的@AutoConfigure…​注释。

[提示]提示

也可以将@AutoConfigure…​注释与标准@SpringBootTest注释一起使用。如果您对“切片”应用程序不感兴趣,但想要一些自动配置的测试beans,则可以使用此组合。

45.3.9自动配置的JSON测试

要测试该对象JSON序列化和反序列化是否按预期工作,您可以使用@JsonTest注释。@JsonTest自动配置可用的受支持的JSON映射器,它可以是以下库之一:

  • Jackson ObjectMapper,任何@JsonComponent beans和任何Jackson Module s
  • Gson
  • Jsonb
[提示]提示

可以在附录中找到 @JsonTest启用的自动配置列表

如果需要配置自动配置的元素,可以使用@AutoConfigureJsonTesters注释。

Spring Boot包括基于AssertJ的助手,它们与JSONAssert和JsonPath库一起使用,以检查JSON是否按预期显示。JacksonTesterGsonTesterJsonbTesterBasicJsonTester类可分别用于Jackson,Gson,Jsonb和Strings。使用@JsonTest时,测试类上的任何辅助字段都可以是@Autowired以下示例显示了Jackson的测试类:

import org.junit.*;
import org.junit.runner.*;
import org.springframework.beans.factory.annotation.*;
import org.springframework.boot.test.autoconfigure.json.*;
import org.springframework.boot.test.context.*;
import org.springframework.boot.test.json.*;
import org.springframework.test.context.junit4.*;

import static org.assertj.core.api.Assertions.*;

@RunWith(SpringRunner.class)
@JsonTest
public class MyJsonTests {

	@Autowired
	private JacksonTester<VehicleDetails> json;

	@Test
	public void testSerialize() throws Exception {
		VehicleDetails details = new VehicleDetails("Honda", "Civic");
		// Assert against a `.json` file in the same package as the test
		assertThat(this.json.write(details)).isEqualToJson("expected.json");
		// Or use JSON path based assertions
		assertThat(this.json.write(details)).hasJsonPathStringValue("@.make");
		assertThat(this.json.write(details)).extractingJsonPathStringValue("@.make")
				.isEqualTo("Honda");
	}

	@Test
	public void testDeserialize() throws Exception {
		String content = "{\"make\":\"Ford\",\"model\":\"Focus\"}";
		assertThat(this.json.parse(content))
				.isEqualTo(new VehicleDetails("Ford", "Focus"));
		assertThat(this.json.parseObject(content).getMake()).isEqualTo("Ford");
	}

}
[注意]注意

JSON帮助程序类也可以直接用于标准单元测试。为此,如果不使用@JsonTest,请在@Before方法中调用助手的initFields方法。

45.3.10自动配置的Spring MVC测试

要测试Spring MVC控制器是否按预期工作,请使用@WebMvcTest注释。@WebMvcTest自动配置Spring MVC基础设施并将扫描beans限制为@Controller@ControllerAdvice@JsonComponentConverterGenericConverterFilterWebMvcConfigurerHandlerMethodArgumentResolver使用此注释时,不会扫描常规@Component beans。

[提示]提示

可以在附录中找到 @WebMvcTest启用的自动配置设置列表

[提示]提示

如果您需要注册额外的组件,例如Jackson Module,则可以在测试中使用@Import导入其他配置类。

通常,@WebMvcTest仅限于一个控制器,并与@MockBean结合使用,为所需的协作者提供模拟实现。

@WebMvcTest也自动配置MockMvcMock MVC提供了一种快速测试MVC控制器的强大方法,无需启动完整的HTTP服务器。

[提示]提示

您还可以使用@AutoConfigureMockMvc对其进行注释,以非@WebMvcTest(例如@SpringBootTest)自动配置MockMvc以下示例使用MockMvc

import org.junit.*;
import org.junit.runner.*;
import org.springframework.beans.factory.annotation.*;
import org.springframework.boot.test.autoconfigure.web.servlet.*;
import org.springframework.boot.test.mock.mockito.*;

import static org.assertj.core.api.Assertions.*;
import static org.mockito.BDDMockito.*;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;

@RunWith(SpringRunner.class)
@WebMvcTest(UserVehicleController.class)
public class MyControllerTests {

	@Autowired
	private MockMvc mvc;

	@MockBean
	private UserVehicleService userVehicleService;

	@Test
	public void testExample() throws Exception {
		given(this.userVehicleService.getVehicleDetails("sboot"))
				.willReturn(new VehicleDetails("Honda", "Civic"));
		this.mvc.perform(get("/sboot/vehicle").accept(MediaType.TEXT_PLAIN))
				.andExpect(status().isOk()).andExpect(content().string("Honda Civic"));
	}

}
[提示]提示

如果需要配置自动配置的元素(例如,应该应用servlet过滤器时),可以使用@AutoConfigureMockMvc注释中的属性。

如果您使用HtmlUnit或Selenium,则自动配置还会提供HTMLUnit WebClient bean和/或WebDriver bean。以下示例使用HtmlUnit:

import com.gargoylesoftware.htmlunit.*;
import org.junit.*;
import org.junit.runner.*;
import org.springframework.beans.factory.annotation.*;
import org.springframework.boot.test.autoconfigure.web.servlet.*;
import org.springframework.boot.test.mock.mockito.*;

import static org.assertj.core.api.Assertions.*;
import static org.mockito.BDDMockito.*;

@RunWith(SpringRunner.class)
@WebMvcTest(UserVehicleController.class)
public class MyHtmlUnitTests {

	@Autowired
	private WebClient webClient;

	@MockBean
	private UserVehicleService userVehicleService;

	@Test
	public void testExample() throws Exception {
		given(this.userVehicleService.getVehicleDetails("sboot"))
				.willReturn(new VehicleDetails("Honda", "Civic"));
		HtmlPage page = this.webClient.getPage("/sboot/vehicle.html");
		assertThat(page.getBody().getTextContent()).isEqualTo("Honda Civic");
	}

}
[注意]注意

默认情况下,Spring Boot将WebDriver beans置于特殊的“范围”中,以确保驱动程序在每次测试后退出并注入新实例。如果您不想要此行为,可以将@Scope("singleton")添加到WebDriver @Bean定义中。

[警告]警告

Spring Boot创建的webDriver范围将替换任何用户定义的同名范围。如果您定义自己的webDriver范围,则在使用@WebMvcTest时可能会发现它停止工作。

如果您在类路径上拥有Spring安全性,@WebMvcTest也会扫描WebSecurityConfigurer beans。您可以使用Spring安全性测试支持,而不是完全禁用此类测试的安全性。有关如何使用Spring安全性MockMvc支持的更多详细信息,请参阅本章80,使用Spring安全性操作方法部分进行测试。

[提示]提示

有时写Spring MVC测试是不够的; Spring Boot可以帮助您使用实际服务器运行 完整的端到端测试

45.3.11自动配置Spring WebFlux测试

要测试Spring WebFlux控制器是否按预期工作,您可以使用@WebFluxTest注释。@WebFluxTest自动配置Spring WebFlux基础架构,并将扫描的beans限制为@Controller@ControllerAdvice@JsonComponentConverterGenericConverterWebFluxConfigurer使用@WebFluxTest注释时,不会扫描常规@Component beans。

[提示]提示

可以在附录中找到 @WebFluxTest启用的自动配置列表

[提示]提示

如果需要注册额外的组件,例如Jackson Module,则可以在测试中使用@Import导入其他配置类。

通常,@WebFluxTest仅限于单个控制器,并与@MockBean注释结合使用,为所需的协作者提供模拟实现。

@WebFluxTest也是自动配置 WebTestClient,它提供了一种快速测试WebFlux控制器的强大方法,无需启动完整的HTTP服务器。

[提示]提示

您还可以通过使用@AutoConfigureWebTestClient对其进行注释,在非@WebFluxTest(例如@SpringBootTest)中自动配置WebTestClient以下示例显示了同时使用@WebFluxTestWebTestClient的类:

import org.junit.Test;
import org.junit.runner.RunWith;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.reactive.WebFluxTest;
import org.springframework.http.MediaType;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.reactive.server.WebTestClient;

@RunWith(SpringRunner.class)
@WebFluxTest(UserVehicleController.class)
public class MyControllerTests {

	@Autowired
	private WebTestClient webClient;

	@MockBean
	private UserVehicleService userVehicleService;

	@Test
	public void testExample() throws Exception {
		given(this.userVehicleService.getVehicleDetails("sboot"))
				.willReturn(new VehicleDetails("Honda", "Civic"));
		this.webClient.get().uri("/sboot/vehicle").accept(MediaType.TEXT_PLAIN)
				.exchange()
				.expectStatus().isOk()
				.expectBody(String.class).isEqualTo("Honda Civic");
	}

}
[提示]提示

此设置仅由WebFlux应用程序支持,因为在模拟的Web应用程序中使用WebTestClient目前仅适用于WebFlux。

[注意]注意

@WebFluxTest无法检测通过功能Web框架注册的路由。要在上下文中测试RouterFunction beans,请考虑通过@Import或使用@SpringBootTest自行导入RouterFunction

[提示]提示

有时写Spring WebFlux测试是不够的; Spring Boot可以帮助您使用实际服务器运行 完整的端到端测试

45.3.12自动配置的数据JPA测试

您可以使用@DataJpaTest注释来测试JPA应用程序。默认情况下,它配置内存中的嵌入式数据库,扫描@Entity类,并配置Spring Data JPA存储库。常规@Component beans未加载到ApplicationContext

[提示]提示

可以在附录中找到 @DataJpaTest启用的自动配置设置列表

默认情况下,数据JPA测试是事务性的,并在每次测试结束时回滚。有关 更多详细信息,请参阅Spring框架参考文档中相关部分如果这不是您想要的,您可以为测试或整个类禁用事务管理,如下所示:

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

@RunWith(SpringRunner.class)
@DataJpaTest
@Transactional(propagation = Propagation.NOT_SUPPORTED)
public class ExampleNonTransactionalTests {

}

数据JPA测试也可以注入 TestEntityManager bean,它提供了专门为测试设计的标准JPA EntityManager的替代方案。如果要在@DataJpaTest实例之外使用TestEntityManager,还可以使用@AutoConfigureTestEntityManager注释。如果您需要,也可以使用JdbcTemplate以下示例显示正在使用的@DataJpaTest注释:

import org.junit.*;
import org.junit.runner.*;
import org.springframework.boot.test.autoconfigure.orm.jpa.*;

import static org.assertj.core.api.Assertions.*;

@RunWith(SpringRunner.class)
@DataJpaTest
public class ExampleRepositoryTests {

	@Autowired
	private TestEntityManager entityManager;

	@Autowired
	private UserRepository repository;

	@Test
	public void testExample() throws Exception {
		this.entityManager.persist(new User("sboot", "1234"));
		User user = this.repository.findByUsername("sboot");
		assertThat(user.getUsername()).isEqualTo("sboot");
		assertThat(user.getVin()).isEqualTo("1234");
	}

}

内存中嵌入式数据库通常适用于测试,因为它们速度快且不需要任何安装。但是,如果您更喜欢对真实数据库运行测试,则可以使用@AutoConfigureTestDatabase注释,如以下示例所示:

@RunWith(SpringRunner.class)
@DataJpaTest
@AutoConfigureTestDatabase(replace=Replace.NONE)
public class ExampleRepositoryTests {

	// ...

}

45.3.13自动配置的JDBC测试

@JdbcTest类似于@DataJpaTest,但适用于仅需要DataSource并且不使用Spring数据JDBC的测试。默认情况下,它配置内存中嵌入式数据库和JdbcTemplate常规@Component beans未加载到ApplicationContext

[提示]提示

可以在附录中找到 @JdbcTest启用的自动配置列表

默认情况下,JDBC测试是事务性的,并在每次测试结束时回滚。有关更多详细信息,请参阅Spring框架参考文档中相关部分如果这不是您想要的,您可以禁用测试或整个类的事务管理,如下所示:

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.autoconfigure.jdbc.JdbcTest;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

@RunWith(SpringRunner.class)
@JdbcTest
@Transactional(propagation = Propagation.NOT_SUPPORTED)
public class ExampleNonTransactionalTests {

}

如果您希望测试针对真实数据库运行,则可以使用@AutoConfigureTestDatabase注释,方法与DataJpaTest相同。(参见“ 第45.3.12节,“自动配置的数据JPA测试” “。)

45.3.14自动配置的数据JDBC测试

@DataJdbcTest类似于@JdbcTest,但适用于使用Spring数据JDBC存储库的测试。默认情况下,它配置内存中的嵌入式数据库,JdbcTemplate和Spring数据JDBC存储库。常规@Component beans未加载到ApplicationContext

[提示]提示

可以在附录中找到 @DataJdbcTest启用的自动配置列表

默认情况下,数据JDBC测试是事务性的,并在每次测试结束时回滚。有关 更多详细信息,请参阅Spring框架参考文档中相关部分如果这不是您想要的,您可以禁用测试或整个测试类的事务管理,如 JDBC示例中所示

如果您希望测试针对真实数据库运行,则可以使用@AutoConfigureTestDatabase注释,方法与DataJpaTest相同。(参见“ 第45.3.12节,“自动配置的数据JPA测试” “。)

45.3.15自动配置的jOOQ测试

您可以使用与@JdbcTest类似的方式使用@JooqTest,但是可以使用与jOOQ相关的测试。由于jOOQ严重依赖于与数据库模式相对应的基于Java的模式,因此使用现有的DataSource如果要将其替换为内存数据库,可以使用@AutoConfigureTestDatabase覆盖这些设置。(有关在Spring Boot中使用jOOQ的更多信息,请参阅本章前面的第30.6节,“使用jOOQ”。)常规@Component beans未加载到ApplicationContext

[提示]提示

可以在附录中找到 @JooqTest启用的自动配置列表

@JooqTest配置DSLContext常规@Component beans未加载到ApplicationContext以下示例显示正在使用的@JooqTest注释:

import org.jooq.DSLContext;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.autoconfigure.jooq.JooqTest;
import org.springframework.test.context.junit4.SpringRunner;

@RunWith(SpringRunner.class)
@JooqTest
public class ExampleJooqTests {

	@Autowired
	private DSLContext dslContext;
}

JOOQ测试是事务性的,默认情况下在每个测试结束时回滚。如果这不是您想要的,您可以禁用测试或整个测试类的事务管理,如 JDBC示例中所示

45.3.16自动配置的数据MongoDB测试

您可以使用@DataMongoTest来测试MongoDB应用程序。默认情况下,它配置内存中嵌入的MongoDB(如果可用),配置MongoTemplate,扫描@Document类,并配置Spring Data MongoDB存储库。常规@Component beans未加载到ApplicationContext(有关将MongoDB与Spring Boot一起使用的更多信息,请参阅本章前面的第31.2节”,“MongoDB”。)

[提示]提示

可以在附录中找到 @DataMongoTest启用的自动配置设置列表

以下类显示正在使用的@DataMongoTest注释:

import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.data.mongo.DataMongoTest;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.test.context.junit4.SpringRunner;

@RunWith(SpringRunner.class)
@DataMongoTest
public class ExampleDataMongoTests {

	@Autowired
	private MongoTemplate mongoTemplate;

	//
}

内存中嵌入式MongoDB通常适用于测试,因为它速度快,不需要任何开发人员安装。但是,如果您更喜欢对真正的MongoDB服务器运行测试,则应排除嵌入式MongoDB自动配置,如以下示例所示:

import org.junit.runner.RunWith;
 import org.springframework.boot.autoconfigure.mongo.embedded.EmbeddedMongoAutoConfiguration;
import org.springframework.boot.test.autoconfigure.data.mongo.DataMongoTest;
import org.springframework.test.context.junit4.SpringRunner;

@RunWith(SpringRunner.class)
@DataMongoTest(excludeAutoConfiguration = EmbeddedMongoAutoConfiguration.class)
public class ExampleDataMongoNonEmbeddedTests {

}

45.3.17自动配置的数据Neo4j测试

您可以使用@DataNeo4jTest来测试Neo4j应用程序。默认情况下,它使用内存中嵌入式Neo4j(如果嵌入式驱动程序可用),扫描@NodeEntity类,并配置Spring Data Neo4j存储库。常规@Component beans未加载到ApplicationContext(有关使用带有Spring Boot的Neo4J的更多信息,请参阅本章前面的第31.3节”,“Neo4j”。)

[提示]提示

可以在附录中找到 @DataNeo4jTest启用的自动配置设置列表

以下示例显示了在Spring Boot中使用Neo4J测试的典型设置:

import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.data.neo4j.DataNeo4jTest;
import org.springframework.test.context.junit4.SpringRunner;

@RunWith(SpringRunner.class)
@DataNeo4jTest
public class ExampleDataNeo4jTests {

	@Autowired
	private YourRepository repository;

	//
}

默认情况下,Data Neo4j测试是事务性的,并在每次测试结束时回滚。有关更多详细信息,请参阅Spring框架参考文档中相关部分如果这不是您想要的,您可以禁用测试或整个类的事务管理,如下所示:

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.autoconfigure.data.neo4j.DataNeo4jTest;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

@RunWith(SpringRunner.class)
@DataNeo4jTest
@Transactional(propagation = Propagation.NOT_SUPPORTED)
public class ExampleNonTransactionalTests {

}

45.3.18自动配置的数据Redis测试

您可以使用@DataRedisTest来测试Redis应用程序。默认情况下,它会扫描@RedisHash类并配置Spring Data Redis存储库。常规@Component beans未加载到ApplicationContext(有关将Redis与Spring Boot一起使用的更多信息,请参阅本章前面的第31.1节”,“37 /}”

[提示]提示

可以在附录中找到 @DataRedisTest启用的自动配置设置列表

以下示例显示正在使用的@DataRedisTest注释:

import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.data.redis.DataRedisTest;
import org.springframework.test.context.junit4.SpringRunner;

@RunWith(SpringRunner.class)
@DataRedisTest
public class ExampleDataRedisTests {

	@Autowired
	private YourRepository repository;

	//
}

45.3.19自动配置的数据LDAP测试

您可以使用@DataLdapTest来测试LDAP应用程序。默认情况下,它配置内存中嵌入式LDAP(如果可用),配置LdapTemplate,扫描@Entry类,并配置Spring数据LDAP存储库。常规@Component beans未加载到ApplicationContext(有关将LDAP与Spring Boot一起使用的更多信息,请参阅本章前面的第31.9节”,“LDAP”。)

[提示]提示

可以在附录中找到 @DataLdapTest启用的自动配置设置列表

以下示例显示正在使用的@DataLdapTest注释:

import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.data.ldap.DataLdapTest;
import org.springframework.ldap.core.LdapTemplate;
import org.springframework.test.context.junit4.SpringRunner;

@RunWith(SpringRunner.class)
@DataLdapTest
public class ExampleDataLdapTests {

	@Autowired
	private LdapTemplate ldapTemplate;

	//
}

内存中嵌入式LDAP通常适用于测试,因为它速度快,不需要任何开发人员安装。但是,如果您希望针对真实LDAP服务器运行测试,则应排除嵌入式LDAP自动配置,如以下示例所示:

import org.junit.runner.RunWith;
import org.springframework.boot.autoconfigure.ldap.embedded.EmbeddedLdapAutoConfiguration;
import org.springframework.boot.test.autoconfigure.data.ldap.DataLdapTest;
import org.springframework.test.context.junit4.SpringRunner;

@RunWith(SpringRunner.class)
@DataLdapTest(excludeAutoConfiguration = EmbeddedLdapAutoConfiguration.class)
public class ExampleDataLdapNonEmbeddedTests {

}

45.3.20自动配置的REST客户端

您可以使用@RestClientTest注释来测试REST客户端。默认情况下,它会自动配置Jackson,GSON和Jsonb支持,配置RestTemplateBuilder,并添加对MockRestServiceServer的支持。常规@Component beans未加载到ApplicationContext

[提示]提示

可以在附录中找到 @RestClientTest启用的自动配置设置列表

应使用@RestClientTestvaluecomponents属性指定要测试的特定beans,如以下示例所示:

@RunWith(SpringRunner.class)
@RestClientTest(RemoteVehicleDetailsService.class)
public class ExampleRestClientTest {

	@Autowired
	private RemoteVehicleDetailsService service;

	@Autowired
	private MockRestServiceServer server;

	@Test
	public void getVehicleDetailsWhenResultIsSuccessShouldReturnDetails()
			throws Exception {
		this.server.expect(requestTo("/greet/details"))
				.andRespond(withSuccess("hello", MediaType.TEXT_PLAIN));
		String greeting = this.service.callRestService();
		assertThat(greeting).isEqualTo("hello");
	}

}

45.3.21自动配置的Spring REST文档测试

您可以使用@AutoConfigureRestDocs注释在Mock MVC,REST Assured或WebTestClient的测试中使用Spring REST Docs它消除了对Spring REST Docs中JUnit规则的需求。

@AutoConfigureRestDocs可用于覆盖默认输出目录(如果您使用Maven,则为target/generated-snippets;如果您使用Gradle,则为build/generated-snippets)。它还可用于配置出现在任何已记录的URI中的主机,方案和端口。

使用Mock MVC自动配置Spring REST文档测试

@AutoConfigureRestDocs自定义MockMvc bean以使用Spring REST文档。您可以使用@Autowired注入它并在测试中使用它,就像使用Mock MVC和Spring REST Docs时一样,如下例所示:

import org.junit.Test;
import org.junit.runner.RunWith;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.http.MediaType;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;

import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;

@RunWith(SpringRunner.class)
@WebMvcTest(UserController.class)
@AutoConfigureRestDocs
public class UserDocumentationTests {

	@Autowired
	private MockMvc mvc;

	@Test
	public void listUsers() throws Exception {
		this.mvc.perform(get("/users").accept(MediaType.TEXT_PLAIN))
				.andExpect(status().isOk())
				.andDo(document("list-users"));
	}

}

如果您需要对Spring REST Docs配置的更多控制,而不是@AutoConfigureRestDocs属性提供的控制,则可以使用RestDocsMockMvcConfigurationCustomizer bean,如以下示例所示:

@TestConfiguration
static class CustomizationConfiguration
		implements RestDocsMockMvcConfigurationCustomizer {

	@Override
	public void customize(MockMvcRestDocumentationConfigurer configurer) {
		configurer.snippets().withTemplateFormat(TemplateFormats.markdown());
	}

}

如果要对参数化输出目录使用Spring REST Docs支持,可以创建RestDocumentationResultHandler bean。自动配置使用此结果处理程序调用alwaysDo,从而导致每个MockMvc调用自动生成默认代码段。以下示例显示正在定义的RestDocumentationResultHandler

@TestConfiguration
static class ResultHandlerConfiguration {

	@Bean
	public RestDocumentationResultHandler restDocumentation() {
		return MockMvcRestDocumentation.document("{method-name}");
	}

}

使用REST Assured自动配置Spring REST文档测试

@AutoConfigureRestDocs生成RequestSpecification bean,预先配置为使用Spring REST文档,可用于您的测试。您可以使用@Autowired注入它并在测试中使用它,就像使用REST Assured和Spring REST Docs时一样,如下例所示:

import io.restassured.specification.RequestSpecification;
import org.junit.Test;
import org.junit.runner.RunWith;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.restdocs.AutoConfigureRestDocs;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.boot.web.server.LocalServerPort;
import org.springframework.test.context.junit4.SpringRunner;

import static io.restassured.RestAssured.given;
import static org.hamcrest.CoreMatchers.is;
import static org.springframework.restdocs.restassured3.RestAssuredRestDocumentation.document;

@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
@AutoConfigureRestDocs
public class UserDocumentationTests {

	@LocalServerPort
	private int port;

	@Autowired
	private RequestSpecification documentationSpec;

	@Test
	public void listUsers() {
		given(this.documentationSpec).filter(document("list-users")).when()
				.port(this.port).get("/").then().assertThat().statusCode(is(200));
	}

}

如果您需要对Spring REST Docs配置进行更多控制,而不是@AutoConfigureRestDocs属性提供的控制,则可以使用RestDocsRestAssuredConfigurationCustomizer bean,如以下示例所示:

@TestConfiguration
public static class CustomizationConfiguration
		implements RestDocsRestAssuredConfigurationCustomizer {

	@Override
	public void customize(RestAssuredRestDocumentationConfigurer configurer) {
		configurer.snippets().withTemplateFormat(TemplateFormats.markdown());
	}

}

45.3.22附加自动配置和切片

每个切片提供一个或多个@AutoConfigure…​注释,即定义应作为切片的一部分包括的自动配置。可以通过创建自定义@AutoConfigure…​注释或仅通过向测试添加@ImportAutoConfiguration来添加其他自动配置,如以下示例所示:

@RunWith(SpringRunner.class)
@JdbcTest
@ImportAutoConfiguration(IntegrationAutoConfiguration.class)
public class ExampleJdbcTests {

}
[注意]注意

确保不使用常规@Import注释来导入自动配置,因为Spring Boot以特定方式处理它们。

45.3.23用户配置和切片

如果以合理的方式构造代码默认情况下使用 @SpringBootApplication作为测试的配置。

然后,重要的是不要使用特定于其功能的特定区域的配置设置来丢弃应用程序的主类。

假设您正在使用Spring Batch,并依赖于它的自动配置。您可以按如下方式定义@SpringBootApplication

@SpringBootApplication
@EnableBatchProcessing
public class SampleApplication { ... }

因为此类是测试的源配置,所以任何切片测试实际上都会尝试启动Spring Batch,这绝对不是您想要做的。建议的方法是将特定于区域的配置移动到与应用程序相同级别的单独@Configuration类,如以下示例所示:

@Configuration
@EnableBatchProcessing
public class BatchConfiguration { ... }
[注意]注意

根据应用程序的复杂程度,您可能只有一个@Configuration类用于自定义,或者每个域区域有一个类。后一种方法允许您在必要时使用@Import注释在其中一个测试中启用它。

混淆的另一个原因是类路径扫描。假设您以合理的方式构建代码,则需要扫描其他包。您的应用程序可能类似于以下代码:

@SpringBootApplication
@ComponentScan({ "com.example.app", "org.acme.another" })
public class SampleApplication { ... }

这样做会有效地覆盖默认的组件扫描指令,无论您选择哪个切片,都会扫描这两个包。例如,@DataJpaTest似乎突然扫描应用程序的组件和用户配置。同样,将自定义指令移动到单独的类是解决此问题的好方法。

[提示]提示

如果这不是您的选项,您可以在测试的层次结构中的某处创建一个@SpringBootConfiguration,以便使用它。或者,您可以为测试指定源,这会禁用查找默认源的行为。

45.3.24使用Spock测试Spring Boot应用程序

如果您希望使用Spock来测试Spring Boot应用程序,您应该将Spock的spock-spring模块的依赖项添加到您的应用程序的构建中。spock-spring将Spring的测试框架集成到Spock中。建议您使用Spock 1.2或更高版本从Spock的Spring框架和Spring Boot集成的许多改进中受益。有关更多详细信息,请参阅Spock的Spring模块的文档

45.4测试实用程序

测试应用程序时通常有用的一些测试实用程序类打包为spring-boot的一部分。

45.4.1 ConfigFileApplicationContextInitializer

ConfigFileApplicationContextInitializerApplicationContextInitializer,您可以将其应用于测试以加载Spring Boot application.properties个文件。当您不需要@SpringBootTest提供的全部功能时,可以使用它,如以下示例所示:

@ContextConfiguration(classes = Config.class,
	initializers = ConfigFileApplicationContextInitializer.class)
[注意]注意

仅使用ConfigFileApplicationContextInitializer不能为@Value("${…​}")注射提供支持。它唯一的工作是确保将application.properties个文件加载到Spring的Environment中。对于@Value支持,您需要另外配置PropertySourcesPlaceholderConfigurer或使用@SpringBootTest,它会为您自动配置一个。

45.4.2 TestPropertyValues

TestPropertyValues可让您快速向ConfigurableEnvironmentConfigurableApplicationContext添加属性。您可以使用key=value字符串调用它,如下所示:

TestPropertyValues.of("org=Spring", "name=Boot").applyTo(env);

45.4.3 OutputCapture

OutputCapture是一个JUnit Rule,可用于捕获System.outSystem.err输出。您可以将捕获声明为@Rule,然后使用toString()进行断言,如下所示:

import org.junit.Rule;
import org.junit.Test;
import org.springframework.boot.test.rule.OutputCapture;

import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;

public class MyTest {

	@Rule
	public OutputCapture capture = new OutputCapture();

	@Test
	public void testName() throws Exception {
		System.out.println("Hello World!");
		assertThat(capture.toString(), containsString("World"));
	}

}

45.4.4 TestRestTemplate

[提示]提示

Spring Framework 5.0提供了一个新的WebTestClient,适用于 WebFlux集成测试以及 WebFlux和MVC端到端测试TestRestTemplate不同,它为断言提供了流畅的API。

TestRestTemplate是Spring RestTemplate的便利替代品,可用于集成测试。您可以获得一个vanilla模板或一个发送基本HTTP身份验证(使用用户名和密码)的模板。在任何一种情况下,模板都以一种测试友好的方式运行,不会在服务器端错误上抛出异常。建议(但不是强制性的)使用Apache HTTP Client(版本4.3.2或更高版本)。如果您在类路径上有这个,那么TestRestTemplate通过适当地配置客户端来响应。如果您确实使用Apache的HTTP客户端,则启用一些其他测试友好功能:

  • 不遵循重定向(因此您可以断言响应位置)。
  • Cookie被忽略(因此模板是无状态的)。

TestRestTemplate可以直接在集成测试中实例化,如以下示例所示:

public class MyTest {

	private TestRestTemplate template = new TestRestTemplate();

	@Test
	public void testRequest() throws Exception {
		HttpHeaders headers = this.template.getForEntity(
				"http://myhost.example.com/example", String.class).getHeaders();
		assertThat(headers.getLocation()).hasHost("other.example.com");
	}

}

或者,如果您将@SpringBootTest注释与WebEnvironment.RANDOM_PORTWebEnvironment.DEFINED_PORT一起使用,则可以注入完全配置的TestRestTemplate并开始使用它。如有必要,可以通过RestTemplateBuilder bean应用其他自定义设置。任何未指定主机和端口的URL都会自动连接到嵌入式服务器,如以下示例所示:

@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
public class SampleWebClientTests {

	@Autowired
	private TestRestTemplate template;

	@Test
	public void testRequest() {
		HttpHeaders headers = this.template.getForEntity("/example", String.class)
				.getHeaders();
		assertThat(headers.getLocation()).hasHost("other.example.com");
	}

	@TestConfiguration
	static class Config {

		@Bean
		public RestTemplateBuilder restTemplateBuilder() {
			return new RestTemplateBuilder().setConnectTimeout(Duration.ofSeconds(1))
					.setReadTimeout(Duration.ofSeconds(1));
		}

	}

}

46. WebSockets

Spring Boot为嵌入式Tomcat,Jetty和Undertow提供WebSockets自动配置。如果将war文件部署到独立容器,则Spring Boot假定容器负责其WebSocket支持的配置。

Spring Framework 为MVC Web应用程序提供了丰富的WebSocket支持,可以通过spring-boot-starter-websocket模块轻松访问。

WebSocket支持也可用于 响应式Web应用程序,并且需要在spring-boot-starter-webflux旁边包含WebSocket API:

<dependency>
	<groupId>javax.websocket</groupId>
	<artifactId>javax.websocket-api</artifactId>
</dependency>

47.网络服务

Spring Boot提供Web服务自动配置,因此您必须做的就是定义Endpoints

Spring Web服务功能,可以与spring-boot-starter-webservices模块可以轻松访问。

可以分别为您的WSDL和XSD自动创建SimpleWsdl11DefinitionSimpleXsdSchema beans。为此,请配置其位置,如以下示例所示:

spring.webservices.wsdl-locations=classpath:/wsdl

48.使用WebServiceTemplate调用Web服务

如果需要从应用程序调用远程Web服务,则可以使用 WebServiceTemplate该类。由于WebServiceTemplate实例在使用之前通常需要进行自定义,因此Spring Boot不提供任何单个自动配置的WebServiceTemplate bean。但是,它会自动配置WebServiceTemplateBuilder,可用于在需要时创建WebServiceTemplate实例。

以下代码显示了一个典型示例:

@Service
public class MyService {

	private final WebServiceTemplate webServiceTemplate;

	public MyService(WebServiceTemplateBuilder webServiceTemplateBuilder) {
		this.webServiceTemplate = webServiceTemplateBuilder.build();
	}

	public DetailsResp someWsCall(DetailsReq detailsReq) {
		 return (DetailsResp) this.webServiceTemplate.marshalSendAndReceive(detailsReq, new SoapActionCallback(ACTION));

	}

}

默认情况下,WebServiceTemplateBuilder使用类路径上的可用HTTP客户端库检测到合适的基于HTTP的WebServiceMessageSender您还可以按如下方式自定义读取和连接超时:

@Bean
public WebServiceTemplate webServiceTemplate(WebServiceTemplateBuilder builder) {
	return builder.messageSenders(new HttpWebServiceMessageSenderBuilder()
			.setConnectTimeout(5000).setReadTimeout(2000).build()).build();
}

49.创建自己的自动配置

如果您在开发共享库的公司工作,或者您在开源或商业库中工作,则可能需要开发自己的自动配置。自动配置类可以捆绑在外部jar中,仍然可以通过Spring Boot获取。

自动配置可以与“启动器”相关联,该启动器提供自动配置代码以及您将使用它的典型库。我们首先介绍了构建自己的自动配置需要了解的内容,然后我们将继续介绍创建自定义启动器所需典型步骤

[提示]提示

可以使用演示项目来展示如何逐步创建启动器。

49.1了解自动配置Beans

在引擎盖下,自动配置使用标准@Configuration类实现。额外的@Conditional注释用于约束何时应用自动配置。通常,自动配置类使用@ConditionalOnClass@ConditionalOnMissingBean注释。这可确保仅在找到相关类时以及未声明自己的@Configuration时才应用自动配置。

您可以浏览源代码spring-boot-autoconfigure 以查看Spring提供的@Configuration类(请参阅 META-INF/spring.factories 文件)。

49.2找到自动配置候选者

Spring Boot检查已发布jar中是否存在META-INF/spring.factories文件。该文件应在EnableAutoConfiguration键下列出您的配置类,如以下示例所示:

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.mycorp.libx.autoconfigure.LibXAutoConfiguration,\
com.mycorp.libx.autoconfigure.LibXWebAutoConfiguration

如果需要按特定顺序应用配置,则可以使用 @AutoConfigureAfter@AutoConfigureBefore注释。例如,如果您提供特定于Web的配置,则可能需要在WebMvcAutoConfiguration之后应用您的类。

如果您想订购某些不应该彼此直接了解的自动配置,您也可以使用@AutoConfigureOrder该注释与常规@Order注释具有相同的语义,但为自动配置类提供了专用顺序。

[注意]注意

自动配置,必须加载这种方式确保它们是在特定的包空间中定义的,特别是它们永远不是组件扫描的目标。

49.3条件Annotations

您几乎总是希望在自动配置类中包含一个或多个@Conditional注释。@ConditionalOnMissingBean注释是一个常见示例,用于允许开发人员在您的默认值不满意时覆盖自动配置。

Spring Boot包含许多@Conditional注释,您可以通过注释@Configuration类或单独的@Bean方法在您自己的代码中重用这些注释。这些注释包括:

49.3.1等级条件

@ConditionalOnClass@ConditionalOnMissingClass注释允许根据特定类的存在与否来包含配置。由于使用ASM解析注释元数据这一事实,您可以使用value属性来引用真实类,即使该类实际上可能不会出现在正在运行的应用程序类路径中。如果您希望使用String值指定类名,也可以使用name属性。

[提示]提示

如果您使用@ConditionalOnClass@ConditionalOnMissingClass作为元注释的一部分来编写自己的组合注释,则必须使用name作为引用该类的情况,在这种情况下不会处理。

49.3.2 Bean条件

@ConditionalOnBean@ConditionalOnMissingBean注释允许根据特定beans的存在与否来包括bean。您可以使用value属性按类型指定beans,或使用name按名称指定beans。search属性允许您限制搜索beans时应考虑的ApplicationContext层次结构。

置于@Bean方法时,目标类型默认为方法的返回类型,如以下示例所示:

@Configuration
public class MyAutoConfiguration {

	@Bean
	@ConditionalOnMissingBean
	public MyService myService() { ... }

}

在前面的示例中,如果ApplicationContext中未包含类型MyService的bean,则将创建myService bean。

[提示]提示

您需要非常小心添加bean定义的顺序,因为这些条件是根据到目前为止已处理的内容进行评估的。因此,我们建议仅对自动配置类使用@ConditionalOnBean@ConditionalOnMissingBean注释(因为这些注释保证在添加任何用户定义的bean定义后加载)。

[注意]注意

@ConditionalOnBean@ConditionalOnMissingBean不会阻止创建@Configuration类。在类级别使用这些条件和使用注释标记每个包含@Bean方法的唯一区别是,如果条件不匹配,前者会阻止将@Configuration类注册为bean。

49.3.3 Property条件

@ConditionalOnProperty注释允许基于Spring Environment属性包含配置。使用prefixname属性指定应检查的属性。默认情况下,匹配存在且不等于false的任何属性。您还可以使用havingValuematchIfMissing属性创建更高级的检查。

49.3.4资源条件

@ConditionalOnResource注释仅在存在特定资源时才允许配置。可以使用通常的Spring约定来指定资源,如以下示例所示:file:/home/user/test.dat

49.3.5 Web应用程序条件

@ConditionalOnWebApplication@ConditionalOnNotWebApplication注释允许配置,具体取决于应用程序是否为“Web应用程序”。Web应用程序是使用Spring WebApplicationContext,定义session范围或具有StandardServletEnvironment的任何应用程序。

49.3.6 SpEL表达条件

@ConditionalOnExpression注释允许根据SpEL表达式的结果包含配置

49.4测试自动配置

自动配置可能受许多因素的影响:用户配置(@Bean定义和Environment自定义),条件评估(存在特定库)等。具体而言,每个测试都应创建一个定义良好的ApplicationContext,它代表这些自定义的组合。ApplicationContextRunner提供了实现这一目标的好方法。

ApplicationContextRunner通常被定义为测试类的一个字段,用于收集基本的通用配置。以下示例确保始终调用UserServiceAutoConfiguration

private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
		.withConfiguration(AutoConfigurations.of(UserServiceAutoConfiguration.class));
[提示]提示

如果必须定义多个自动配置,则无需按照与运行应用程序时完全相同的顺序调用它们的声明。

每个测试都可以使用运行器来表示特定的用例。例如,下面的示例调用用户配置(UserConfiguration)并检查自动配置是否正确退回。调用run提供了一个可以与Assert4J一起使用的回调上下文。

@Test
public void defaultServiceBacksOff() {
	this.contextRunner.withUserConfiguration(UserConfiguration.class)
			.run((context) -> {
				assertThat(context).hasSingleBean(UserService.class);
				assertThat(context.getBean(UserService.class)).isSameAs(
						context.getBean(UserConfiguration.class).myUserService());
			});
}

@Configuration
static class UserConfiguration {

	@Bean
	public UserService myUserService() {
		return new UserService("mine");
	}

}

也可以轻松自定义Environment,如以下示例所示:

@Test
public void serviceNameCanBeConfigured() {
	this.contextRunner.withPropertyValues("user.name=test123").run((context) -> {
		assertThat(context).hasSingleBean(UserService.class);
		assertThat(context.getBean(UserService.class).getName()).isEqualTo("test123");
	});
}

跑步者也可以用来显示ConditionEvaluationReport该报告可以INFODEBUG级别打印。以下示例显示如何使用ConditionEvaluationReportLoggingListener在自动配置测试中打印报表。

@Test
public void autoConfigTest {
	ConditionEvaluationReportLoggingListener initializer = new ConditionEvaluationReportLoggingListener(
			LogLevel.INFO);
	ApplicationContextRunner contextRunner = new ApplicationContextRunner()
			.withInitializer(initializer).run((context) -> {
					// Do something...
			});
}

49.4.1模拟Web上下文

如果需要测试仅在Servlet或Reactive Web应用程序上下文中运行的自动配置,请分别使用WebApplicationContextRunnerReactiveWebApplicationContextRunner

49.4.2覆盖Classpath

还可以测试在运行时不存在特定类和/或包时发生的情况。Spring Boot装有FilteredClassLoader,可以很容易地被跑步者使用。在以下示例中,我们声明如果不存在UserService,则会正确禁用自动配置:

@Test
public void serviceIsIgnoredIfLibraryIsNotPresent() {
	this.contextRunner.withClassLoader(new FilteredClassLoader(UserService.class))
			.run((context) -> assertThat(context).doesNotHaveBean("userService"));
}

49.5创建自己的初学者

库的完整Spring Boot启动器可能包含以下组件:

  • 包含自动配置代码的autoconfigure模块。
  • starter模块,它提供对autoconfigure模块以及库的依赖关系以及通常有用的任何其他依赖项。简而言之,添加启动器应该提供开始使用该库所需的一切。
[提示]提示

如果您不需要将这两个问题分开,则可以将自动配置代码和依赖关系管理组合在一个模块中。

49.5.1命名

您应该确保为您的启动器提供适当的命名空间。即使您使用不同的Maven groupId,也不要使用spring-boot启动模块名称。我们可能会为您将来自动配置的内容提供官方支持。

根据经验,您应该在启动后命名组合模块。例如,假设您正在为“acme”创建启动器,并且您将自动配置模块acme-spring-boot-autoconfigure和启动器acme-spring-boot-starter命名为。如果您只有一个组合两者的模块,请将其命名为acme-spring-boot-starter

此外,如果您的启动器提供配置密钥,请为它们使用唯一的命名空间。特别是,不要将密钥包含在Spring Boot使用的名称空间中(例如servermanagementspring等)。如果您使用相同的命名空间,我们将来可能会以破坏您的模块的方式修改这些命名空间。

确保 触发元数据生成,以便为您的密钥提供IDE帮助。您可能需要查看生成的元数据(META-INF/spring-configuration-metadata.json)以确保正确记录您的密钥。

49.5.2 autoconfigure模块

autoconfigure模块包含开始使用库所需的所有内容。它还可能包含配置键定义(例如@ConfigurationProperties)以及可用于进一步自定义组件初始化方式的任何回调接口。

[提示]提示

您应该将库的依赖项标记为可选,以便您可以更轻松地在项目中包含autoconfigure模块。如果您这样做,则不提供库,默认情况下,Spring Boot会退出。

Spring Boot使用注释处理器来收集元数据文件(META-INF/spring-autoconfigure-metadata.properties)中自动配置的条件。如果该文件存在,则用于热切过滤不匹配的自动配置,这将缩短启动时间。建议在包含自动配置的模块中添加以下依赖项:

<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-autoconfigure-processor</artifactId>
	<optional>true</optional>
</dependency>

对于Gradle 4.5及更早版本,依赖项应在compileOnly配置中声明,如以下示例所示:

dependencies {
	compileOnly "org.springframework.boot:spring-boot-autoconfigure-processor"
}

对于Gradle 4.6及更高版本,应在annotationProcessor配置中声明依赖项,如以下示例所示:

dependencies {
	annotationProcessor "org.springframework.boot:spring-boot-autoconfigure-processor"
}

49.5.3启动器模块

起动器真的是一个空罐子。它的唯一目的是提供必要的依赖项来使用库。您可以将其视为对入门所需内容的一种看法。

不要对添加启动器的项目做出假设。如果您自动配置的库通常需要其他启动器,请同时提及它们。如果可选依赖项的数量很高,则提供一组适当的默认依赖项可能很难,因为您应该避免包含对典型库的使用不必要的依赖项。换句话说,您不应该包含可选的依赖项。

[注意]注意

无论哪种方式,您的启动器必须直接或间接引用核心Spring Boot启动器(spring-boot-starter)(即如果您的启动器依赖于另一个启动器,则无需添加它)。如果仅使用自定义启动程序创建项目,则核心启动程序将支持Spring引导的核心功能。

50. Kotlin的支持

Kotlin是一种针对JVM(和其他平台)的静态类型语言,它允许编写简洁而优雅的代码,同时提供 与Java编写的现有库的互操作性

Spring Boot通过利用Spring框架,Spring数据和反应堆等其他Spring项目的支持,提供Kotlin支持。有关 更多信息,请参阅 Spring Framework Kotlin支持文档

从Spring Boot和Kotlin开始的最简单方法是遵循 这个全面的教程您可以通过start.spring.io创建新的Kotlin项目 如果您需要支持,随意加入Kotlin Slack的#spring频道或在Stack Overflow上使用springkotlin标签提问

50.1要求

Spring Boot支持Kotlin 1.2.x. 要使用Kotlin,类路径上必须存在org.jetbrains.kotlin:kotlin-stdliborg.jetbrains.kotlin:kotlin-reflect也可以使用kotlin-stdlib变体kotlin-stdlib-jdk7kotlin-stdlib-jdk8

由于Kotlin类默认为final,因此您可能需要配置 kotlin-spring 插件以自动打开Spring - 带注释的类,以便可以代理它们。

在Kotlin中序列化/反序列化JSON数据需要Jackson的Kotlin模块在类路径中找到它时会自动注册。如果Jackson和Kotlin存在但Jackson Kotlin模块不存在,则会记录警告消息。

[提示]提示

如果在start.spring.io上引导Kotlin项目,默认提供这些依赖项和插件

50.2无安全性

Kotlin的一个关键特性是零安全性它在编译时处理null值,而不是将问题推迟到运行时并遇到NullPointerException这有助于消除常见的错误来源,而无需支付Optional等包装器的成本。Kotlin还允许使用具有可空值的功能构造,如本 Kotlin中关于零安全性的综合指南中所述

虽然Java不允许在其类型系统中表示null安全性,但Spring Framework,Spring Data和Reactor现在通过工具友好的注释提供其API的空安全性。默认情况下,Kotlin中使用的Java API类型被识别为 放宽空检查的平台类型Kotlin对JSR 305注释的支持与可空性注释相结合,为Kotlin中相关的Spring API提供了空的安全性。

可以通过使用以下选项添加-Xjsr305编译器标志来配置JSR 305检查:-Xjsr305={strict|warn|ignore}默认行为与-Xjsr305=warn相同。strict值需要在从Spring API推断的Kotlin类型中考虑空安全性,但应该使用Spring API可空性声明甚至可以在次要版本和更多检查之间发展的知识可能会在将来添加)。

[警告]警告

尚不支持泛型类型参数,varargs和数组元素可空性。有关最新信息,请参见SPR-15942另请注意,Spring Boot自己的API 尚未注释

50.3 Kotlin API

50.3.1 runApplication

Spring Boot提供了使用runApplication<MyApplication>(*args)运行应用程序的惯用方法,如以下示例所示:

import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.runApplication

@SpringBootApplication
class MyApplication

fun main(args: Array<String>) {
	runApplication<MyApplication>(*args)
}

这是SpringApplication.run(MyApplication::class.java, *args)的替代品。它还允许自定义应用程序,如以下示例所示:

runApplication<MyApplication>(*args) {
	setBannerMode(OFF)
}

50.3.2扩展

Kotlin 扩展提供了使用附加功能扩展现有类的能力。Spring Boot Kotlin API利用这些扩展为现有API添加新的Kotlin特定便利。

TestRestTemplate扩展类似于Spring框架中Caffeine框架Caffeine提供的扩展。除此之外,扩展使得可以利用Kotlin具体类型参数。

50.4依赖管理

为了避免在类路径上混合使用不同版本的Kotlin依赖项,提供了以下Kotlin依赖项的依赖项管理:

  • kotlin-reflect
  • kotlin-runtime
  • kotlin-stdlib
  • kotlin-stdlib-jdk7
  • kotlin-stdlib-jdk8
  • kotlin-stdlib-jre7
  • kotlin-stdlib-jre8

使用Maven,可以通过kotlin.version属性自定义Kotlin版本,并为kotlin-maven-plugin提供插件管理。使用Gradle,Spring Boot插件会自动将kotlin.version与Kotlin插件的版本对齐。

50.5 @ConfigurationProperties

@ConfigurationProperties目前仅适用于lateinit或可空var属性(建议使用前者),因为尚不支持由构造函数初始化的不可变类

@ConfigurationProperties("example.kotlin")
class KotlinExampleProperties {

	lateinit var name: String

	lateinit var description: String

	val myService = MyService()

	class MyService {

		lateinit var apiToken: String

		lateinit var uri: URI

	}

}
[提示]提示

使用注释处理器生成 您自己的元数据kapt应配置 spring-boot-configuration-processor依赖项。

50.6测试

虽然可以使用JUnit 4(由spring-boot-starter-test提供的默认值)来测试Kotlin代码,但建议使用JUnit 5。JUnit 5使测试类能够实例化一次并重用于所有类的测试。这使得可以在非静态方法上使用@BeforeAll@AfterAll注释,这非常适合Kotlin。

要使用JUnit 5,请从spring-boot-starter-test中排除junit:junit依赖项,添加JUnit 5依赖项,并相应地配置Maven或Gradle插件。有关更多详细信息,请参阅 JUnit 5文档您还需要将 测试实例生命周期切换为“每个类”

50.7资源

50.7.2例子

51.接下来要阅读的内容

如果您想了解本节中讨论的任何类的更多信息,可以查看Spring Boot API文档,也可以直接浏览 源代码如果您有具体问题,请查看 操作方法部分。

如果您对Spring Boot的核心功能感到满意,可以继续阅读有关生产就绪功能的内容

第五部分。Spring Boot Actuator:生产就绪功能

Spring Boot包含许多其他功能,可帮助您在将应用程序推送到生产环境时监控和管理应用程序。您可以选择使用HTTP端点或JMX来管理和监视应用程序。审核,运行状况和指标收集也可以自动应用于您的应用程序。

52.启用生产就绪功能

spring-boot-actuator模块提供了所有Spring Boot的生产就绪功能。启用这些功能的最简单方法是为spring-boot-starter-actuator'Starter'添加依赖项。

要将执行器添加到基于Maven的项目,请添加以下“Starter”依赖项:

<dependencies>
	<dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-actuator</artifactId>
	</dependency>
</dependencies>

对于Gradle,请使用以下声明:

dependencies {
	compile("org.springframework.boot:spring-boot-starter-actuator")
}

53.终点

通过执行器端点,您可以监控应用程序并与之交互。Spring Boot包含许多内置端点,允许您添加自己的端点。例如,health端点提供基本的应用程序运行状况信息。

可以启用或禁用每个单独的端点它控制是否在应用程序上下文中创建端点并且其bean存在。要远程访问,还必须通过JMX或HTTP公开端点 大多数应用程序选择HTTP,其中端点的ID以及/actuator的前缀映射到URL。例如,默认情况下,health端点映射到/actuator/health

可以使用以下与技术无关的端点:

ID描述默认情况下启用

auditevents

公开当前应用程序的审核事件信息。

Yes

beans

显示应用程序中所有Spring beans的完整列表。

Yes

caches

暴露可用的缓存。

Yes

conditions

显示在配置和自动配置类上评估的条件以及它们匹配或不匹配的原因。

Yes

configprops

显示所有@ConfigurationProperties的整理列表。

Yes

env

公开Spring ConfigurableEnvironment的财产。

Yes

flyway

显示已应用的任何Flyway数据库迁移。

Yes

health

显示应用健康信息。

Yes

httptrace

显示HTTP跟踪信息(默认情况下,最后100个HTTP请求 - 响应交换)。

Yes

info

显示任意应用信息。

Yes

integrationgraph

显示Spring Integration图表。

Yes

loggers

显示和修改应用程序中记录器的配置。

Yes

liquibase

显示已应用的任何Liquibase数据库迁移。

Yes

metrics

显示当前应用程序的“指标”信息。

Yes

mappings

显示所有@RequestMapping路径的整理列表。

Yes

scheduledtasks

显示应用程序中的计划任务。

Yes

sessions

允许从支持Spring Session的会话存储中检索和删除用户会话。使用Spring Session对响应式Web应用程序的支持时不可用。

Yes

shutdown

允许应用程序正常关闭。

No

threaddump

执行线程转储。

Yes

如果您的应用程序是Web应用程序(Spring MVC,Spring WebFlux或Jersey),则可以使用以下附加端点:

ID描述默认情况下启用

heapdump

返回hprof堆转储文件。

Yes

jolokia

通过HTTP公开JMX beans(当Jolokia在类路径上时,不适用于WebFlux)。

Yes

logfile

返回日志文件的内容(如果已设置logging.filelogging.path属性)。支持使用HTTP Range标头来检索部分日志文件的内容。

Yes

prometheus

以可由Prometheus服务器抓取的格式公开指标。

Yes

要了解有关Actuator端点及其请求和响应格式的更多信息,请参阅单独的API文档(HTMLPDF)。

53.1启用端点

默认情况下,启用除shutdown之外的所有端点。要配置端点的启用,请使用其management.endpoint.<id>.enabled属性。以下示例启用shutdown端点:

management.endpoint.shutdown.enabled=true

如果您希望端点启用是选择加入而不是选择退出,请将management.endpoints.enabled-by-default属性设置为false并使用单个端点enabled属性重新加入。以下示例启用info endpoint并禁用所有其他端点:

management.endpoints.enabled-by-default=false
management.endpoint.info.enabled=true
[注意]注意

已完全从应用程序上下文中删除已禁用的端点。如果您只想更改端点所暴露的技术,请改用 includeexclude属性

53.2公开端点

由于端点可能包含敏感信息,因此应仔细考虑何时公开它们。下表显示了内置端点的默认曝光:

IDJMX卷筒纸

auditevents

Yes

No

beans

Yes

No

caches

Yes

No

conditions

Yes

No

configprops

Yes

No

env

Yes

No

flyway

Yes

No

health

Yes

Yes

heapdump

N/A

No

httptrace

Yes

No

info

Yes

Yes

integrationgraph

Yes

No

jolokia

N/A

No

logfile

N/A

No

loggers

Yes

No

liquibase

Yes

No

metrics

Yes

No

mappings

Yes

No

prometheus

N/A

No

scheduledtasks

Yes

No

sessions

Yes

No

shutdown

Yes

No

threaddump

Yes

No

要更改公开的端点,请使用以下特定于技术的includeexclude属性:

Property默认

management.endpoints.jmx.exposure.exclude

 

management.endpoints.jmx.exposure.include

*

management.endpoints.web.exposure.exclude

 

management.endpoints.web.exposure.include

info, health

include属性列出了公开的端点的ID。exclude属性列出了不应公开的端点的ID。exclude属性优先于include属性。includeexclude属性都可以配置端点ID列表。

例如,要停止通过JMX公开所有端点并仅显示healthinfo端点,请使用以下属性:

management.endpoints.jmx.exposure.include=health,info

*可用于选择所有端点。例如,要通过HTTP公开除envbeans端点之外的所有内容,请使用以下属性:

management.endpoints.web.exposure.include=*
management.endpoints.web.exposure.exclude=env,beans
[注意]注意

*在YAML中具有特殊含义,因此如果要包含(或排除)所有端点,请务必添加引号,如以下示例所示:

management:
  endpoints:
    web:
      exposure:
        include: "*"
[注意]注意

如果您的申请是公开的,我们强烈建议您 保护您的终端

[提示]提示

如果您想在暴露端点时实施自己的策略,可以注册EndpointFilter bean。

53.3保护HTTP端点

您应该像使用任何其他敏感URL一样注意保护HTTP端点。如果存在Spring安全性,则默认使用Spring安全性内容协商策略来保护端点。例如,如果您希望为HTTP端点配置自定义安全性,仅允许具有特定角色的用户访问它们,Spring Boot提供了一些方便的RequestMatcher对象,可以与Spring安全性结合使用。

典型的Spring安全配置可能类似于以下示例:

@Configuration
public class ActuatorSecurity extends WebSecurityConfigurerAdapter {

	@Override
	protected void configure(HttpSecurity http) throws Exception {
		http.requestMatcher(EndpointRequest.toAnyEndpoint()).authorizeRequests()
				.anyRequest().hasRole("ENDPOINT_ADMIN")
				.and()
			.httpBasic();
	}

}

上面的示例使用EndpointRequest.toAnyEndpoint()将请求与任何端点进行匹配,然后确保所有端点都具有ENDPOINT_ADMIN角色。EndpointRequest也提供了其他几种匹配方法。有关详细信息,请参阅API文档(HTMLPDF)。

如果在防火墙后部署应用程序,您可能希望无需身份验证即可访问所有执行器端点。您可以通过更改management.endpoints.web.exposure.include属性来执行此操作,如下所示:

application.properties。 

management.endpoints.web.exposure.include=*

此外,如果存在Spring安全性,则需要添加自定义安全性配置,以允许对端点进行未经身份验证的访问,如以下示例所示:

@Configuration
public class ActuatorSecurity extends WebSecurityConfigurerAdapter {

	@Override
	protected void configure(HttpSecurity http) throws Exception {
		http.requestMatcher(EndpointRequest.toAnyEndpoint()).authorizeRequests()
			.anyRequest().permitAll();
	}

}

53.4配置端点

端点自动缓存对不带任何参数的读取操作的响应。要配置端点缓存响应的时间量,请使用其cache.time-to-live属性。以下示例将beans端点缓存的生存时间设置为10秒:

application.properties。 

management.endpoint.beans.cache.time-to-live=10s

[注意]注意

前缀management.endpoint.<name>用于唯一标识正在配置的端点。

[注意]注意

在进行经过身份验证的HTTP请求时,Principal被视为端点的输入,因此不会缓存响应。

53.5用于执行器Web端点的超媒体

添加了“发现页面”,其中包含指向所有端点的链接。默认情况下,/actuator上提供了“发现页面”。

配置自定义管理上下文路径后,“发现页面”会自动从/actuator移动到管理上下文的根目录。例如,如果管理上下文路径为/management,则可以从/management获取发现页面。当管理上下文路径设置为/时,将禁用发现页面以防止与其他映射冲突的可能性。

53.6 CORS支持

跨源资源共享 (CORS)是一种W3C规范,允许您以灵活的方式指定授权的跨域请求类型。如果您使用Spring MVC或Spring WebFlux,可以配置Actuator的Web端点以支持此类方案。

默认情况下禁用CORS支持,仅在设置了management.endpoints.web.cors.allowed-origins属性后才启用CORS支持。以下配置允许来自example.com域的GETPOST来电:

management.endpoints.web.cors.allowed-origins=http://example.com
management.endpoints.web.cors.allowed-methods=GET,POST
[提示]提示

有关 选项的完整列表,请参阅 CorsEndpointProperties

53.7实现自定义端点

如果添加注释为@Endpoint@Bean,则使用@ReadOperation@WriteOperation@DeleteOperation注释的任何方法都会通过JMX自动公开,并且在Web应用程序中也会通过HTTP自动公开。可以使用Jersey,Spring MVC或Spring WebFlux通过HTTP公开端点。

您还可以使用@JmxEndpoint@WebEndpoint编写特定于技术的端点。这些端点仅限于各自的技术。例如,@WebEndpoint仅通过HTTP而不是通过JMX公开。

您可以使用@EndpointWebExtension@EndpointJmxExtension编写特定于技术的扩展。通过这些注释,您可以提供特定于技术的操作来扩充现有端点。

最后,如果您需要访问特定于Web框架的功能,您可以实现Servlet或Spring @Controller@RestController端点,但代价是它们无法通过JMX或使用不同的Web框架。