19. 动化配置的利弊及解决之道
Spring Boot中的双刃剑:自动化配置
在之前发布的Spring Boot基础教程系列文章中,我们通过各种功能性示例体验了Spring Boot的自动化配置给我们所带来的超便利的新开发方式。但是,在一些情况下Spring Boot的自动化配置也会给我们惹来不少的麻烦,比如这些场景:
- 项目依赖复杂的情况下,由于依赖方的依赖组织不够严格,可能引入了一些实际我们不需要的依赖,从而导致我们的项目满足一些特定的自动化配置。
- 传统Spring项目转换为Spring Boot项目的过程中,由于不同的组织方式问题,引发自动化配置加载的错误,比如:通过xml手工组织的多数据源配置等。
上面这些原因都会导致不必要的自动化配置加载而导致应用无法启动或触发/health的健康检查不通过等问题。比如,我们在改造传统Spring项目到Spring Boot项目中碰到的一些错误:
六月 21, 2017 6:23:47 下午 org.apache.catalina.loader.WebappClassLoaderBase clearReferencesThreads
警告: The web application [ROOT] appears to have started a thread named [Abandoned connection cleanup thread] but has failed to stop it. This is very likely to create a memory leak. Stack trace of thread:
java.lang.Object.wait(Native Method)
java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:143)
com.mysql.jdbc.AbandonedConnectionCleanupThread.run(AbandonedConnectionCleanupThread.java:43)
2017-06-21 18:23:47,230 INFO [main] org.springframework.boot.autoconfigure.logging.AutoConfigurationReportLoggingInitializer -
Error starting ApplicationContext. To display the auto-configuration report re-run your application with 'debug' enabled.
2017-06-21 18:23:47,237 ERROR [main] org.springframework.boot.diagnostics.LoggingFailureAnalysisReporter -
***************************
APPLICATION FAILED TO START
***************************
Description:
Cannot determine embedded database driver class for database type NONE
Action:
If you want an embedded database please put a supported one on the classpath. If you have database settings to be loaded from a particular profile you may need to active it (no profiles are currently active).
从报错信息中,我们就可以分析出错误原因是触发了数据源的自动化配置,然而当前项目其实并不需要数据源。查其根源是依赖方提供的API依赖中引用了一些多余的依赖触发了该自动化配置的加载。
如何解决
为了解决上面所述的问题,我们可以用两种方法来解决:
- 通过外部依赖的修改来解决:通过与依赖方沟通,在对方提供的API依赖中去掉不必要的依赖
- 通过禁用指定的自动化配置来避免加载不必要的自动化配置,下面列举了禁用的方法:
使用了@EnableAutoConfiguration
的时候
@EnableAutoConfiguration(exclude={DataSourceAutoConfiguration.class})
使用了@SpringBootApplication
的时候
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
使用了@SpringCloudApplication
的时候
@EnableAutoConfiguration(exclude={DataSourceAutoConfiguration.class})
@SpringCloudApplication
通过配置文件来设置
spring.autoconfigure.exclude=org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration
20. Spring Boot 2.0
Spring帝国
Spring几乎是每一位Java开发人员都耳熟能详的开发框架,不论您是一名初出茅庐的程序员还是经验丰富的老司机,都会对其有一定的了解或使用经验。在现代企业级应用架构中,Spring技术栈几乎成为了Java语言的代名词,那么Spring为什么能够在众多开源框架中脱颖而出,成为业内一致认可的技术解决方案呢?我们不妨从最初的Spring Framework开始,看看它为什么能够横扫千军,一统江湖!
挑战权威,一战成名
2004年3月,Spring的第一个版本以及其创始人Rod Johnson的经典力作《Expert one-on-one J2EE Development without EJB》发布,打破了当时Java开发领域的传统思考模式,企业级应用开始走向“轻量化”发展的步伐。
最初的Spring Framework 1.0并不像如今的Spring那么复杂,但是在该版本中已经包含了Spring中最为核心的两大要素:
- 依赖注入和面向切面编程,
这两个功能是Spring区别于其他优秀框架,并在企业级应用中建立核心地位的关键所在。很多开发者在初涉Java应用的时候很可能会觉得这两个功能的意义并不大,因为不用它们我们依然可以很好的实现业务功能,事实也确实如此,
- 但是随着业务的迭代和开发的深入,复杂多变的需求开始慢慢侵蚀原本“完美”的架构,开发与测试的难度逐步增大,往往在这个时候,我们才体会到了Spring的价值。所以,即便在Spring的最初版本中也封装了诸多偏业务型的功能封装,如:邮件发送、事务管理等,但我们要知道真正让企业级应用离不开Spring的理由并不是这些与业务直接相关的功能,而是上面所提及的与业务实现毫不相关的两大核心。
由于在初期版本中Spring对很多功能性封装并没有今天的Spring那么强大,所以很长一段时间,我们都采用了Spring做工程管理来整合其他更优秀的功能型框架来完成系统开发的架构模式,比如曾经风靡一时的Spring + Struts + Hibernate架构,相信可以勾起一代人的回忆。
优雅灵活,吸粉无数
Spring在发布并获得业界的普遍认可之后,Spring开源社区变得异常活跃,除了社区自身不断对Spring进行增强之外,其他功能性框架也纷纷对Spring进行适配与支持。在随后发布的Spring 2.x和3.x中,
- 先后支持了Annotation的优雅配置方式以及更为灵活的
- Java类的配置,
这使得Spring在管理Bean的配置方式上变得更为多样化。
但是随着Spring的深入应用,繁琐的配置问题也开始显现,我们会发现每次在构建项目的时候总是在不断的复制黏贴着一些模版化的配置与代码,有时候我们只是想实现几个很简单的功能,结果配置内容远大于业务逻辑代码的编写;同时,在框架整合过程中,对于一些共同依赖的Jar包存在着潜在的冲突风险,使得一些复杂的整合任务变得困难起来。所以,Spring的“轻量级”在其他动态语言面前就显得不那么轻了。
轮子大师,前途未卜
在之后的Spring 4.x中除了提供对Java 8的支持以及对依赖注入的增强之外,有很长一段时间,Spring社区对其核心框架的创新就没有那么出彩了,社区更多的精力开始将矛头转向了曾经那些亲密无间的小伙伴们。于是,我们在Spring社区发现多出了各种功能性的兄弟项目,
- 比如:简化数据访问的Spring Data、
- 提供批处理能力的Spring Batch、
- 用于保护应用安全的Spring Security等。
虽然这些框架从个体来说都有一定的优势和先进的理念,但是对于很多既有系统来说,在功能性框架上很难做出改变,对于这些新生的轮子项目就很难得到应用,除了一些从零开始的系统会做一些尝试之外,鉴于学习成本和踩坑风险的考虑,中小团队对这些新项目很少有愿意去尝试的。所以,一些老牌的功能性框架除非有严重的性能或安全问题出现,不然很难被这些轮子所替代。
在这段时间里,虽然Spring社区推出了那么多的轮子项目,但是真正在国内得到广泛应用的并不多,很多开发团队依然只是使用最核心的IOC和AOP,并根据自己团队的技术栈情况整合出更适合自身的脚手架来进行系统开发。
神兵出世,再创辉煌
2014年4月1日,Spring Boot发布了第一个正式版本。该项目旨在帮助开发者更容易地创建基于Spring的应用程序和服务,使得现有的和新的Spring开发者能够最快速地获得所需要的Spring功能。一直到今天发布2.x版本,共经历了近4年的发展,Spring Boot已经是一个拥有了21000多Star,15000多次Commits,贡献者超过400多名的超热门开源项目。
Spring Boot为什么突然如此备受关注与推崇呢?主要有以下几点:
- 简化依赖管理:在Spring Boot中提供了一系列的Starter POMs,将各种功能性模块进行了划分与封装,让我们可以更容易的引入和使用,有效的避免了用户在构建传统Spring应用时维护大量依赖关系而引发的JAR冲突等问题。
- 自动化配置:Spring Boot为每一个Starter都提供了自动化的Java配置类,用来替代我们传统Spring应用在XML中繁琐且并不太变化的Bean配置;同时借助一系列的条件注解修饰,使得我们也能轻松的替换这些自动化配置的Bean来进行扩展。
- 嵌入式容器:除了代码组织上的优化之外,Spring Boot中支持的嵌入式容器也是一个极大的亮点(此处仿佛又听到了Josh Long的那句:“Deploy as a Jar, not a War”),借助这个特性使得Spring Boot应用的打包运行变得非常的轻量级。
- 生产级的监控端点:
spring-boot-starter-actuator
的推出可以说是Spring Boot在Spring基础上的另一个重要创新,为Spring应用的工程化变得更加完美。该模块并不能帮助我们实现任何业务功能,但是却在架构运维层面给予我们更多的支持,通过该模块暴露的HTTP接口,我们可以轻松的了解和控制Spring Boot应用的运行情况。
Spring Boot虽然是基于Spring构建的,但是通过上面这些特性的支持,改变了我们使用Spring的姿势,极大得简化了构建企业级应用的各种配置工作,尤其对于很多初学者来说,变得更加容易入门使用。
Spring Boot 2.0 如约而至,升级与否?
万众期待的Spring Boot 2.0终于发布了第一个正式版本,为什么Spring Boot 2.0如此受期待呢?我认为主要有以下几个原因:
- 支持最新的Java 9
- 基于Spring 5构建,Spring的新特性均可以在Spring Boot 2.0中使用
- 为各种组件的响应式编程提供了自动化配置,如:Reactive Spring Data、Reactive Spring Security等
- 支持Spring MVC的非阻塞式替代方案WebFlux以及嵌入式Netty Server
- Spring Boot 2.0的发布,Spring Cloud Finchley还会远吗?
上述列举的内容是笔者主要关心的重要内容,并非Spring Boot 2.0所有的新特性,对于不同的使用者来说相信会有不同的关注点。除此之外,在Spring Boot 2.0中还有非常多其他令人振奋的新特性,比如:对HTTP/2的支持、
- 新增了更灵活的属性绑定API(可以不通过
@ConfigurationProperties
注解就能实现配置内容读取和使用)、 - 对Spring Security整合的简化配置、
- Gradle插件的增强、
- Actuator模块的优化等等。
本文不对这些新特性做详细的介绍,下面主要说说,我们是否有必要将我们的Spring Boot 1.x升级到Spring Boot 2.x,在这过程中,我们需要考虑和注意哪些问题。
@Data
@Component
@ConfigurationProperties(prefix = "spring2.jpa2")
public class MyModel {
private String databasePlatform;
}
//方式2:@EnableConfigurationProperties({MyModel.class}),此时无需加:@Component
Java版本要求的变化
我们在选择是否要升级Spring Boot的时候,最先需要考虑的是Java版本的选择。在Spring Boot 2.0中提高了对Java版本的要求,我们需要至少使用Java 8才能使用它,如果您的Spring Boot应用还运行在Java 7上,那就还得考虑Java的升级成本。
另外,在未来的一段时间内,您是否想要使用Java 9将是一个影响升级与否的重要决策依据,因为Spring Boot 1.x版本明确说明了没有对Java 9的支持计划;换言之,如果你想将Spring Boot运行在Java 9上,那么你必须升级到Spring Boot 2.0。
Tips:当前版本的Spring Boot 2.0虽然支持Java 9,但是依然还有一些问题。比如:JDK的代理支持需要使用AspectJ 1.9,但是该版本还处于RC版;还不支持Apache Cassandra;对于JSP TLDs在嵌入式Tomcat中也无法支持等情况。对于这些问题的具体处理方法可见:Running Spring Boot on Java 9
依赖组件的升级
Spring Boot的Starter中整合了不少优秀的第三方组件,这些组件的升级也需要我们做好一定的考量,在这些组件的版本升级过程中,使用上是否有变化等问题。其中,最为关键的几个组件需要我们注意:
- Tomcat升级至8.5
- Flyway升级至5
- Hibernate升级至5.2
- Thymeleaf升级至3
Tips:前几日曝出的Tomcat漏洞问题。经查Spring Boot 2.0选用的版本为8.5.28,属于安全版本,所以大家可以放心使用。
依赖重组和配置重定位
在Spring Boot 2.0的升级过程中,可能这部分内容将是大家要做出较多修改的地方,所以建议大家在这里留个心眼。由于Spring Boot在构建Starter POMs的时候并非是扁平的一层结构,一些功能模块Starter之间是存在包含引用关系的,比如:spring-boot-starter-thymeleaf中包含了spring-boot-starter-web,因为thymeleaf模版引擎之前肯定是在Spring MVC下使用的。但是,在Spring Boot 2.0中,WebFlux的出现对于Web应用的解决方案将不再唯一,因此spring-boot-starter-thymeleaf中的依赖就不在包含spring-boot-starter-web,开发人员需要自己添加spring-boot-starter-web或spring-boot-starter-webflux来决定是使用哪个模块实现Web应用。
除了类似上面的依赖重组之后,在Spring Boot 2.0中对于配置属性的重定位也是比较多的,这将导致一些原有的配置将不再生效,需要我们手工的去修改这些配置的Key来完成升级适配。比如,一些与servlet相关的server.*
属性重定位到server.servlet
前缀下:
Old property | New property |
---|---|
server.context-parameters.* | server.servlet.context-parameters.* |
server.context-path | server.servlet.context-path |
server.jsp.class-name | server.servlet.jsp.class-name |
server.jsp.init-parameters.* | server.servlet.jsp.init-parameters.* |
server.jsp.registered | server.servlet.jsp.registered |
server.servlet-path | server.servlet.path |
更多的依赖变化、配置重定位以及默认配置的变化,读者可自行查阅官方升级手册:Spring Boot 2.0 Migration Guide
不必要的顾虑
之前有朋友在spring4all社区上问:如果Spring Boot升级2.0,2.0出了那么多新功能,我们的业务代码是否也需要随之修改,风险会不会很大?其实,这个问题大家完全不用太多的顾虑,Spring Boot 2.0虽然新增了很多强大的新特性,但是对于原有功能的支持并没有抛弃。所以,就算我们不用任何类似WebFlux这样的新功能,将工程升级到了Spring Boot 2.0之后,继续使用Spring MVC开发我们的项目也是完全没有影响的。只是,就如上面所述的,我们可能需要做一些依赖和配置上的调整才能继续将应用正常的运行起来。
21. Boot 2.0 新特性
以Java 8 为基准
Spring Boot 2.0 要求Java 版本必须8以上, Java 6 和 7 不再支持。
内嵌容器包结构调整
为了支持reactive使用场景,内嵌的容器包结构被重构了的幅度有点大。EmbeddedServletContainer被重命名为WebServer,并且org.springframework.boot.context.embedded 包被重定向到了org.springframework.boot.web.embedded包下。举个例子,如果你要使用TomcatEmbeddedServletContainerFactory回调接口来自定义内嵌Tomcat容器,你现在应该使用TomcatServletWebServerFactory。
Servlet-specific 的server properties调整
大量的Servlet专属的server.* properties被移到了server.servlet下:
Old property | New property |
---|---|
server.context-parameters.* | server.servlet.context-parameters.* |
server.context-path | server.servlet.context-path |
server.jsp.class-name | server.servlet.jsp.class-name |
server.jsp.init-parameters.* | server.servlet.jsp.init-parameters.* |
server.jsp.registered | server.servlet.jsp.registered |
server.servlet-path | server.servlet.path |
由此可以看出一些端倪,那就是server不再是只有servlet了,还有其他的要加入。
http://localhost:8080/actuator
{
"_links": {
"self": {
"href": "http://localhost:8080/actuator",
"templated": false
},
"health": {
"href": "http://localhost:8080/actuator/health",
"templated": false
},
"health-component": {
"href": "http://localhost:8080/actuator/health/{component}",
"templated": true
},
"health-component-instance": {
"href": "http://localhost:8080/actuator/health/{component}/{instance}",
"templated": true
},
"info": {
"href": "http://localhost:8080/actuator/info",
"templated": false
}
}
}
Actuator 默认映射
Actuator的端点(endpoint)现在默认映射到/application,比如,/info 端点现在就是在/application/info。但你可以使用management.context-path来覆盖此默认值 (boot2.1就被废弃了)。
@ConditionalOnBean
@ConditionalOnBean现在的判断条件由OR变为了AND。
Remote CRaSH shell
1.5的时候此远程工具被标为deprecated,2.0的时候将会把这个支持彻底remove掉,以及基于此功能的项目也会被删除掉。
Spring Loaded不再支持
由于Spring Loaded项目已被移到了attic了,所以不再支持Spring Loaded了。现在建议你去使用Devtools。Spring Loaded不再支持了。
Hazelcast自动配置不再支持
不能再自动配置HazelcastInstance进行缓存。 因此,spring.cache.hazelcast.config属性不再可用。
默认connection pool变了
默认的连接池已经由Tomcat切换到了HikariCP。如果你过去使用spring.datasource.type在基于Tomcat的应用程序中强制使用Hikari,现在你可以删除这个覆盖了。同样的,如果想要使用Tomcat的连接池,只需要简单的加入以下配置就可以了:
spring.datasource.type=org.apache.tomcat.jdbc.pool.DataSource
Servlet Filters
针对一个Filter默认的dispatcher类型现在为 DipatcherType.REQUEST,这样就保证了Spring Boot和Servlet默认的配置统一了。
Spring Security
Spring Security的 filter 现在可以自动配置如下类型了: ASYNC, ERROR, and REQUEST 。这样就让Spring Boot中的配置和Spring Security默认配置保持一致了。
Spring Session
Spring Session的 filter 现在支持自动配置如下dispatcher类型 ASYNC, ERROR, and REQUEST 。同样是为了让Spring Boot的配置与Spring Session的默认配置保持一致。值得注意的是从Spring Session 2.0起, Mongo和GemFire 将不再被支持。
Jetty
要求Jetty最低版本为9.4。
Tomcat
要求Tomcat最低版本为8.5。
Hibernate
要求Hibernate最低版本为5.2。
Gradle
要求Gradle最低版本为3.4。
SendGrid
SendGrid最低支持版本是3.2。为了支持这次升级,username和password已经被干掉了。因为API key现在是唯一支持的认证方式。
Starter 的传递依赖的改变
以前有几个Spring Boot starter是依靠Spring MVC和spring-boot-starter-web传递的。 为了对Spring WebFlux的支持,spring-boot-starter-mustache和spring-boot-starter-thymeleaf不再依赖spring-boot-starter-web。现在你要自己选择并添加spring-boot-starter-web或spring-boot-starter-webflux作为依赖。
**记住:**web和webflux是平行的关系。我们之前的文章中提到过spring webflux。你可以移步查看:Spring 5 新增全新的reactive web框架:webflux。
Solr健康指标
针对Solr的健康检查信息不再是solrStatus这个属性了。现在是status property,是一个标准状态属性,对应于一个的整型值。
默认代理策略
Spring Boot现在默认是使用CGLIB代理,同时包含AOP支持。如果你需要基于代理(proxy-based)的代理策略,你需要把spring.aop.proxy-target-class
设置为false。
基于CLI的测试
从Spring Boot的CLI中删除了测试支持,现在建议你使用Maven或Gradle构建应用程序,去使用它们提供的丰富的测试支持吧。
@ConfigurationProperties
@ConfigurationProperties
里的ignoreNestedProperties属性已被删除。
Multipart配置改变
为了更好的反映Servlet的特性, spring.http.multipart. 属性已经被命名为 spring.servlet.multipart。
ps:其实就是因为webflux来了,只能把servlet和webflux区分开来。
Mustache 模板默认文件扩展名
过去Mustache模板的默认的文件扩展名是.html。现在.mustache成了官方指定的扩展名,而且很多的IDE插件已经支持了此后缀。你可以通过spring.mustache.suffix来覆盖现在的默认的支持。
Spring Framework 5.0
Spring Boot 2.0 是建立在Spring Framework 5.0之上的(最低要求)。Spring 5最大的亮点就是reactive。你可以去看看这篇:Spring 5 新增全新的reactive web框架:webflux。
松绑定改善
松绑定已经得到改善。这里简单的举个例子:
简单的属性在删除特殊字符然后转成小写后进行绑定。比如:
下面的属性最终都会被映射为spring.jpa.databaseplatform=mysql:
spring.jpa.database-platform=mysql
spring.jpa.databasePlatform=mysql
spring.JPA.database_platform=mysql
有关详细信息,我们可以查阅:https://github.com/spring-projects/spring-boot/wiki/Relaxed-Binding-2.0
WebFlux 和 WebFlux.fn支持
Spring Boot 2.0 提供了一个新的starter ,用来支持Reactive Spring web frameworks。该starter为spring-boot-starter-webflux。其中Reactor Netty是默认的web引擎(spring-boot-starter-reactor-netty)。
Reactive数据库支持
Spring Boot 2.0 对一下的数据库提供了自动配置( auto-configuration )的reactive的支持:
- MongoDB (spring-boot-starter-data-mongodb-reactive)
- Redis (spring-boot-starter-data-redis-reactive)
- Cassandra (spring-boot-starter-data-cassandra-reactive)
@DataMongoTest
测试注解也是支持reactive的。
@WebFluxTest支持
Reactive controller现在可以使用@WebFluxTest
来测试。它提供的功能和 @WebMvcTest
类似。而且WebTestClient可以直接使用,已经被自动配置(auto-configured)了。
支持使用@SpringBootTest自动配置WebTestClient
当你使用@SpringBootTest
with an actual server (that is, either DEFINED_PORT or RANDOM_PORT), a WebTestClient is available the same way TestRestTemplate is.
使用@SpringBootTest进行WebTestClient自动配置
将@SpringBootTest用于实际服务器(即DEFINED_PORT或RANDOM_PORT)时,WebTestClient的可用方式与TestRestTemplate相同。
Gradle插件
Spring Boot的Gradle插件已在很大程度上被重写,以实现一些重大的改进。有关这方面的就不细讲了,感兴趣的同学可以去一探究竟。
/loggers端点POST的状态码改变
针对/loggers端点上POST操作的状态码已又200改为204。
Elasticsearch
Elasticsearch已升级到5.4。 与Elastic公司宣布不再支持嵌入式Elasticsearch的情况一样,NodeClient的自动配置已被删除。就是这么的节奏一致。现在你可以通过使用spring.data.elasticsearch.cluster-nodes自动配置TransportClient,具体value可以是一个或多个要连接的节点的地址。
Quartz Scheduler
Spring Boot 2 针对Quartz调度器提供了支持。你可以加入spring-boot-starter-quartz starter来启用。而且支持基于内存和基于jdbc两种存储。
Spring Data Web配置
Spring Boot公开了一个新的spring.data.web配置名称空间,可以轻松配置分页和排序。
Json starter
一个全新的spring-boot-starter-json starter 聚合了很多常用的json工具,可以支持对json的读写。
它不仅仅提供了jackson-databind而且当你使用java8时候,还提供了有用的模块:jackson-datatype-jdk8, jackson-datatype-jsr310 和 jackson-module-parameter-names。
之前使用jackson-databind的地方就可以使用这个新的starter了。
Thymeleaf starter
Thymeleaf starter现在包含了thymeleaf-extras-java8time,开箱即用。
InfluxDB
如果InfluxDB java client 和 the spring.influx.url 被设置, 一个InfluxDB client现在就会被自动配置。而且现在支持认证。
JdbcTemplate
Spring Boot自动配置(auto-configuration)的JdbcTemplate现在可以通过spring.jdbc.template命名空间进行定制。 此外,自动配置(auto-configuration)的NamedParameterJdbcTemplate在底层就是JdbcTemplate。
jOOQ
Spring Boot现在可以根据DataSource自动检测出jOOQ方言(类似于JPA方言)。
此外,还引入了@JooqTest用于只有jOOQ才能hold的测试场景。
@DataRedisTest
新加了一个测试的时候针对redis的新注解。
强大的Mongo客户端自定义
现在可以通过MongoClientSettingsBuilderCustomizer这个bean来高度定制化Spring Boot的Mongo客户端。
Cassandra
spring.data.cassandra 现在支持池化(pooling)。
Kafka listener支持批量消费
现在支持一次性批量消费多个ConsumerRecord,你可以创建一批的监听器(listener),这样设置:
spring.kafka.listener.type=batch
Web filters 初始化
Web filters 现在在所有支持的容器中都会被立刻初始化。也就是eagerly,急加载。
Auto-configuration 报告
现在不满足条件(unconditional)的class也会被包含进来,在自动配置(auto-configuration)的Actuator端点的response中一并返回。
重置logger操作
现在Loggers端点(endpoint) 支持reset日志级别到默认设置。
Maven 插件属性
插件的配置属性现在的暴露方式有所改变,现在所有的都是以spring-boot为前缀,这是为了避免和其他插件冲突而导致错误。
比如,以下命令行可以启用profile foo:
mvn spring-boot:run -Dspring-boot.run.profiles=foo
Devtools 远程调试
已经从Devtools中删除了通过HTTP进行远程调试的支持。(#9489)
Jetty
为了和Tomcat和Undertow看齐,现在对Jetty的所有的http method的请去都进行压缩,而不是之前那样只对GET request进行压缩(#8184)。
Reactive server 自定义
当配置一个reactive web server时,针对Jetty,Tomcat,Undertow的定制化器现在会被调用 (#9572)。
Jolokia
Jolokia不再是一个endpoint。并且默认是禁用的,这已和其他的web端点保持了一直。它的配置已转移到了management.jolokia。如果想启用 Jolokia, 向你的配置加入management.jolokia.enabled=true就可以了。
数据库迁移
Liquibase 和 Flyway 配置的key 已被转移到了spring 的命名空间下:(比如: spring.liquibase and spring.flyway )。
Auto-configuration排序
@AutoConfigureOrder 默认值由Ordered.LOWEST_PRECEDENCE变为0。 (#10142)
Auto-configuration测试工具
一个新的ApplicationContextRunner 测试工具让我们测试自动配置变得容易。 未来将会把所有的测试套件都迁移到这个模型上。
Java 9 支持
基本支持了Java 9。之所以是“基本”,是因为还没得到用户的验证。
Jedis变为了Lettuce
Redis客户端驱动现在由Jedis变为了Lettuce。使用Jedis的同学们,大概知道方向了吧。
但仍然支持Jedis,那么exclude掉io.lettuce:lettuce-core,然后添加 redis.clients:jedis就是了。
OAuth 2.0 支持
Spring Security OAuth 项目中的功能将会迁移到Spring Security中。将会OAuth 2.0。
Mockito 1.x
Mockito 1.x不再支持@MockBean和@SpyBean。 如果你不使用spring-boot-starter-test来管理依赖关系,则应升级到Mockito 2.x。
JSON-B 支持
除了Jackson 和 Gson,现在还支持了JSON-B 。JSON测试支持也已更新为新的JsonbTester类。
Session Endpoint
Spring Session 用现在可以通过/application/sessions Actuator Endpoint进行查找和删除session。
ConfigurationProperties 验证
如果你希望@ConfigurationProperties
对象上开启验证,那么只需要添加@Validated
就可以了。
Spring Mobile
针对Spring Mobile的自动配置和依赖不再支持,已被删除。汗,我们之前的文章中还介绍过这个项目:使用Spring Boot开发一个Spring Mobile程序。
Spring WebFlux支持错误约定
Spring Boot现在让WebFlux的错误约定和MVC保持一致就像使用MVC一样:默认视图和JSON响应错误,自定义错误视图等等。
TLS 配置 和 HTTP/2 支持
你现在可以为你的WebFlux应用配置SSL,使用server.ssl.*
配置属性。Tomcat, Jetty, Undertow 和 Reactor Netty都支持。
你现在也可以为你的MVC 或 WebFlux应用配置HTTP/2:
使用server.http2.enabled
。
@KafkaListener支持使用@SendTo
使用了自动配置工厂的Kafka listener现在支持@SendTo
。
Kotlin扩展
Spring Boot 2.0 发布了Kotlin runApplication扩展:
package com.example.demo
import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.runApplication
@SpringBootApplication
class DemoApplication
fun main(args: Array<String>) {
runApplication<DemoApplication>(*args)
}
Job command line runner 顺序
CommandLineRunner 现在执行批处理job的启动order是0。
支持自动配置的模板化欢迎页
Spring Boot 2.0 现在支持静态和模板化两种欢迎页类型。它会首先去配置好的静态内容的目录下查找index.html文件,如果没找到,然后就去查找index模板。 只要找到了一个就会被用作欢迎页。
Context path会在启动时被打印
在Spring Boot之前的版本中,对context path貌似并没有那么的重视一样。现在当我们使用内嵌容器的时候, context path 会被打印在HTTP 端口的旁边,像这样:
Tomcat started on port(s): 8080 (http) with context path ‘/foo’
测试优化,自动扫描Converter和GenericConverter
Converter 和 GenericConverter beans现在可以被@WebMvcTest和@WebFluxTest自动扫描到了。
Health vs. Status
status endpoint 已经被删除了,现在改成了health。这个health 端点既可以展示status也可以有更多的细节。 health 端点现在默认是被暴露的(只展示status)。如果你希望展示更多的细节信息,可以通过修改属性management.endpoints.health.show-details来实现:
management.endpoints.health.show-details=true
本文作者:贺卓凡,
原文链接:https://mp.weixin.qq.com/s/EWmuzsgHueHcSB0WH-3AQw
22. Spring Boot 2.0与Java 9
必须使用Spring Boot2.0
在Spring Boot的版本计划中明确说明了2.0版本开始才对Java 9进行支持,而1.x版本暂时没有对Java 9的支持计划,所以如果我们要使用Java 9,就必须将Spring Boot版本升级至2.0。
细节注意点
AspectJ
在Java9中要使用JDK的编译织入切面时,我们需要引入AspectJ 1.9,但是这个版本还处于RC状态,并不是正式版本,所以当Spring Boot 2会在Aspect 1.9 GA的时候更新这个版本依赖。
JAXB
如果使用Hibernate的情况下,由于依赖JAXB,这个时候可能会碰到这个错误:java.lang.NoClassDefFoundError: javax/xml/bind/JAXBException
,面对这个问题,只需要引入如下依赖就可以解决:
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.3.0</version>
</dependency>
测试插件
最新的maven-surefire-plugin
插件(2.20.1版本)需要手工指定一个模块以防止包含java.se.ee
:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<argLine>--add-modules java.base</argLine>
</configuration>
</plugin>
或者也可以指定降级到2.20.0版本
一些暂不支持的类库
- Apache Cassandra,具体可见:#10453
- JSP TLDs在嵌入式Tomcat中不生效,具体可见:#10456
参考资料
23. 2.0 新特性1:配置绑定
在Spring Boot 2.0中推出了Relaxed Binding 2.0,对原有的属性绑定功能做了非常多的改进以帮助我们更容易的在Spring应用中加载和读取配置信息。下面本文就来说说Spring Boot 2.0中对配置的改进。
配置文件绑定
简单类型
在Spring Boot 2.0中对配置属性加载的时候会除了像1.x版本时候那样移除特殊字符外,还会将配置均以全小写的方式进行匹配和加载。所以,下面的4种配置方式都是等价的:
- properties格式:
spring.jpa.databaseplatform=mysql
spring.jpa.database-platform=mysql
spring.jpa.databasePlatform=mysql
spring.JPA.database_platform=mysql
- yaml格式:
spring:
jpa:
databaseplatform: mysql
database-platform: mysql
databasePlatform: mysql
database_platform: mysql
Tips:推荐使用全小写配合-
分隔符的方式来配置,比如:spring.jpa.database-platform=mysql
List类型
在properties文件中使用[]
来定位列表类型,比如:
spring.my-example.url[0]=http://example.com
spring.my-example.url[1]=http://spring.io
也支持使用逗号分割的配置方式,上面与下面的配置是等价的:
spring.my-example.url=http://example.com,http://spring.io
而在yaml文件中使用可以使用如下配置:
spring:
my-example:
url:
- http://example.com
- http://spring.io
也支持逗号分割的方式:
spring:
my-example:
url: http://example.com, http://spring.io
注意:在Spring Boot 2.0中对于List类型的配置必须是连续的,不然会抛出UnboundConfigurationPropertiesException
异常,所以如下配置是不允许的:
foo[0]=a
foo[2]=b
在Spring Boot 1.x中上述配置是可以的,foo[1]
由于没有配置,它的值会是null
Map类型
Map类型在properties和yaml中的标准配置方式如下:
- properties格式:
spring.my-example.foo=bar
spring.my-example.hello=world
- yaml格式:
spring:
my-example:
foo: bar
hello: world
注意:如果Map类型的key包含非字母数字和-
的字符,需要用[]
括起来,比如:
spring:
my-example:
'[foo.baz]': bar
环境属性绑定
简单类型
在环境变量中通过小写转换与.
替换_
来映射配置文件中的内容,比如:环境变量SPRING_JPA_DATABASEPLATFORM=mysql
的配置会产生与在配置文件中设置spring.jpa.databaseplatform=mysql
一样的效果。
List类型
由于环境变量中无法使用[
和]
符号,所以使用_
来替代。任何由下划线包围的数字都会被认为是[]
的数组形式。比如:
MY_FOO_1_ = my.foo[1]
MY_FOO_1_BAR = my.foo[1].bar
MY_FOO_1_2_ = my.foo[1][2]
另外,最后环境变量最后是以数字和下划线结尾的话,最后的下划线可以省略,比如上面例子中的第一条和第三条等价于下面的配置:
MY_FOO_1 = my.foo[1]
MY_FOO_1_2 = my.foo[1][2]
系统属性绑定
简单类型
系统属性与文件配置中的类似,都以移除特殊字符并转化小写后实现绑定,比如下面的命令行参数都会实现配置spring.jpa.databaseplatform=mysql
的效果:
-Dspring.jpa.database-platform=mysql
-Dspring.jpa.databasePlatform=mysql
-Dspring.JPA.database_platform=mysql
List类型
系统属性的绑定也与文件属性的绑定类似,通过[]
来标示,比如:
-D"spring.my-example.url[0]=http://example.com"
-D"spring.my-example.url[1]=http://spring.io"
同样的,他也支持逗号分割的方式,比如:
-Dspring.my-example.url=http://example.com,http://spring.io
属性的读取
上文介绍了Spring Boot 2.0中对属性绑定的内容,可以看到对于一个属性我们可以有多种不同的表达,但是如果我们要在Spring应用程序的environment中读取属性的时候,每个属性的唯一名称符合如下规则:
- 通过
.
分离各个元素 - 最后一个
.
将前缀与属性名称分开 - 必须是字母(a-z)和数字(0-9)
- 必须是小写字母
- 用连字符
-
来分隔单词 - 唯一允许的其他字符是
[
和]
,用于List的索引 - 不能以数字开头
所以,如果我们要读取配置文件中spring.jpa.database-platform
的配置,可以这样写:
this.environment.containsProperty("spring.jpa.database-platform")
而下面的方式是无法获取到spring.jpa.database-platform
配置内容的:
this.environment.containsProperty("spring.jpa.databasePlatform")
注意:使用@Value
获取配置内容的时候也需要这样的特点
全新的绑定API
在Spring Boot 2.0中增加了新的绑定API来帮助我们更容易的获取配置信息。下面举个例子来帮助大家更容易的理解:
例子一:简单类型
假设在propertes配置中有这样一个配置:com.didispace.foo=bar
我们为它创建对应的配置类:
@Data
@ConfigurationProperties(prefix = "com.didispace")
public class FooProperties {
private String foo;
}
接下来,通过最新的Binder
就可以这样来拿配置信息了:
@SpringBootApplication
public class Application {
public static void main(String[] args) {
ApplicationContext context = SpringApplication.run(Application.class, args);
Binder binder = Binder.get(context.getEnvironment());
// 绑定简单配置
FooProperties foo = binder.bind("com.didispace", Bindable.of(FooProperties.class)).get();
System.out.println(foo.getFoo());
}
}
例子二:List类型
如果配置内容是List类型呢?比如:
com.didispace.post[0]=Why Spring Boot
com.didispace.post[1]=Why Spring Cloud
com.didispace.posts[0].title=Why Spring Boot
com.didispace.posts[0].content=It is perfect!
com.didispace.posts[1].title=Why Spring Cloud
com.didispace.posts[1].content=It is perfect too!
要获取这些配置依然很简单,可以这样实现:
ApplicationContext context = SpringApplication.run(Application.class, args);
Binder binder = Binder.get(context.getEnvironment());
// 绑定List配置
List<String> post = binder.bind("com.didispace.post", Bindable.listOf(String.class)).get();
System.out.println(post);
List<PostInfo> posts = binder.bind("com.didispace.posts", Bindable.listOf(PostInfo.class)).get();
System.out.println(posts);
Chapter2-2-1
目录:
24. 2.0 新特性2:新增事件ApplicationStartedEvent
2.0版本中的事件模型,尤其是新增的事件:
ApplicationStartedEvent
。
在Spring Boot 2.0中对事件模型做了一些增强,主要就是增加了ApplicationStartedEvent
事件,所以在2.0版本中所有的事件按执行的先后顺序如下:
ApplicationStartingEvent
ApplicationEnvironmentPreparedEvent
ApplicationPreparedEvent
ApplicationStartedEvent
<= 新增的事件ApplicationReadyEvent
ApplicationFailedEvent
从上面的列表中,我们可以看到ApplicationStartedEvent
位于ApplicationPreparedEvent
之后,ApplicationReadyEvent
之前。
下面我们通过代码的方式来直观的感受这个事件的切入位置,以便与将来我们在这个切入点加入自己需要的逻辑。
第一步:我们可以编写ApplicationPreparedEvent
、ApplicationStartedEvent
以及ApplicationReadyEvent
三个事件的监听器,然后在这三个事件触发的时候打印一些日志来观察它们各自的切入点,比如:
@Slf4j
public class ApplicationPreparedEventListener implements ApplicationListener<ApplicationPreparedEvent> {
@Override
public void onApplicationEvent(ApplicationPreparedEvent event) {
log.info("......ApplicationPreparedEvent......");
}
}
@Slf4j
public class ApplicationStartedEventListener implements ApplicationListener<ApplicationStartedEvent> {
@Override
public void onApplicationEvent(ApplicationStartedEvent event) {
log.info("......ApplicationStartedEvent......");
}
}
@Slf4j
public class ApplicationReadyEventListener implements ApplicationListener<ApplicationReadyEvent> {
@Override
public void onApplicationEvent(ApplicationReadyEvent event) {
log.info("......ApplicationReadyEvent......");
}
}
第二步:在/src/main/resources/
目录下新建:META-INF/spring.factories
配置文件,通过配置org.springframework.context.ApplicationListener
来加载上面我们编写的监听器。
org.springframework.context.ApplicationListener=
com.didispace.ApplicationPreparedEventListener,\
com.didispace.ApplicationReadyEventListener,\
com.didispace.ApplicationStartedEventListener
此时,我们运行Spring Boot应用可以获得类似如下日志输出:
......ApplicationPreparedEvent......
程序启动,端口开启
......ApplicationStartedEvent......
......ApplicationReadyEvent......
从日志中我们可以看到清晰的看到ApplicationPreparedEvent
、ApplicationStartedEvent
以及ApplicationReadyEvent
三个事件的切入点。通过这个例子可能读者会感到疑问:ApplicationStartedEvent
和ApplicationReadyEvent
从事件命名和日志输出位置来看,都是应用加载完成之后的事件,它们是否有什么区别呢?
下面可以看看官方文档对ApplicationStartedEvent
和ApplicationReadyEvent
的解释:
An ApplicationStartedEvent is sent after the context has been refreshed but before any application and command-line runners have been called.An ApplicationReadyEvent is sent after any application and command-line runners have been called. It indicates that the application is ready to service requests
从文档中我们可以知道他们两中间还有一个过程就是command-line runners
被调用的内容。所以,为了更准确的感受这两个事件的区别,我们在应用主类中加入CommandLineRunner
的实现,比如:
@Slf4j
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
@Bean
public DataLoader dataLoader() {
return new DataLoader();
}
@Slf4j
static class DataLoader implements CommandLineRunner {
@Override
public void run(String... strings) throws Exception {
log.info("Loading data...");
}
}
}
最后,我们再运行程序,此时我们可以发现这两个事件中间输出了上面定义的DataLoader
的输出内容,具体如下:
......ApplicationStartedEvent......
Loading data...
......ApplicationReadyEvent......
查看下面仓库中的Chapter1-2-1
目录
15. Boot 2.2,支持 Java13
之前 Spring Boot 2.2没能按时发布,是由于 Spring Framework 5.2 的发布受阻而推迟。这次随着 Spring Framework 5.2.0 成功发布之后,Spring Boot 2.2 也紧跟其后,发布了第一个版本:2.2.0。
组件版本更新
这些Spring框架组件更新了依赖版本:
- Spring AMQP 2.2
- Spring Batch 4.2
- Spring Data Moore
- Spring Framework 5.2
- Spring HATEOAS 1.0
- Spring Integration 5.2
- Spring Kafka 2.3
- Spring Security 5.2
- Spring Session Corn
框架中涉及的第三方包也更新了依赖版本:
- Elasticsearch 6.7
- Flyway 6.0
- Jackson 2.10
- JUnit 5.5
- Micrometer 1.3
- Reactor Dysprosium
- Solr 8.0
大幅的性能提升
关于Spring Boot的性能问题是我们经常在内容平台上看到吐槽的关键词。这次在Spring Boot 2.2中,针对性能这一点,做了大幅的优化。应用程序的启动速度将变得更快,内存占用也会变得更少。
同时,为了加快应用的启动,还增加一个全局延迟初始化的配置参数spring.main.lazy-initialization
,这可以让我们的应用更快的完成启动动作,但是值得注意的是,延迟启动也会有下面这些副作用:
- 应用在进行延迟初始化的时候,HTTP请求的处理会需要更长的时间
- 原本可能在启动期出现的错误,将延迟到启动的运行期间出现
Java 13的支持
由于Spring Framework 5.2增加了对Java 13的支持,所以Spring Boot 2.2也自然增加了这一特性。同时,Spring Boot 2.2对于老版本的Java 11、Java 8依然支持良好。所以,对于还在使用Java 8的用户也可以安心的升级使用。
不可变的 @ConfigurationProperties 绑定
配置属性现在支持基于构造函数的绑定,该绑定允许@ConfigurationProperties
注解修饰的类是不可变的。可以通过使用@ConstructorBinding
注解修饰@ConfigurationProperties
类或其构造函数之一来启用基于构造函数的绑定。可以在配置属性绑定提供的构造函数参数上使用@DefaultValue和@DateTimeFormat
之类的注释。
更多详细信息参阅文档:https://docs.spring.io/spring-boot/docs/2.2.0.RELEASE/reference/html/spring-boot-features.html#boot-features-external-config-constructor-binding
RSocket 支持
已为RSocket添加了自动化配置的starter实现:spring-boot-starter-rsocket
。当项目依赖了spring-security-rsocket
的时候,该starter还会自动配置Spring Security对RSocket的集成实现。
更多详细信息参阅文档:https://docs.spring.io/spring-boot/docs/2.2.0.RELEASE/reference/html//spring-boot-features.html#boot-features-rsocket
健康检查的分组支持
现在可以将Spring Boot Actuator中各种各样的健康指标实现分组。如果将应用程序部署到Kubernetes,一个典型的需求是您可能需要不同组的健康指标来进行“liveness”和“readiness”的探测。这个时候,我们就可以通过配置属性来定义不同的分组,比如:下面创建了一个仅具有DataSource指示器的自定义组:
management.endpoint.health.group.custom.include=db
通过访问localhost8080/actuator/health/custom
,就可以访问自定义的组了。
25. Spring Boot 2.3.0 发布
Spring Boot 2.3.0 已经发布,此版本主要更新内容包括:
依赖升级
新版本核心组件依赖升级
- Spring Data Neumann
- Spring HATEOAS 1.1
- Spring Integration 5.3
- Spring Kafka 2.5
- Spring Security 5.3
- Spring Session Dragonfruit
三方组件依赖
- Cassandra Driver 4.6
- Couchbase Client 3.0
- Elasticsearch 7.6
- Kafka 2.5
- Micrometer 1.5
- MongoDB 4.0
支持 Java 14
spring boot 2.3.0 支持 Java 14 ,同样对 Java 11 、Java 8 提供兼容
Docker 容器支持
spring boot 2.3.0 添加了部分功能用来帮助将Spring Boot 应用直接打包到 Docker 镜像。
支持 Cloud Native Buildpacks 构建镜像
maven 插件 增加 spring-boot:build-image 、gradle增加bootBuildImage task 帮助快速构建镜像
支持jar 分层,更好的优化打包镜像过程
优雅关机
目前内置的四个嵌入式Web服务器(Jetty,Reactor Netty,Tomcat和Undertow)以及响应式和基于Servlet的Web应用程序都支持优雅关机。
配置关机缓冲时间后,在关闭时,Web服务器将不再允许新请求,并且将等待缓冲时间以使活动请求完成。
服务可用性探针
spring boot 2.3.0 内置了应用可用性判断的功能,可以跟踪应用程序是否处理活动状态和是否准备好处理请求。详细可以参考:liveness-and-readiness-probes-with-spring-boot
其他变化
详细的发版日志可以参考Spring-Boot-2.3-Release-Notes。也可以在此处找到在下一版本中删除的不推荐使用的类和方法的列表。
目前spring boot 已经有680多人参与提交了代码, 并且超过26000次 commit。
26. 2.3.0放弃 Maven 转投 Gradle ?
在 2.3.0 中对 Spring Boot 进行了相当重大的更改,这是使用 Gradle 而非 Maven 构建的项目的第一个版本。
Spring 的每个项目都独立的项目组在开发运营,在用户最常使用的白盒部分(例如 API 设计)保持一致性,对于用户不可见的黑盒部分,各个项目组选择自己适合工具没有统一的约定。
例如: 项目构建工具。Spring Framework 自 2012 年的 3.2.0 起就使用 Gradle 构建,而一年后开始使用 Spring Boot,此后不久又开始使用 Spring Cloud,两者都基于 Maven。
项目 | 构建工具 |
---|---|
Spring Framework | Gradle |
Spring Boot | Maven |
Spring Cloud | Maven |
为什么要切换
Spring Boot 团队考虑由 Maven 切换到 Gradle 的主要原因为了减少构建项目所需的时间。在开发和测试过程中,等待构建完成所花费的时间增加了修复错误和实现新功能所花费的时间。
为了解决这个问题,团队曾尝试利用 Maven 对并行构建的支持。由于 Spring Boot 构建的复杂性,特别是对 Invoker 插件的使用,尝试失败。通过将构建分为四个部分来解决 CI 问题。首先构建项目的主要核心,然后并行构建三个独立的部分。但 CI 的构建仍需要一个小时或更长时间。此外,由于针对的是模块化 CI 构建,因此并没有使得开发人员本地构建效率有所改变。
Spring Boot 团队在其他利用 Gradle 作为构建工具的 Spring 项目中看到了 Gradle 的增量和并行构建以及在第三方项目中看到了 Gradle 的构建缓存的好处。希望通过使用 Gradle 为 Spring Boot 构建获得类似的好处。
Gradle 具有非常灵活的构建模型,并且可以定义每个任务的输入和输出及其相互依赖性。这种构建模型的好处是,它允许任务并行运行,同时也可以增量、缓存或完全跳过。换句话说,Gradle 可以最小化的执行必要的 CI 任务。虽然可以使用了 Gradle Enterprise 的 Maven 支持,我们也可以享受构建缓存和跳过的好处。但是要充分享受这四个方面的好处,必须尝试切换到 Gradle。
如何切换
Gradle 配置过于灵活,导致它的构建比基于 Maven 构建更难以维护和理解。例如: 同一个构建结果,可以通过不同的配置实现。如果切换到 Gradle,需要避免这种情况。从目前发布的四个 Spring Boot 2.3 里程碑版本,在核心团队或贡献者中,还没有发现任何重大的构建问题。
- Spring Boot 关键功能是约定优于配置,将这种方法应用于构建。避免在 build.gradle 文件中包含命令式逻辑,编写了几个可以在项目的中找到的小插件 buildSrc。。
虽然现有 Gradle 生态系统对 Spring Boot 构建几乎空白,需要从头通过编写很多通用的 gradle 插件来应用到 Spring Boot,但迁移到 Gradle 的提交从代码库中删除了近 9500 行。
切换结果
就减少项目构建时间而言,将构建迁移到 Gradle 无疑是成功的。如上所述,在 CI 和开发人员机器上,基于 Maven 的完整构建都需要一个小时或更长时间。而基于 Gradle 的平均成功构建时间为 9 分 22 秒,如以下截图所示:
如果对构建性能的更多细节感兴趣,可以在 Spring Boot 的公共Gradle Enterprise实例上获得更多数据。
除了提高性能外,对其他功能进行探索。例如,一段时间以来,进行许多不稳定的测试。由于这些原因,构建失败的次数比预期要多,可以在 Tests 仪表板中看到这一点。使用 Gradle 分片测试来替代 CI 的通用测试方案,并帮组我们了解是否已成功解决问题。
结论
CI 构建现在平均大约需要 20 分钟,比以前快 3-4 倍。
本地构建平均需要 2 分钟 30 秒,比以前快 20-30 倍。
本文作者:冷冷zz,
原文链接:https://juejin.im/post/5ee6c3dc6fb9a047b75a26bc
27. 2.3.2 发布,解决 Too many open files 导致的应用宕机问题
- Spring Boot 2.3.2
- Spring Boot 2.2.9
- Spring Boot 2.1.16
现在可从 repo.spring.io 和 Maven Central 获得。
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.2.RELEASE</version>
<relativePath/>
</parent>
多个版本发布,本文仅着重分享关于 v2.3 版本的更新报告,此版本包括 88 个错误修复,增强功能,文档改进和依赖项升级。
更新日志
新特性
- 增强 Liveness/Readiness 的健康监测并支持配置探针
- 构建 Docker 镜像支持可配置参数
- 增加 反应式 Elasticsearch 健康检查
问题修复与优化
- Upgrade to Reactor Dysprosium-SR10 #22376。解决 v2.2.8 、v2.3.2 版本 Too many open files,导致应用宕机问题
- Redis Cluster 造成反应式 Redis 健康检查失效问题修复 #22096
- 优化 优雅关机的业务场景,支持 Spring Cloud 应用 #22014
- 欢迎页(index.html)绕过 / 控制器问题 #21909
更多日志可参考 https://github.com/spring-projects/spring-boot/releases/tag/v2.3.2.RELEASE 获取
总结
若你环境中使用的是 spring boot v2.3.1 或者 v2.2.8 版本 请及时更新至当前版本。
解决由于 reactor-netty bug 造成的服务宕机,例如 【spring cloud gateway 网关应用】、【spring boot admin 监控应用】
本文作者:冷冷zz,
28. 2.4.0 正式发布!全新的配置处理机制,拥抱云原生!
2020年11月12日,Spring官方发布了Spring Boot 2.4.0 GA的公告。
在这个版本中增加了大量的新特性和改进,下面我们一起看看在这个重要版本中都有哪些值得关注的内容!
更新内容
- 版本命名的更改,从2.4开始,版本名将去除RELEASE后缀,所以这次的版本不是2.4.0.RELEASE,而是2.4.0
- 改进了 application.properties 和 application.yml 文件的处理方式。如果您只有一个简单的 application.properties 或 application.yml 文件,那么您的升级应该是无缝的。但是,如果您有更复杂的设置,那么如果您想使用新特性,则可能需要进行一些更改。更细节的内容可参考:
https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-Config-Data-Migration-Guide
- 新的 spring.config.import 属性可用于导入 Kubernetes 中常用的配置树。
- 现在可以使用一个新的startup端点来显示有关应用程序启动的信息。这个端点可以帮助您识别比预期启动时间更长的 bean。
- Docker/Buildpack的支持,可以更方便的构建镜像
- 完美支持Java 15
- 相关依赖的升级
- Spring AMQP 2.3
- Spring Batch 4.3
- Spring Data 2020.0
- Spring Framework 5.3
- Spring HATEOAS 1.2
- Spring Integration 5.4
- Spring Kafka 2.6
- Spring Retry 1.3
- Spring Security 5.4
- Spring Session 2020.0
- 嵌入式数据库的检测逻辑改进,只有当数据库在内存中时才视为嵌入式数据库。所以,如果当你对 H2、 HSQL 和 Derby 采用文件形式持久化的时候将不会自动初始化
- Logback配置属性的更改
- logging.pattern.rolling-file-name → logging.logback.rollingpolicy.file-name-pattern
- logging.file.clean-history-on-start → logging.logback.rollingpolicy.clean-history-on-start
- logging.file.max-size → logging.logback.rollingpolicy.max-file-size
- logging.file.total-size-cap → logging.logback.rollingpolicy.total-size-cap
- logging.file.max-history → logging.logback.rollingpolicy.max-history
- 默认情况下,不在 HTTP traces中包含 Cookie 请求头和 set-Cookie 响应头。如果从 Spring Boot 2.3升级的话,需要将 management.trace.http.include 配置设置为 cookies、 errors、 request-headers、 response-headers。
rolling
英 /ˈrəʊlɪŋ/ 美 /ˈroʊlɪŋ/ 全球(美国)
简明 牛津 柯林斯 例句 百科
adj. 起伏的,绵延的;规则的,周而复始的;(走路)左右摇晃的,摇摆的;(水面)汹涌澎湃的;旋转的
n. 旋转,动摇,轰响
policy
英 /ˈpɒləsi/ 美 /ˈpɑːləsi/ 全球(美国)
简明 牛津 新牛津 韦氏 柯林斯 例句 百科
n. 政策,方针;(处事) 原则,策略;保险单
- Undertow 在转发请求时将保留原始请求 URL。这个版本覆盖了 Undertow 的默认设置,以符合 Servlet 规范。当然,你也可以将属性 server.undertow.preserve-path-on-forward 设置为 true,来恢复 Undertow 的默认行为。
- 使用ES的用户需要注意,这个版本中不再自动配置低级的 Elasticsearch RestClient,但 RestHighLevelClient 仍然是可以自动配置的。建议用户不应该使用低级的客户端,应该使用更高级的客户端的,所以这样的改动应该不会影响太多用户。
- 如果你正在使用 Flyway 5,请确保在升级到 Spring Boot 2.4之前升级到 Flyway 6,因为 Flyway 只对一个功能版本进行模式升级。
29. 2020最后一击:2.4.1、2.3.7、2.2.12 发布
近日,Spring Boot官方发布了本年度最后一次版本更新,主要针对目前维护的三个版本:
- 2.4.x:第一个bug修复版本 2.4.1
- 2.3.x:常规维护版本 2.3.7
- 2.2.x:常规维护版本 2.2.12
由于2.2.x和2.3.x已经非常稳定,所以我们主要关注本次2.4.1的更新。
2.4.1版本内容
由于在Spring Boot 2.4.0版本中,对原有的配置加载机制做了较大改动,不少开发者反映在升级的时候也出现了各种不同的问题。而这次2.4.1的发布,主要着手解决了不少关于配置相关的Bug。下面我们一起看看这次都解决了哪些重要问题:
- 通过通配符匹配的配置文件互相覆盖的问题
- 配置属性与JavaBean之间绑定的顺序问题
- 允许递归配置文件组的引用
- 外部应用程序属性加载顺序的问题
- @Name在Kotlin中绑定失败的问题
- Redis健康检查器对性能消耗过大的问题
- Actuator端点在MVC和WebFlux下运行时,无法正确响应自定义HTTP状态码
- Actuator的env端点没有正确显示包装类型的数据
- 通过配置树绑定非字符串属性时,找不到转换器的问题
- 使用Log4J调用LoggingSystem时会抛出NullPointerException的问题
- 加载属性文件的时候,“#”标注之后的内容会丢失
- 在启用 WebTestClientContextCustomizer 之前,确保 WebClient 已经存在
可以看到,大量的修复都是针对配置相关的。那么读者在之前的升级过程中,是否有碰到上述问题吗?
这次的更新是否可以解决呢?欢迎留言说说你对2.4.0版本的看法吧!
Spring Boot 2.5.0 发布:支持Java16、Gradle 7、Datasource初始化机制调整
今年的520事情是真的多,把Spring Boot 2.5.0的版本发布都给忽略了!今天就跟DD一起看看Spring Boot 2.5.0又都带来了哪些振奋人心的新特性吧!
主要更新
- 支持 Java 16
- 支持 Gradle 7
- 支持 Jetty 10
- 增强 Docker 镜像的构建
- 更新了Datasource的初始化机制
除了框架功能更新之后,该版本在文档方面也顺应时代潮流,增加了暗黑模式的支持!
长这样,是你喜欢的阅读模式吗?
其他更新
management.endpoints.web.cors.allowed-origin-patterns
配置可以用来控制是否允许Actuator端点跨域访问HttpSessionIdListener
现在开始自动注册到Servlet上下文- Couchbase现在默认使用自动化配置的
ObjectMapper
- Elasticsearch的
Sniffer
会根据classpath下是否存在elasticsearch-rest-client-sniffer
模块来自动配置 spring.data.cassandra.controlconnection.timeout
现在可以用来配置Cassandra的连接超时控制spring.kafka.listener.only-log-record-metadata
现在可以用来配置重试时记录的元数据- 支持Apache Phoenix,自动检测
jdbc:phoenix
这样的JDBC链接配置 /actuator
的发现页现在可以通过management.endpoints.web.discovery.enabled
配置来禁用/actuator/configprops
和actuator/env
端点现在可以用additional-keys-to-sanitize
来配置不展示的key- 如果要自定义JMX的Actuator端点,可以使用
EndpointObjectNameFactory
- 当classpath下有Spring Security的时候,会自动配置并绑定
RSAPublicKey
和RSAPrivateKey
- RabbitMQ的
ConnectionFactory
现在可以通过ConnectionFactoryCustomizer
来实现自定义 CloudPlatform
现在可以自动侦测Azure App Serviceserver.tomcat.keep-alive-timeout
可以用来配置Tomcat在关闭keep-alive连接之前等待另一个请求的时间。server.tomcat.max-keep-alive-requests
可以用来控制在keep-alive状态的连接关闭之前可以保持的最大请求数。spring.webflux.session.cookie.same-site
用来配置WebFlux的SameSite cookie策略,默认为lax- Apache HttpCient 5现在是默认的自动化配置使用WebClient
依赖组件版本
在Spring Boot 2.5 中更新了各项依赖组件的版本,具体清单如下:
- Spring Data 2021.0
- Spring HATEOAS 1.3
- Spring Integration 5.5
- Spring Kafka 2.7
- Spring Retry 1.3
- Spring Security 5.5
- Spring Session 2021.0
下面是第三方依赖组件的版本清单:
- Kotlin 1.5
- Groovy 3.0
- Flyway 7.7
- Liquibase 4.2
- Jackson 2.12
- Kafka 2.7
- Cassandra Driver 4.10
- Embedded Mongo 3.0
- Hibernate Validator 6.2
- Jersey 2.33
- Mockito 3.7
- MongoDB 4.2
- JUnit Jupiter 5.7
- Elasticsearch 7.12
弃用内容
以下是Spring Boot 2.5中被弃用的内容,大家升级的时候有所涉及的要做好调整哦!
- 原位于
org.springframework.boot.actuate.endpoint.http
包下的ActuatorMediaType
和ApiVersion
被整合并移动到了org.springframework.boot.actuate.endpoint
包下。
- 原用于实现jOOQ的一些Provider的回调接口以及配置从这个版本开始弃用。后面要使用
org.springframework.boot.autoconfigure.jooq.DefaultConfigurationCustomizer
来替代。 - 原位于
org.springframework.boot.autoconfigure.data.jpa
包下的EntityManagerFactoryDependsOnPostProcessor
移动到org.springframework.boot.autoconfigure.orm.jpa
包下
更多关于Spring Boot 2.5.0的发布资讯可参考官方页面