资讯详情

boot教程5,2.0-2.5新特性,自动配置双刃剑,spring帝国神兵出世,转投Gradle,拥抱云原生

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(exclude={DataSourceAutoConfiguration.class}) 

@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class}) 

@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.不像今天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 除了对依赖注入的支持和增强外,还有很长一段时间,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中提供了一系列的,将各种功能性模块进行了划分与封装,让我们可以更容易的引入和使用,有效的避免了用户在构建传统Spring应用时维护大量依赖关系而引发的JAR冲突等问题。
  • 自动化配置:Spring Boot为每一个Starter都提供了,用来替代我们传统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如此受期待呢?我认为主要有以下几个原因:

  1. 支持最新的Java 9
  2. 基于Spring 5构建,Spring的新特性均可以在Spring Boot 2.0中使用
  3. 为各种组件的响应式编程提供了自动化配置,如:Reactive Spring Data、Reactive Spring Security等
  4. 支持Spring MVC的非阻塞式替代方案WebFlux以及嵌入式Netty Server
  5. 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 新特性

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专属的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的端点(endpoint)现在默认映射到/application,比如,/info 端点现在就是在/application/info。但你可以使用management.context-path来覆盖此默认值 (boot2.1就被废弃了)。

@ConditionalOnBean现在的判断条件由OR变为了AND。

1.5的时候此远程工具被标为deprecated,2.0的时候将会把这个支持彻底remove掉,以及基于此功能的项目也会被删除掉。

由于Spring Loaded项目已被移到了attic了,所以不再支持Spring Loaded了。现在建议你去使用Devtools。Spring Loaded不再支持了。

不能再自动配置HazelcastInstance进行缓存。 因此,spring.cache.hazelcast.config属性不再可用。

默认的连接池已经由Tomcat切换到了HikariCP。如果你过去使用spring.datasource.type在基于Tomcat的应用程序中强制使用Hikari,现在你可以删除这个覆盖了。同样的,如果想要使用Tomcat的连接池,只需要简单的加入以下配置就可以了:

spring.datasource.type=org.apache.tomcat.jdbc.pool.DataSource

针对一个Filter默认的dispatcher类型现在为 DipatcherType.REQUEST,这样就保证了Spring Boot和Servlet默认的配置统一了。

Spring Security的 filter 现在可以自动配置如下类型了: ASYNC, ERROR, and REQUEST 。这样就让Spring Boot中的配置和Spring Security默认配置保持一致了。

Spring Session的 filter 现在支持自动配置如下dispatcher类型 ASYNC, ERROR, and REQUEST 。同样是为了让Spring Boot的配置与Spring Session的默认配置保持一致。值得注意的是从Spring Session 2.0起, Mongo和GemFire 将不再被支持。

要求Jetty最低版本为9.4。

要求Tomcat最低版本为8.5。

要求Hibernate最低版本为5.2。

要求Gradle最低版本为3.4。

SendGrid最低支持版本是3.2。为了支持这次升级,username和password已经被干掉了。因为API key现在是唯一支持的认证方式。

以前有几个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的健康检查信息不再是solrStatus这个属性了。现在是status property,是一个标准状态属性,对应于一个的整型值。

Spring Boot现在默认是使用CGLIB代理,同时包含AOP支持。如果你需要基于代理(proxy-based)的代理策略,你需要把spring.aop.proxy-target-class设置为false。

从Spring Boot的CLI中删除了测试支持,现在建议你使用Maven或Gradle构建应用程序,去使用它们提供的丰富的测试支持吧。

@ConfigurationProperties里的ignoreNestedProperties属性已被删除。

为了更好的反映Servlet的特性, spring.http.multipart. 属性已经被命名为 spring.servlet.multipart。

ps:其实就是因为webflux来了,只能把servlet和webflux区分开来。

过去Mustache模板的默认的文件扩展名是.html。现在.mustache成了官方指定的扩展名,而且很多的IDE插件已经支持了此后缀。你可以通过spring.mustache.suffix来覆盖现在的默认的支持。

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

