温故 Spring5 特性

2023-10-07 19:28

本文主要是介绍温故 Spring5 特性,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

图片

一、前言

随着技术的不断发展,Spring框架也在不断地更新迭代。我们将温故Spring 5的特性,并探讨如何在实际项目中应用这些特性来提升开发效率和系统性能。

Spring 5是Spring框架的一个重要版本,它带来了许多新特性,包括对Java 8的支持、WebFlux的引入、响应式流等等。本文将详细介绍Spring 5的新特性,并通过代码说明如何使用这些新特性。

二、特性

2.1 升级到 Java SE 8 和 Java EE 7

直到现在,Spring Framework 仍支持一些弃用的 Java 版本,但 Spring 5已从旧包袱中解放出来。为了充分利用 Java 8 特性,它的代码库已进行了改进,而且该框架要求将 Java8 作为最低的 JDK 版本。

Spring 5 在类路径(和模块路径)上完全兼容 Java 9,而且它通过了 JDK 9 测试套件的测试。对Java 9 爱好者而言,这是一条好消息,因为在 Java 9 发布后,Spring 能立即使用它。

在 API 级别上,Spring 5 兼容 Java EE 8 技术,满足对 Servlet 4.0、BeanValidation 2.0 和全新的 JSON Binding API 的需求。对 Java EEAPI 的最低要求为 V7,该版本引入了针对 Servlet、JPA 和 Bean ValidationAPI 的次要版本。

2.2 反应式编程模型

Spring 5 最令人兴奋的新特性是它的反应式编程模型。Spring 5 Framework 基于一种反应式基础而构建,而且是完全异步和非阻塞的。只需少量的线程,新的事件循环执行模型就可以垂直扩展。

该框架采用反应式流来提供在反应式组件中传播负压的机制。负压是一个确保来自多个生产者的数据不会让使用者不堪重负的概念。

Spring WebFlux 是 Spring 5 的反应式核心,它为开发人员提供了两种为 SpringWeb 编程而设计的编程模型:一种基于注解的模型和 Functional Web Framework(WebFlux.fn)。

基于注解的模型是 Spring WebMVC 的现代替代方案,该模型基于反应式基础而构建,而 FunctionalWeb Framework 是基于 @Controller 注解的编程模型的替代方案。这些模型都通过同一种反应式基础来运行,后者调整非阻塞 HTTP 来适应反应式流 API。

2.3 使用注解进行编程

WebMVC 程序员应该对 Spring 5 的基于注解的编程模型非常熟悉。Spring 5 调整了WebMVC 的@Controller 编程模型,采用了相同的注解。

在栗子 1 中,BookController 类提供了两个方法,分别响应针对某个图书列表的 HTTP请求,以及针对具有给定 id 的图书的 HTTP 请求。请注意 resource 方法返回的对象(Mono和 Flux)。这些对象是实现反应式流规范中的 Publisher 接口的反应式类型。它们的职责是处理数据流。Mono对象处理一个仅含 1 个元素的流,而 Flux 表示一个包含 N 个元素的流。

栗子1. 反应式控制器


@RestControllerpublic class BookController {@GetMapping("/book")Flux<Book> list() {return this.repository.findAll();}@GetMapping("/book/{id}")Mono<Book> findById(@PathVariable String id) {return this.repository.findOne(id);}// Plumbing code omitted for brevity
}

这是针对 Spring Web 编程的注解。现在我们使用函数式 Web 框架来解决同一个问题。

2.4 函数式编程

Spring 5 的新函数式方法将请求委托给处理函数,这些函数接受一个服务器请求实例并返回一种反应式类型。栗子2 演示了这一过程,其中 listBook 和 getBook 方法类似于栗子 1 中的功能。

栗子2. BookHandler 函数类


public class BookHandler {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());}// Plumbing code omitted for brevity
}

通过路由函数来匹配 HTTP 请求谓词与媒体类型,将客户端请求路由到处理函数。栗子 3 展示了图书资源端点 URI 将调用委托给合适的处理函数:

栗子3. Router 函数


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、ReactiveMongoDB 和 Cassandra 的支持来实现的。

2.5 使用 REST 端点执行反应式编程

新的编程模型脱离了传统的 Spring WebMVC 模型,引入了一些很不错的新特性。

举例来说,WebFlux 模块为 RestTemplate 提供了一种完全非阻塞、反应式的替代方案,名为WebClient。栗子4 创建了一个 WebClient,并调用 books 端点来请求一本给定 id 为 1234 的图书。

栗子4. 通过 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));

2.6 HTTP/2 支持

HTTP/2 幕后原理:要了解 HTTP/2 如何提高传输性能,减少延迟,并帮助提高应用程序吞吐量,从而提供经过改进的丰富Web 体验,请查阅我的有关这项期待已久的升级的文章。

