spring5新特性全面介绍
前方:对于很多开发人员来说,目前大都还在使用spring4的时候,而spring5早已经发布。虽然你可能暂时还没有使用到spring5,但还是需要对其有个大概的了解。
Spring5于2017年9月发布了通用版本(GA),它标志着自2013年12月以来第一个主要SpringFramework版本。它提供了一些人们期待已久的改进,还采用了一种全新的编程范例,以反应式宣言中陈述的反应式原则为基础。
这个版本是很长时间以来最令人兴奋的SpringFramework版本。Spring5兼容Java?8和JDK9,它集成了反应式流,以便提供一种颠覆性方法来实现端点和Web应用程序开发。
诚然,反应式编程不仅是此版本的主题,还是令许多开发人员激动不已的重大特性。人们对能够针对负载波动进行无缝扩展的灾备和响应式服务的需求在不断增加,Spring5很好地满足了这一需求。
我还会简要介绍测试和性能增强,最后介绍对Spring核心和容器的一般性修订。
升级到JavaSE8和JavaEE7
直到现在,SpringFramework仍支持一些弃用的Java版本,但Spring5已从旧包袱中解放出来。为了充分利用Java8特性,它的代码库已进行了改进,而且该框架要求将Java8作为最低的JDK版本。
Spring5在类路径(和模块路径)上完全兼容Java9,而且它通过了JDK9测试套件的测试。对Java9爱好者而言,这是一条好消息,因为在Java9发布后,Spring能立即使用它。
在API级别上,Spring5兼容JavaEE8技术,满足对Servlet4.0、BeanValidation2.0和全新的JSONBindingAPI的需求。对JavaEEAPI的最低要求为V7,该版本引入了针对Servlet、JPA和BeanValidationAPI的次要版本。
反应式编程模型
Spring5最令人兴奋的新特性是它的反应式编程模型。Spring5Framework基于一种反应式基础而构建,而且是完全异步和非阻塞的。只需少量的线程,新的事件循环执行模型就可以垂直扩展。
该框架采用反应式流来提供在反应式组件中传播负压的机制。负压是一个确保来自多个生产者的数据不会让使用者不堪重负的概念。
SpringWebFlux是Spring5的反应式核心,它为开发人员提供了两种为SpringWeb编程而设计的编程模型:一种基于注解的模型和FunctionalWebFramework(WebFlux.fn)。
基于注解的模型是SpringWebMVC的现代替代方案,该模型基于反应式基础而构建,而FunctionalWebFramework是基于@Controller注解的编程模型的替代方案。这些模型都通过同一种反应式基础来运行,后者调整非阻塞HTTP来适应反应式流API。
使用注解进行编程
WebMVC程序员应该对Spring5的基于注解的编程模型非常熟悉。Spring5调整了WebMVC的@Controller编程模型,采用了相同的注解。
在清单1中,BookController类提供了两个方法,分别响应针对某个图书列表的HTTP请求,以及针对具有给定id的图书的HTTP请求。请注意resource方法返回的对象(Mono和Flux)。这些对象是实现反应式流规范中的Publisher接口的反应式类型。它们的职责是处理数据流。Mono对象处理一个仅含1个元素的流,而Flux表示一个包含N个元素的流。
清单1.反应式控制器
@RestController publicclassBookController{ @GetMapping("/book") Fluxlist(){ returnthis.repository.findAll(); } @GetMapping("/book/{id}") Mono findById(@PathVariableStringid){ returnthis.repository.findOne(id); } //Plumbingcodeomittedforbrevity }
这是针对SpringWeb编程的注解。现在我们使用函数式Web框架来解决同一个问题。
函数式编程
Spring5的新函数式方法将请求委托给处理函数,这些函数接受一个服务器请求实例并返回一种反应式类型。清单2演示了这一过程,其中listBook和getBook方法类似于清单1中的功能。
清单2.清单2.BookHandler函数类
publicclassBookHandler{ publicMonolistBooks(ServerRequestrequest){ returnServerResponse.ok() .contentType(APPLICATION_JSON) .body(repository.allPeople(),Book.class); } publicMono getBook(ServerRequestrequest){ returnrepository.getBook(request.pathVariable("id")) .then(book->ServerResponse.ok() .contentType(APPLICATION_JSON) .body(fromObject(book))) .otherwiseIfEmpty(ServerResponse.notFound().build()); } //Plumbingcodeomittedforbrevity }
通过路由函数来匹配HTTP请求谓词与媒体类型,将客户端请求路由到处理函数。清单3展示了图书资源端点URI将调用委托给合适的处理函数:
清单3.Router函数
BookHandlerhandler=newBookHandler(); RouterFunctionpersonRoute= route( GET("/books/{id}") .and(accept(APPLICATION_JSON)),handler::getBook) .andRoute( GET("/books") .and(accept(APPLICATION_JSON)),handler::listBooks);
这些示例背后的数据存储库也支持完整的反应式体验,该体验是通过SpringData对反应式Couchbase、ReactiveMongoDB和Cassandra的支持来实现的。
使用REST端点执行反应式编程
新的编程模型脱离了传统的SpringWebMVC模型,引入了一些很不错的新特性。
举例来说,WebFlux模块为RestTemplate提供了一种完全非阻塞、反应式的替代方案,名为WebClient。清单4创建了一个WebClient,并调用books端点来请求一本给定id为1234的图书。
清单4.通过WebClient调用REST端点
Monobook=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幕后原理:要了解HTTP/2如何提高传输性能,减少延迟,并帮助提高应用程序吞吐量,从而提供经过改进的丰富Web体验,请查阅我的有关这项期待已久的升级的文章。
SpringFramework5.0将提供专门的HTTP/2特性支持,还支持人们期望出现在JDK9中的新HTTP客户端。尽管HTTP/2的服务器推送功能已通过Jettyservlet引擎的ServerPushFilter类向Spring开发人员公开了很长一段时间,但如果发现Spring5中开箱即用地提供了HTTP/2性能增强,Web优化者们一定会为此欢呼雀跃。
JavaEEServlet规范预计将于2017年第4季度发布,Servlet4.0支持将在Spring5.1中提供。到那时,HTTP/2特性将由Tomcat9.0、Jetty9.3和Undertow1.4原生提供。
Kotlin和SpringWebFlux
Kotlin是一种来自JetBrains的面向对象的语言,它支持函数式编程。它的主要优势之一是与Java有非常高的互操作性。通过引入对Kotlin的专门支持,Spring在V5中全面吸纳了这一优势。它的函数式编程风格与SpringWebFlux模块完美匹配,它的新路由DSL利用了函数式Web框架以及干净且符合语言习惯的代码。可以像清单5中这样简单地表达端点路由:
清单5.Kotlin的用于定义端点的路由DSL
@Bean funapiRouter()=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) } } }
使用Kotlin1.1.4+时,还添加了对Kotlin的不可变类的支持(通过带默认值的可选参数),以及对完全支持null的API的支持。
使用Lambda表达式注册bean
作为传统XML和JavaConfig的替代方案,现在可以使用lambda表达式注册Springbean,使bean可以实际注册为提供者。清单6使用lambda表达式注册了一个Bookbean。
清单6.将Bean注册为提供者
GenericApplicationContextcontext=newGenericApplicationContext(); context.registerBean(Book.class,()->new Book(context.getBean(Author.class)) );
SpringWebMVC支持最新的API
全新的WebFlux模块提供了许多新的、令人兴奋的功能,但Spring5也迎合了愿意继续使用SpringMVC的开发人员的需求。Spring5中更新了模型-视图-控制器框架,以兼容WebFlux和最新版的Jackson2.9和Protobuf3.0,甚至包括对新的JavaEE8JSON-BindingAPI的支持。
除了HTTP/2特性的基础服务器实现之外,SpringWebMVC还通过MVC控制器方法的一个参数来支持Servlet4.0的PushBuilder。最后,WebMVC全面支持Reactor3.1的Flux和Mono对象,以及RxJava1.3和2.1,它们被视为来自MVC控制器方法的返回值。这项支持的最终目的是支持SpringData中的新的反应式WebClient和反应式存储库。
使用JUnit5执行条件和并发测试
JUnit和Spring5:Spring5全面接纳了函数式范例,并支持JUnit5及其新的函数式测试风格。还提供了对JUnit4的向后兼容性,以确保不会破坏旧代码。
Spring5的测试套件通过多种方式得到了增强,但最明显的是它对JUnit5的支持。现在可以在您的单元测试中利用Java8中提供的函数式编程特性。清单7演示了这一支持:
清单7.清单7.JUnit5全面接纳了Java8流和lambda表达式
@Test voidgivenStreamOfInts_SumShouldBeMoreThanFive(){ assertTrue(Stream.of(20,40,50) .stream() .mapToInt(i->i) .sum()>110,()->"Totalshouldbemorethan100"); }
迁移到JUnit5:如果您对升级到JUnit5持观望态度,StevePerry的分两部分的深入剖析教程将说服您冒险尝试。
Spring5继承了JUnit5在SpringTestContextFramework内实现多个扩展API的灵活性。举例而言,开发人员可以使用JUnit5的条件测试执行注解@EnabledIf和@DisabledIf来自动计算一个SpEL(SpringExpressionLanguage)表达式,并适当地启用或禁用测试。借助这些注解,Spring5支持以前很难实现的复杂的条件测试方案。SpringTextContextFramework现在能够并发执行测试。
使用SpringWebFlux执行集成测试
SpringTest现在包含一个WebTestClient,后者支持对SpringWebFlux服务器端点执行集成测试。WebTestClient使用模拟请求和响应来避免耗尽服务器资源,并能直接绑定到WebFlux服务器基础架构。
WebTestClient可绑定到真实的服务器,或者使用控制器或函数。在清单8中,WebTestClient被绑定到localhost:
清单8.绑定到localhost的WebTestClient
WebTestClienttestClient=WebTestClient .bindToServer() .baseUrl("http://localhost:8080") .build();
在清单9中,测试了RouterFunction:
清单9.将WebTestClient绑定到RouterFunction
RouterFunctionbookRouter=RouterFunctions.route(RequestPredicates.GET("/books"), request->ServerResponse.ok().build() ); WebTestClient .bindToRouterFunction(bookRouter) .build().get().uri("/books") .exchange() .expectStatus().isOk() .expectBody().isEmpty();
包清理和弃用
Spring5中止了对一些过时API的支持。遭此厄运的还有Hibernate3和4,为了支持Hibernate5,它们遭到了弃用。另外,对Portlet、Velocity、JasperReports、XMLBeans、JDO和Guava的支持也已中止。
包级别上的清理工作仍在继续:Spring5不再支持beans.factory.access、jdbc.support.nativejdbc、mock.staticmock(来自spring-aspects模块)或web.view.tiles2M。Tiles3现在是Spring的最低要求。
对Spring核心和容器的一般更新
SpringFramework5改进了扫描和识别组件的方法,使大型项目的性能得到提升。目前,扫描是在编译时执行的,而且向META-INF/spring.components文件中的索引文件添加了组件坐标。该索引是通过一个为项目定义的特定于平台的应用程序构建任务来生成的。
标有来自javax包的注解的组件会添加到索引中,任何带@Index注解的类或接口都会添加到索引中。Spring的传统类路径扫描方式没有删除,而是保留为一种后备选择。有许多针对大型代码库的明显性能优势,而托管许多Spring项目的服务器也会缩短启动时间。
Spring5还添加了对@Nullable的支持,后者可用于指示可选的注入点。使用者现在必须准备接受null值。此外,还可以使用此注解来标记可以为null的参数、字段和返回值。@Nullable主要用于IntelliJIDEA等IDE,但也可用于Eclipse和FindBugs,它使得在编译时处理null值变得更方便,而无需在运行时发送NullPointerExceptions。
SpringLogging还提升了性能,自带开箱即用的CommonsLogging桥接器。现在已通过资源抽象支持防御性编程,为getFile访问提供了isFile指示器。
结束语
Spring5的首要特性是新的反应式编程模型,这代表着对提供可无缝扩展、基于Spring的响应式服务的重大保障。随着人们对Spring5的采用,开发人员有望看到反应式编程将会成为使用Java语言的Web和企业应用程序开发的未来发展道路。
未来的SpringFramework版本将继续反映这一承诺,因为SpringSecurity、SpringData和SpringIntegration有望采用反应式编程的特征和优势。
总之,Spring5代表着一次大受Spring开发人员欢迎的范例转变,同时也为其他框架指出了一条发展之路。
以上就是spring5新特性全面介绍的详细内容,更多关于spring5新特性的资料请关注毛票票其它相关文章!