Spring Boot 2.0 提供了一个新的starter ,用来支持Reactive Spring web frameworks。该starter为spring-boot-starter-webflux。其中Reactor Netty是默认的web引擎(spring-boot-starter-reactor-netty)。

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的。


Reactive controller现在可以使用@WebFluxTest来测试。它提供的功能和 @WebMvcTest类似。而且WebTestClient可以直接使用,已经被自动配置(auto-configured)了。


当你使用@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相同。


Spring Boot的Gradle插件已在很大程度上被重写,以实现一些重大的改进。有关这方面的就不细讲了,感兴趣的同学可以去一探究竟。

针对/loggers端点上POST操作的状态码已又200改为204。

Elasticsearch已升级到5.4。 与Elastic公司宣布不再支持嵌入式Elasticsearch的情况一样,NodeClient的自动配置已被删除。就是这么的节奏一致。现在你可以通过使用spring.data.elasticsearch.cluster-nodes自动配置TransportClient,具体value可以是一个或多个要连接的节点的地址。


Spring Boot 2 针对Quartz调度器提供了支持。你可以加入spring-boot-starter-quartz starter来启用。而且支持基于内存和基于jdbc两种存储。

Spring Boot公开了一个新的spring.data.web配置名称空间,可以轻松配置分页和排序。

一个全新的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-extras-java8time,开箱即用。

如果InfluxDB java client 和 the spring.influx.url 被设置, 一个InfluxDB client现在就会被自动配置。而且现在支持认证。

Spring Boot自动配置(auto-configuration)的JdbcTemplate现在可以通过spring.jdbc.template命名空间进行定制。 此外,自动配置(auto-configuration)的NamedParameterJdbcTemplate在底层就是JdbcTemplate。

Spring Boot现在可以根据DataSource自动检测出jOOQ方言(类似于JPA方言)。

此外,还引入了@JooqTest用于只有jOOQ才能hold的测试场景。

新加了一个测试的时候针对redis的新注解。

现在可以通过MongoClientSettingsBuilderCustomizer这个bean来高度定制化Spring Boot的Mongo客户端。

spring.data.cassandra 现在支持池化(pooling)。

现在支持一次性批量消费多个ConsumerRecord,你可以创建一批的监听器(listener),这样设置:

spring.kafka.listener.type=batch

Web filters 现在在所有支持的容器中都会被立刻初始化。也就是eagerly,急加载。

现在不满足条件(unconditional)的class也会被包含进来,在自动配置(auto-configuration)的Actuator端点的response中一并返回。

现在Loggers端点(endpoint) 支持reset日志级别到默认设置。

插件的配置属性现在的暴露方式有所改变,现在所有的都是以spring-boot为前缀,这是为了避免和其他插件冲突而导致错误。

比如,以下命令行可以启用profile foo:

mvn spring-boot:run -Dspring-boot.run.profiles=foo

