我这样回答了Spring 5的新特性,面试官对我刮目相看
最近,有一个小伙伴拿到了自己满意的Offer,和他交谈的过程中得知他面试官问他关于Spring的问题比较多,其中最让面试官满意的就是自己回答关于Spring 5的知识点回答的不错。
Spring5于2017年9月发布了通用版本,它是自2013年12月以来第一个主要的Spring版本。它提供了一些人们期待已久的改进,还采用了一种全新的编程范例,以反应式原则为基础。
这个版本是很长时间以来最令人激动的版本。Spring 5兼容Java™8和JDK 9,它集成了反应式流,以方便后续提供一种颠覆性方法来实现端点和Web应用程序开发。
当然,反应式编程不仅是此版本的主题,还是令许多程序员激动不已的重大特性。人们对能够针对负载波动进行无缝扩展的容灾和响应式服务的需求在不断增加,Spring 5很好地满足了这一需求。
下面介绍Java SE 8和Java EE 7 API升级的基本内容、Spring 5的新反应式编程模型、对HTTP/2的支持,以及Spring通过Kotlin对函数式编程的全面支持。还会简要介绍测试和性能增强,最后介绍对Spring核心和容器的一般性修订。
升级到Java SE 8和Java EE 7
以前的Spring一直在支持一些弃用的Java版本,而Spring 5已从“旧包袱”中解放出来。为了充分利用Java 8的特性,它的代码库已进行了改进,而且要求将Java 8作为最低的JDK版本。
Spring 5在类路径(和模块路径)上完全兼容Java 9,而且它通过了JDK 9测试套件的测试。对Java 9爱好者而言,这是一个好消息。
在API级别上,Spring 5兼容Java EE 8技术,满足对Servlet 4.0、Bean Validation 2.0和全新的JSON Binding API的需求。对Java EE API的最低要求为V7,该版本引入了针对Servlet、JPA和Bean Validation API的次要版本。
反应式编程模型
Spring 5最令人兴奋的新特性是它的反应式编程模型。Spring 5基于一种反应式基础而构建,而且是完全异步和非阻塞的。只需少量的线程,新的事件循环执行模型就可以垂直扩展。
Spring 5采用反应式流来提供在反应式组件中传播负压的机制。负压是一个确保来自多个生产者的数据不会让使用者不堪重负的概念。
Spring WebFlux是Spring 5的反应式核心,它为开发人员提供了两种为Spring Web编程而设计的编程模型:基于注解的模型和Functional WebFramework(WebFlux.fn)。
基于注解的模型是Spring Web MVC的现代替代方案,该模型基于反应式基础而构建,而Functional Web Framework是基于@Controller注解的编程模型的替代方案。这些模型都通过同一种反应式规则来运行,后者调整非阻塞HTTP来适应反应式流API。
使用注解进行编程
Web MVC程序员应该对Spring 5的基于注解的编程模型非常熟悉,Spring 5调整了Web MVC的@Controller编程模型,采用了相同的注解。
在下面的代码中BookController类提供了两个方法,分别响应针对某个图书列表的HTTP请求,以及针对具有给定id的图书的HTTP请求。请注意Mono和Flux等对象。这些对象是实现反应式流规范中的Publisher接口的反应式类型,它们的职责是处理数据流。Mono对象处理一个仅含1个元素的流,而Flux表示一个包含N个元素的流。
@RestController
public class BookController { //反应式控制器
@GetMapping("/book")
Flux<Book> list() {
returnthis.repository.findAll();
}
@GetMapping("/book/{id}")
Mono<Book> findById(@PathVariable String id) {
returnthis.repository.findOne(id);
}
}
以上是针对Spring Web编程的注解,下面我们使用函数式Web框架来解决同一个问题。
函数式编程
Spring 5的函数式方法将请求委托给处理函数,这些函数接收一个服务器请求实例并返回一种反应式类型。来看一段代码,创建BookHandler类,其中listBooks()和getBook()方法相当于Controller中的功能。
publicclassBookHandler {
public Mono<ServerResponse> listBooks(ServerRequest request) {
return ServerResponse.ok()
.contentType(APPLICATION_JSON)
.body(repository.allPeople(), Book.class);
}
public Mono<ServerResponse> getBook(ServerRequest request) {
return repository.getBook(request.pathVariable("id"))
.then(book -> ServerResponse.ok()
.contentType(APPLICATION_JSON)
.body(fromObject(book)))
.otherwiseIfEmpty(ServerResponse.notFound().build());
}
}
通过路由函数来匹配HTTP请求参数与媒体类型,将客户端请求路由到处理函数。下面的代码展示了图书资源端点URI将调用委托给合适的处理函数:
BookHandler handler = new BookHandler();
RouterFunction<ServerResponse> personRoute =
route(
GET("/books/{id}")
.and(accept(APPLICATION_JSON)), handler::getBook)
.andRoute(
GET("/books")
.and(accept(APPLICATION_JSON)), handler::listBooks);
这些示例背后的数据存储也支持完整的反应式体验,该体验是通过Spring Data对反应式 Couchbase、Reactive MongoDB和Cassandra的支持来实现的。
使用 REST 端点执行反应式编程
新的编程模型脱离了传统的Spring Web MVC模型,引入了一些很不错的新特性。
举例来说,WebFlux模块为RestTemplate提供了一种完全非阻塞、反应式的替代方案,名为WebClient。下面创建一个WebClient,并调用books端点来请求一本给定id为1234的图书。
//通过WebClient调用REST端点
Mono<Book> book =WebClient.create("http://localhost:8080")
.get()
.url("/books/{id}", 1234)
.accept(APPLICATION_JSON)
.exchange(request)
.then(response -> response.bodyToMono(Book.class));
支持HTTP/2
HTTP/2提高了传输性能,减少了延迟,并提高了应用程序的吞吐量,从而提供了丰富的Web体验。
Spring 5提供专门的HTTP/2特性支持,还支持人们期望出现在JDK 9中的新HTTP客户端。尽管HTTP/2的服务器推送功能已通过Jetty Servlet引擎的ServerPushFilter类向Spring开发人员公开很长一段时间了,但如果发现Spring 5中开箱即用地提供了HTTP/2性能增强,Web优化者们一定会为此欢呼雀跃。
Spring 5.1提供Servlet 4.0,HTTP/2新特性将由Tomcat 9.0、Jetty9.3和Undertow 1.4原生提供。
Kotlin和Spring WebFlux
Kotlin是一种来自JetBrains的面向对象语言,支持函数式编程。它的主要优势之一是与Java有非常高的互操作性。通过引入对Kotlin的专门支持,Spring 5全面吸纳了这一优势。它的函数式编程风格与Spring WebFlux模块完美匹配,它的新路由DSL利用了函数式Web框架及干净且符合语言习惯的代码。可以像下面代码中这样简单地表达端点路由:
//Kotlin用于定义端点的路由DSL
@Bean
fun apiRouter() = router {
(accept(APPLICATION_JSON) and "/api").nest {
"/book".nest {
GET("/", bookHandler::findAll)
GET("/{id}", bookHandler::findOne)
}
"/video".nest {
GET("/", videoHandler::findAll)
GET("/{genre}", videoHandler::findByGenre)
}
}
}
使用Kotlin 1.1.4以上版本时,还添加了对Kotlin的不可变类的支持(通过带默认值的可选参数),以及对完全支持null的API的支持。
使用Lambda表达式注册Bean
作为传统XML和JavaConfig的替代方案,现在可以使用Lambda表达式注册Spring Bean,使Bean可以实际注册为提供者。下面代码中使用Lambda表达式注册了一个Book Bean:
GenericApplicationContext context = newGenericApplicationContext();
context.registerBean(Book.class, () ->new
Book(context.getBean(Author.class))
);
Spring Web MVC支持最新的 API
全新的WebFlux模块提供了许多新的、令人兴奋的功能,但Spring 5也迎合了愿意继续使用 Spring MVC的开发人员的需求。Spring 5中更新了“模型-视图-控制器”框架,以兼容WebFlux和最新版的Jackson 2.9和Protobuf 3.0,甚至包括对新的Java EE 8 JSON-Binding API的支持。
除了HTTP/2特性的基础服务器实现,Spring Web MVC还通过MVC控制器方法的一个参数来支持Servlet 4.0 的PushBuilder。最后,Web MVC全面支持Reactor 3.1的Flux和Mono对象,以及RxJava 1.3和RxJava 2.1,它们被视为来自MVC控制器方法的返回值。这项支持的最终目的是支持Spring Data中新的反应式WebClient和反应式存储库。
使用JUnit 5执行条件和并发测试
1. JUnit和Spring 5
Spring5全面接纳了函数式范例,并支持JUnit5及其新的函数式测试风格。还提供了对JUnit 4的向后兼容性,以确保不会破坏旧代码。
Spring5的测试套件通过多种方式得到了增强,但最明显的是它对JUnit 5的支持。现在可以在单元测试中利用Java 8中提供的函数式编程特性。以下代码演示了这一支持:
@Test
void givenStreamOfInts_SumShouldBeMoreThanFive() {
assertTrue(Stream.of(20, 40, 50)
.stream()
.mapToInt(i -> i)
.sum() > 110, () -> "Total should be more than 100");
}
2. 迁移到JUnit 5
如果你对升级到JUnit 5持观望态度,StevePerry的分两部分的深入剖析教程将说服你进行尝试。
Spring5继承了JUnit 5在Spring TestContext Framework内实现多个扩展API的灵活性。举例,开发人员可以使用JUnit 5的条件测试执行注解@EnabledIf和@DisabledIf来自动计算一个SpEL(Spring Expression Language)表达式,并适当地启用或禁用测试。借助这些注解,Spring 5支持以前很难实现的复杂的条件测试方案。SpringTextContext Framework现在能够并发执行测试。
3. 使用 Spring WebFlux 执行集成测试
Spring Test现在包含一个WebTestClient,后者支持对Spring WebFlux服务器端点执行集成测试。WebTestClient使用模拟请求和响应来避免耗尽服务器资源,并能直接绑定到WebFlux服务器的基础架构。
WebTestClient可绑定到真实的服务器,或者使用控制器或函数。在下面的代码中,WebTestClient被绑定到localhost:
WebTestClient testClient = WebTestClient
.bindToServer()
.baseUrl("http://localhost:8080")
.build();
下面的代码将WebTestClient绑定到RouterFunction:
RouterFunction bookRouter = RouterFunctions.route(
RequestPredicates.GET("/books"),
request -> ServerResponse.ok().build()
);
WebTestClient
.bindToRouterFunction(bookRouter)
.build().get().uri("/books")
.exchange()
.expectStatus().isOk()
.expectBody().isEmpty();
包清理和弃用
Spring5终止了对一些过时API的支持。遭此厄运的有Hibernate 3和Hibernate 4,为了支持Hibernate 5,它们遭到了弃用。另外,对Portlet、Velocity、JasperReports、XMLBeans、JDO和Guava的支持也已终止。
包级别上的清理工作仍在继续。Spring 5不再支持beans.factory.access、jdbc.support.nativejdbc、mock.staticmock(来自spring-aspects模块)或web.view.tiles2M。Tiles 3现在是Spring的最低要求。
Spring核心和容器的一般更新
Spring 5改进了扫描和识别组件的方法,使大型项目的性能得到提升。目前,扫描是在编译时执行的,而且向META-INF/spring.components文件中的索引文件添加了组件坐标。该索引是通过一个为项目定义的特定于平台的应用程序构建任务来生成的。
标有来自javax包的注解的组件会添加到索引中,任何带@Index注解的类或接口都会添加到索引中。Spring的传统类路径扫描方式没有被删除,而是保留下来作为一种后备选择。有许多针对大型代码库的明显性能优势,托管许多Spring项目的服务器也会缩短启动时间。
Spring 5还添加了对@Nullable的支持,后者可用于指示可选的注入点。使用者现在必须准备接受null值。此外,还可以使用此注解来标记可以为null的参数、字段和返回值。@Nullable主要用于IntelliJ IDEA等IDE,但也可用于Eclipse和FindBugs,它使得在编译时处理null值变得更方便,无须在运行时发送NullPointerExceptions。
Spring Logging还提升了性能,自带开箱即用的Commons Logging桥接器。现在已通过资源抽象支持防御性编程,为getFile访问提供了isFile指示器。
我如何看Spring 5
Spring 5的首要特性是新的反应式编程模型,这代表着对提供可无缝扩展、基于Spring的响应式服务的重大保障。随着人们对Spring 5的采用,反应式编程有望成为使用Java语言的Web和企业应用程序开发的未来。
未来的Spring将继续体现这一承诺,因为SpringSecurity、Spring Data和Spring Integration有望采用反应式编程的特征和优势。
总之,Spring 5代表着一次大受Spring开发人员欢迎的华丽转变,同时也为其他框架指出了一条发展之路。Spring 5的升级也为Spring Boot、Spring Cloud提供了非常丰富的经验,Spring不只是一个框架,已然成了一个编程生态。
我这样回答了Spring 5的新特性,面试官对我刮目相看的更多相关文章
- Spring Cloud Greenwich 新特性和F升级分享
2019.01.23 期待已久的Spring Cloud Greenwich 发布了release版本,作为我们团队也第一时间把RC版本替换为release,以下为总结,希望对你使用Spring Cl ...
- 【Spring注解驱动开发】面试官:如何将Service注入到Servlet中?朋友又栽了!!
写在前面 最近,一位读者出去面试前准备了很久,信心满满的去面试.没想到面试官的一个问题把他难住了.面试官的问题是这样的:如何使用Spring将Service注入到Servlet中呢?这位读者平时也是很 ...
- JDK8新特性面试
java8:http://ifeve.com/java-8-features-tutorial/ 一.Lambda表达式和函数式接口 Lambda表达式(也叫做闭包) 它允许我们将一个函数当作方法的参 ...
- Spring 3.1新特性之三:Spring对声明式缓存的支持
一.概述: Spring 3.1 引入了激动人心的基于注释(annotation)的缓存(cache)技术,它本质上不是一个具体的缓存实现方案(例如EHCache 或者 OSCache),而是一个对缓 ...
- 【Finchley】【新特性】Spring Cloud Finchley 新特性
Finchley 正式版的发布貌似经历了相当长的时间,这次的重大发布主要带来了以下 4 项重大更新. 重大更新 1.新增 Spring Cloud Gateway 组件 Spring Cloud Ga ...
- Spring 3.1新特性之二:@Enable*注解的源码,spring源码分析之定时任务Scheduled注解
分析SpringBoot的自动化配置原理的时候,可以观察下这些@Enable*注解的源码,可以发现所有的注解都有一个@Import注解.@Import注解是用来导入配置类的,这也就是说这些自动开启的实 ...
- Spring 3.1新特性之一:spring注解之@profile
前言 由于在项目中使用Maven打包部署的时候,经常由于配置参数过多(比如Nginx服务器的信息.ZooKeeper的信息.数据库连接.Redis服务器地址等),导致实际现网的配置参数与测试服务器参数 ...
- Spring 3.1新特性之四:p命名空间设置注入(待补充)
https://www.ibm.com/developerworks/cn/java/j-lo-jparelated/ http://www.ibm.com/developerworks/cn/jav ...
- Spring 3.1新特性之三:Spring支持Servlet 3.0(待补充)
高效并发是JDK 1.6的一个重要主题,HotSpot虚拟机开发团队在这个版本上花费了大量的精力去实现各种锁优化技术,如适应性自旋(Adaptive Spinning).锁削除(Lock Elimin ...
随机推荐
- Docker 自建私有Registry 私有仓库
目录 说明 介绍 原理 搭建 查看配置文件 启动 上传和下载镜像测试 测试上传镜像 测试下载镜像 说明 记录搭建 docker 私有仓库步骤 介绍 docker镜像可以托管到dockerhub中,跟代 ...
- 神奇的 SQL 之 联表细节 → MySQL JOIN 的执行过程(一)
开心一刻 我:嗨,老板娘,有冰红茶没 老板娘:有 我:多少钱一瓶 老板娘:3块 我:给我来一瓶,给,3块 老板娘:来,你的冰红茶 我:玩呐,我要冰红茶,你给我个瓶盖干哈? 老板娘:这是再来一瓶,我家卖 ...
- Python异常处理与上下文管理器
Python异常处理 异常与错误 错误 可以通过IDE或者解释器给出提示的错误opentxt('a.jpg','r') 语法层面没有问题,但是自己代码的逻辑有问题if age>18: print ...
- NoSql中的CAP原则
C:一致性 .A:可用性.P:分区容错性 Partition tolerance(分区容错性): 大多数分布式系统都分布在多个子网络.每个子网络就叫做一个区(partition).分区容错的意思是,区 ...
- php上传下载文件
之前做一个上传下载的项目,发现网上的和自己需求不是很一样,翻阅了下书籍和整理了下网上的一些代码.做了一个上传下载的demo,上传通过php本身的uploadfile函数,并返回以时间戳命名的文件名后, ...
- luogu P2515 [HAOI2010]软件安装 |Tarjan+树上背包
题目描述 现在我们的手头有N个软件,对于一个软件i,它要占用Wi的磁盘空间,它的价值为Vi.我们希望从中选择一些软件安装到一台磁盘容量为MM计算机上,使得这些软件的价值尽可能大(即Vi的和最大). 但 ...
- 2018HDU多校训练-3-Problem F. Grab The Tree
Little Q and Little T are playing a game on a tree. There are n vertices on the tree, labeled by 1,2 ...
- Ceph分布式存储-总
Ceph分布式存储-总 目录: Ceph基本组成及原理 Ceph之块存储 Ceph之文件存储 Ceph之对象存储 Ceph之实际应用 Ceph之总结 一.Ceph基本组成及原理 1.块存储.文件存储. ...
- 修改CentOS7网卡名字
需求:CentOS7网卡名字不像之前CentOS6版本的eth0,eth1这样的名字了,而是enoxxx比较长,不太容易记忆,操作也不方便!这时候就需要改网卡名字了. 1 :查看你的CentOS7 ...
- oracle 日常巡检
1. 检查数据库基本状况 包含:检查Oracle实例状态,检查Oracle服务进程,检查Oracle监听进程,共三个部分. 1.1. 检查Oracle实例状态 select instance_name ...