Spring Framework 5.0 将提供专门的 HTTP/2 特性支持,还支持人们期望出现在JDK 9 中的新 HTTP 客户端。尽管 HTTP/2 的服务器推送功能已通过 Jetty servlet引擎的 ServerPushFilter 类向 Spring 开发人员公开了很长一段时间,但如果发现Spring 5 中开箱即用地提供了 HTTP/2性能增强,Web 优化者们一定会为此欢呼雀跃。

Java EE Servlet 规范预计将于 2017 年第 4 季度发布,Servlet 4.0支持将在 Spring 5.1 中提供。到那时,HTTP/2 特性将由 Tomcat 9.0、Jetty 9.3 和 Undertow 1.4 原生提供。

2.7 Kotlin 和 Spring WebFlux

Kotlin 是一种来自 JetBrains 的面向对象的语言,它支持函数式编程。它的主要优势之一是与Java 有非常高的互操作性。通过引入对 Kotlin 的专门支持,Spring 在 V5 中全面吸纳了这一优势。它的函数式编程风格与Spring WebFlux 模块完美匹配,它的新路由 DSL 利用了函数式 Web 框架以及干净且符合语言习惯的代码。可以像栗子5 中这样简单地表达端点路由:

栗子5. Kotlin 的用于定义端点的路由 DSL


@Beanfun 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 的支持。

2.8 使用 Lambda 表达式注册 bean

作为传统 XML 和 JavaConfig 的替代方案,现在可以使用 lambda 表达式注册 Springbean,使 bean 可以实际注册为提供者。栗子 6 使用 lambda 表达式注册了一个 Bookbean。

栗子6. 将 Bean 注册为提供者


GenericApplicationContext context = new GenericApplicationContext();context.registerBean(Book.class, () -> newBook(context.getBean(Author.class)));

2.9 Spring WebMVC 支持最新的 API

全新的 WebFlux 模块提供了许多新的、令人兴奋的功能,但 Spring 5 也迎合了愿意继续使用Spring MVC 的开发人员的需求。Spring 5 中更新了模型-视图-控制器框架,以兼容 WebFlux和最新版的Jackson 2.9 和 Protobuf 3.0,甚至包括对新的 Java EE 8JSON-Binding API 的支持。

除了 HTTP/2 特性的基础服务器实现之外,Spring WebMVC 还通过 MVC 控制器方法的一个参数来支持Servlet 4.0 的 PushBuilder。最后,WebMVC 全面支持 Reactor 3.1的 Flux 和 Mono 对象,以及 RxJava1.3 和 2.1,它们被视为来自 MVC 控制器方法的返回值。这项支持的最终目的是支持Spring Data 中的新的反应式 WebClient 和反应式存储库。

2.10 使用 JUnit 5 执行条件和并发测试

JUnit 和 Spring 5:Spring 5 全面接纳了函数式范例,并支持 JUnit 5 及其新的函数式测试风格。还提供了对JUnit 4 的向后兼容性,以确保不会破坏旧代码。

Spring 5 的测试套件通过多种方式得到了增强,但最明显的是它对JUnit 5 的支持。现在可以在您的单元测试中利用Java 8 中提供的函数式编程特性。栗子 7 演示了这一支持:

栗子7. JUnit 5 全面接纳了 Java 8 流和 lambda 表达式


@Testvoid givenStreamOfInts_SumShouldBeMoreThanFive() {assertTrue(Stream.of(20, 40, 50).stream().mapToInt(i -> i).sum() > 110, () -> "Total should be more than 100");
}

迁移到 JUnit 5:如果您对升级到 JUnit 5 持观望态度,Steve Perry 的分两部分的深入剖析教程将说服您冒险尝试。

Spring 5 继承了 JUnit 5 在 Spring TestContext Framework内实现多个扩展 API 的灵活性。举例而言,开发人员可以使用 JUnit 5 的条件测试执行注解 @EnabledIf和 @DisabledIf 来自动计算一个 SpEL (Spring Expression Language)表达式,并适当地启用或禁用测试。借助这些注解,Spring 5 支持以前很难实现的复杂的条件测试方案。SpringTextContext Framework 现在能够并发执行测试。

2.11 使用 Spring WebFlux 执行集成测试

Spring Test 现在包含一个 WebTestClient,后者支持对 Spring WebFlux服务器端点执行集成测试。WebTestClient 使用模拟请求和响应来避免耗尽服务器资源,并能直接绑定到WebFlux 服务器基础架构。

WebTestClient 可绑定到真实的服务器,或者使用控制器或函数。在栗子 8 中,WebTestClient被绑定到 localhost:

栗子8. 绑定到 localhost 的 WebTestClient


WebTestClient testClient = WebTestClient .bindToServer().baseUrl("http://localhost:8080").build();

