当前位置: 首页 > 后端技术 > Java

一直在用SpringMVC?一起来认识一下SpringWebflux

时间:2023-04-01 17:16:39 Java

Spring-webflux简介spring-webflux是spring5.0版本之后提供的一套响应式编程风格的web开发框架。该框架包括spring-framework和springmvc,可以运行在3.1以上版本的Netty、Undertow、Serlvet容器上。您可以在项目中同时使用spring-webmvc和spring-webflux,也可以只使用其中之一来开发Web应用程序。什么是“响应式”所谓响应式,比如调用api获取数据时,不需要阻塞等待数据返回,而是有数据返回时通知。可以看出,响应式是非阻塞的,也就是说调用方法后,CPU可以做其他的事情,当收到数据响应时,CPU会回来处理。这种方法提高了系统的吞吐量。响应式编程其实就是针对这种异步非阻塞流式编程的一套标准。流式编程并不陌生,Java8提供的流式API就是这种风格。这套标准包括与运行环境(JVM、JavaScript)和网络协议相关的规范。Spring-webflux的响应式APISpring-webflux框架是基于开源项目Reactor开发的。Reactor框架与Spring紧密合作。它提供了两种API类型,分别是Mono和Flux;//Mono一般作用于单个对象Monoperson=personDao.getPerson(personId);//Flux一般作用于多个对象Fluxpeople=personDao.listAllPeople();虽然webflux框架是基于Reactor的,但它也可以与其他响应式框架一起使用,例如RxJava。选择Spring-webmvc还是Spring-webflux?这两个Web框架代表了两种不同类型的编程类型。官方给出了一张图片作为对比。根据官方的建议,以下几点可以作为参考:如果你使用过Spring-webmvc开发,并且项目运行良好,则无需更改;更何况大部分的三方库都是阻塞的,无法发挥非阻塞的优势。webflux提供了很多选项;在服务层,可以使用(Netty、Tomcat、Jetty、Undertow、3.1以上版本的Servlet容器)作为web服务;在应用层,可以选择使用@Controller来定义或者使用函数式编程来定义;在编程风格方面,您可以选择使用Reactor、RxJava或其他。如果你喜欢Java8提供的lambda表达式这种轻量级、函数式的编程风格,那么推荐使用webflux;同时对于一些轻量级的应用或者复杂度比较低的微服务,建议使用webflux更好的进行控制。在微服务架构中,webmvc和webflux项目可以混用。两个框架都可以使用@Controller注解,使项目重用更容易。评估一个项目是否应该选择webflux最简单的方法是看项目中是否会用到很多阻塞API,比如JDBC或者一些阻塞API不适合webflux项目。如果一个webmvc项目中有大量的外部系统调用,可以试试响应式的WebClient,它可以直接从Controller的方法中返回响应式的结果。响应式编程的学习路径比较陡峭,所以如果你在一个大团队,你要考虑投资成本;但是你可以使用WebClient来体验响应式编程。spring-webflux不仅可以支持3.1以上版本的Tomcat、Jetty、Servlet容器,还可以运行在非Servlet服务器上,如Netty、Undertow等。使用Springboot构建webflux应用默认使用Netty,因为Netty本身是一个非阻塞的实现。并发模型虽然webmvc和webflux都支持使用注解来定义Controller,但是它们的实现方式是完全不同的。webmvc是一个Servlet应用,实现是阻塞IO,它维护一个线程池来处理每个用户请求,也就是Servlet容器启动的时候,会创建,比如10个线程,所以系统吞吐量的瓶颈是有限的连接数和阻塞的请求处理。webflux可以基于netty等NIO网络框架,只需要几个工作线程(Eventloopworker)来处理和响应请求。由于不需要阻塞等待方法返回,CPU资源得到了更好的利用。webflux不会使程序运行得更快;它提高了并发处理请求的能力,即提高了系统吞吐量。webflux代码示例话不多说,看代码让我们看一下webflux的示例。总的来说,使用起来还是很方便的。我们用Springboot搭建一个webflux应用是非常简单的。我们只需要添加这样一个依赖即可整数编号;私人整数年龄;privateStringname;}然后定义“PersonController”。在响应式风格中不再使用@RequestMapping来声明地址映射,而是通过RouterFunctions.route().GET()方法@ConfigurationpublicclassPersonRouter{@ResourceprivatePersonH??andlerpersonH??andler;@BeanpublicRouterFunctionpersonRoutes(){returnRouterFunctions.route().GET("/person/{id}",RequestPredicates.accept(MediaType.APPLICATION_JSON),personH??andler::getPerson).GET("/person",RequestPredicates.accept(MediaType.APPLICATION_JSON),personH??andler::listPeople).POST("/person",personH??andler::createPerson).build();}}在PersonH??andl中er中处理对应的HTTP请求,等同于MVC架构中的Service层@ComponentpublicclassPersonH??andler{@ResourceprivatePersonRepositorypersonDao;publicMonolistPeople(ServerRequestrequest){Fluxpeople=personDao.listAllPeople();返回ServerResponse.ok().contentType(MediaType.APPLICATION_JSON).body(people,Person.class);}publicMonocreatePerson(ServerRequestrequest){Monoperson=request.bodyToMono(Person.class);返回ServerResponse.ok().build(personDao.savePerson(person));}publicMonogetPerson(ServerRequestrequest){intpersonId=Integer.parseInt(request.pathVariable("id"));返回personDao.getPerson(personId).flatMap(person->ServerResponse.ok().contentType(MediaType.APPLICATION_JSON).bodyValue(person))。switchIfEmpty(ServerResponse.notFound().build());}}通过启动日志可以确认Spring-webflux默认使用Netty提供HTTP服务。项目启动后,浏览器访问http://localhost:8080/person/1可以发现,你的Spring-webflux项目已经可以运行了