已经从Devtools中删除了通过HTTP进行远程调试的支持。(#9489)

为了和Tomcat和Undertow看齐,现在对Jetty的所有的http method的请去都进行压缩,而不是之前那样只对GET request进行压缩(#8184)。

当配置一个reactive web server时,针对Jetty,Tomcat,Undertow的定制化器现在会被调用 (#9572)。

Jolokia不再是一个endpoint。并且默认是禁用的,这已和其他的web端点保持了一直。它的配置已转移到了management.jolokia。如果想启用 Jolokia, 向你的配置加入management.jolokia.enabled=true就可以了。

Liquibase 和 Flyway 配置的key 已被转移到了spring 的命名空间下:(比如: spring.liquibase and spring.flyway )。

@AutoConfigureOrder 默认值由Ordered.LOWEST_PRECEDENCE变为0。 (#10142)

一个新的ApplicationContextRunner 测试工具让我们测试自动配置变得容易。 未来将会把所有的测试套件都迁移到这个模型上。

基本支持了Java 9。之所以是“基本”,是因为还没得到用户的验证。

Redis客户端驱动现在由Jedis变为了Lettuce。使用Jedis的同学们,大概知道方向了吧。

但仍然支持Jedis,那么exclude掉io.lettuce:lettuce-core,然后添加 redis.clients:jedis就是了。

Spring Security OAuth 项目中的功能将会迁移到Spring Security中。将会OAuth 2.0。

Mockito 1.x不再支持@MockBean和@SpyBean。 如果你不使用spring-boot-starter-test来管理依赖关系,则应升级到Mockito 2.x。


除了Jackson 和 Gson,现在还支持了JSON-B 。JSON测试支持也已更新为新的JsonbTester类。

Spring Session 用现在可以通过/application/sessions Actuator Endpoint进行查找和删除session。

如果你希望@ConfigurationProperties对象上开启验证,那么只需要添加@Validated就可以了。

针对Spring Mobile的自动配置和依赖不再支持,已被删除。汗,我们之前的文章中还介绍过这个项目:使用Spring Boot开发一个Spring Mobile程序。

Spring Boot现在让WebFlux的错误约定和MVC保持一致就像使用MVC一样:默认视图和JSON响应错误,自定义错误视图等等。

你现在可以为你的WebFlux应用配置SSL,使用server.ssl.*配置属性。Tomcat, Jetty, Undertow 和 Reactor Netty都支持。

你现在也可以为你的MVC 或 WebFlux应用配置HTTP/2:

使用server.http2.enabled

使用了自动配置工厂的Kafka listener现在支持@SendTo

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)
    }

CommandLineRunner 现在执行批处理job的启动order是0。

Spring Boot 2.0 现在支持静态和模板化两种欢迎页类型。它会首先去配置好的静态内容的目录下查找index.html文件,如果没找到,然后就去查找index模板。 只要找到了一个就会被用作欢迎页。

在Spring Boot之前的版本中,对context path貌似并没有那么的重视一样。现在当我们使用内嵌容器的时候, context path 会被打印在HTTP 端口的旁边,像这样:

Tomcat started on port(s): 8080 (http) with context path ‘/foo’

Converter 和 GenericConverter beans现在可以被@WebMvcTest和@WebFluxTest自动扫描到了。

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。

细节注意点

在Java9中要使用JDK的编译织入切面时,我们需要引入AspectJ 1.9,但是这个版本还处于RC状态,并不是正式版本,所以当Spring Boot 2会在Aspect 1.9 GA的时候更新这个版本依赖。

如果使用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版本

  1. Apache Cassandra,具体可见:#10453
  2. JSP TLDs在嵌入式Tomcat中不生效,具体可见:#10456

参考资料

  • Running Spring Boot on Java 9

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

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

foo[0]=a
foo[2]=b

Map类型

Map类型在properties和yaml中的标准配置方式如下:

  • properties格式:
spring.my-example.foo=bar
spring.my-example.hello=world
  • yaml格式:
spring:
  my-example:
    foo: bar
    hello: world

spring:
  my-example:
    '[foo.baz]': bar

环境属性绑定

在环境变量中通过小写转换与.替换_来映射配置文件中的内容,比如:环境变量SPRING_JPA_DATABASEPLATFORM=mysql的配置会产生与在配置文件中设置spring.jpa.databaseplatform=mysql一样的效果。

由于环境变量中无法使用[]符号,所以使用_来替代。任何由下划线包围的数字都会被认为是[]的数组形式。比如:

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

系统属性的绑定也与文件属性的绑定类似,通过[]来标示,比如:

-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")

全新的绑定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类型呢?比如:

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之前。

下面我们通过代码的方式来直观的感受这个事件的切入位置,以便与将来我们在这个切入点加入自己需要的逻辑。

第一步:我们可以编写ApplicationPreparedEventApplicationStartedEvent以及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应用可以获得类似如下日志输

标签: 继电器aqw215a

锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

锐单商城 - 一站式电子元器件采购平台