栗子9. 将 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();

2.12 包清理和弃用

Spring 5 中止了对一些过时 API 的支持。遭此厄运的还有 Hibernate 3 和 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的最低要求。

2.13 对 Spring 核心和容器的一般更新

Spring Framework 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的几个新特性,包括支持Java 8的Optional类、支持Java 9的模块化系统和支持WebFlux响应式编程模型。这些新特性可以帮助我们更加方便地编写代码和管理依赖关系,提高开发效率和系统性能。在未来的开发中,我们应该积极地学习和掌握这些新特性,以便更好地应对日益复杂的开发需求。同时,我们也应该注意到Spring框架在不断地更新和完善,我们应该保持关注并及时了解最新的动态,以便更好地利用这一优秀的开发工具。

图片

这篇关于温故 Spring5 特性的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/159922

相关文章

Java中对象的创建和销毁过程详析

《Java中对象的创建和销毁过程详析》:本文主要介绍Java中对象的创建和销毁过程,对象的创建过程包括类加载检查、内存分配、初始化零值内存、设置对象头和执行init方法,对象的销毁过程由垃圾回收机... 目录前言对象的创建过程1. 类加载检查2China编程. 分配内存3. 初始化零值4. 设置对象头5. 执行

SpringBoot整合easy-es的详细过程

《SpringBoot整合easy-es的详细过程》本文介绍了EasyES,一个基于Elasticsearch的ORM框架,旨在简化开发流程并提高效率,EasyES支持SpringBoot框架,并提供... 目录一、easy-es简介二、实现基于Spring Boot框架的应用程序代码1.添加相关依赖2.添

通俗易懂的Java常见限流算法具体实现

《通俗易懂的Java常见限流算法具体实现》:本文主要介绍Java常见限流算法具体实现的相关资料,包括漏桶算法、令牌桶算法、Nginx限流和Redis+Lua限流的实现原理和具体步骤,并比较了它们的... 目录一、漏桶算法1.漏桶算法的思想和原理2.具体实现二、令牌桶算法1.令牌桶算法流程:2.具体实现2.1

SpringBoot中整合RabbitMQ(测试+部署上线最新完整)的过程

《SpringBoot中整合RabbitMQ(测试+部署上线最新完整)的过程》本文详细介绍了如何在虚拟机和宝塔面板中安装RabbitMQ,并使用Java代码实现消息的发送和接收,通过异步通讯,可以优化... 目录一、RabbitMQ安装二、启动RabbitMQ三、javascript编写Java代码1、引入

spring-boot-starter-thymeleaf加载外部html文件方式

《spring-boot-starter-thymeleaf加载外部html文件方式》本文介绍了在SpringMVC中使用Thymeleaf模板引擎加载外部HTML文件的方法,以及在SpringBoo... 目录1.Thymeleaf介绍2.springboot使用thymeleaf2.1.引入spring

Java实现检查多个时间段是否有重合

《Java实现检查多个时间段是否有重合》这篇文章主要为大家详细介绍了如何使用Java实现检查多个时间段是否有重合,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录流程概述步骤详解China编程步骤1:定义时间段类步骤2:添加时间段步骤3:检查时间段是否有重合步骤4:输出结果示例代码结语作

Java中String字符串使用避坑指南

《Java中String字符串使用避坑指南》Java中的String字符串是我们日常编程中用得最多的类之一,看似简单的String使用,却隐藏着不少“坑”,如果不注意,可能会导致性能问题、意外的错误容... 目录8个避坑点如下:1. 字符串的不可变性:每次修改都创建新对象2. 使用 == 比较字符串,陷阱满

Java判断多个时间段是否重合的方法小结

《Java判断多个时间段是否重合的方法小结》这篇文章主要为大家详细介绍了Java中判断多个时间段是否重合的方法,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录判断多个时间段是否有间隔判断时间段集合是否与某时间段重合判断多个时间段是否有间隔实体类内容public class D

IDEA编译报错“java: 常量字符串过长”的原因及解决方法

《IDEA编译报错“java:常量字符串过长”的原因及解决方法》今天在开发过程中,由于尝试将一个文件的Base64字符串设置为常量,结果导致IDEA编译的时候出现了如下报错java:常量字符串过长,... 目录一、问题描述二、问题原因2.1 理论角度2.2 源码角度三、解决方案解决方案①:StringBui

Java覆盖第三方jar包中的某一个类的实现方法

《Java覆盖第三方jar包中的某一个类的实现方法》在我们日常的开发中,经常需要使用第三方的jar包,有时候我们会发现第三方的jar包中的某一个类有问题,或者我们需要定制化修改其中的逻辑,那么应该如何... 目录一、需求描述二、示例描述三、操作步骤四、验证结果五、实现原理一、需求描述需求描述如下:需要在