美文网首页
Spring 响应式编程

Spring 响应式编程

作者: IT职业与自媒体思考 | 来源:发表于2020-06-13 12:25 被阅读0次

    Peter 老师昨天粗粗谈了响应式编程,这也是个很大的topic。

    今天再次聊聊。

    响应式编程是一种面向数据流和变化传播的编程范式。使用它可以在编程语言中很方便地表达静态或动态的数据流,而相关的计算模型会自动将变化的值通过数据流进行传播。我们可以使用声明的方式构建应用程序的能力,形成更加敏感和有弹性的应用,所以Spring 5在其核心框架中增加了反应系统,已经开始向声明式编程的范式转变。

    响应式编程的优势

    提高了代码的可读性,因此开发人员只需要关注定义业务逻辑。

    在高并发环境中,可以自然的处理消息。

    可以控制生产者和消费者之间的流量,避免内存不足。

    对于一个或多个线程,IO绑定任务可以通过异步和非阻塞方式执行,而且不阻塞当前线程。

    可以有效的管理多个连接系统之间的通信。

    应用场景

    大量的交易处理服务,如银行部门。

    大型在线购物应用程序的通知服务,如亚马逊。

    股票价格同时变动的股票交易业务。

    Spring 5.0前瞻

    Spring 5.0 提供端到端的响应式编程。

    如上图所示左侧是传统的基于Servlet的Spring Web MVC框架,右侧是spring 5.0新引入的基于Reactive Streams的Spring WebFlux框架,从上往下依次是:Router Functions,WebFlux,Reactive Streams三个新组件,其中:Router Functions: 对标@Controller,@RequestMapping等标准的Spring MVC注解,提供一套函数式风格的API,用于创建Router,Handler和Filter。WebFlux: 核心组件,协调上下游各个组件提供响应式编程支持。Reactive Streams: 一种支持背压(Backpressure)的异步数据流处理标准,主流实现有RxJava和Reactor,Spring WebFlux默认集成的是Reactor。———————————————— 

    示例代码

    1.创建项目

    spring响应式开发,需要结合spring boot来完成,所以使用idea创建spring boot项目,选择Spring Initializr选项,jdk选择1.8以上。

    选择下一步,设置groupId和artifactId。

    选择下一步,选择web选项中的Reactive web选项,表明要创建响应式项目,注意Spring Boot的版本为2.0.2。

    下一步,设置项目的目录,点击finish创建项目。

    2.设置服务端口

    为了避免端口冲突,我们可以在项目的application.properties文件中配置服务端口。

    server.port=9002

    3.相关依赖包

    打开项目的pom.xml文件,会发现以下几个依赖包

    <dependencies>

       <dependency>

           <groupId>org.springframework.boot</groupId>

           <artifactId>spring-boot-starter-webflux</artifactId>

       </dependency>

    ​   <dependency>

           <groupId>org.springframework.boot</groupId>

           <artifactId>spring-boot-starter-test</artifactId>

           <scope>test</scope>

       </dependency>

       <dependency>

           <groupId>io.projectreactor</groupId>

           <artifactId>reactor-test</artifactId>

           <scope>test</scope>

       </dependency>

    </dependencies>

    其中:

    spring-boot-starter-webflux:webflux依赖包,是响应式开发的核心依赖包,其中包含了spring-boot-starter-reactor-netty 、spring 5 webflux 包,默认是通过netty启动的。

    spring-boot-starter-test:springboot的单元测试工具库。

    reactor-test:Spring 5提供的官方针对RP框架测试工具库。

    小结

    ​    spring响应式开发需要结合spring boot来完成,同时需要引入spring-boot-starter-webflux和reactor-test两个依赖包来支持响应式开发。

    4.使用webflux创建web应用

    webflux的使用有两种方式,基于注解和函数式编程。这里使用函数式编程,具体操作如下:

    4.1.创建实体类

    public class Good {

       private int id;

       private String name;

       private String price;

       public Good(int id,String name,String price){

           this.id=id;

           this.name=name;

           this.price=price;

       }

       public int getId() {

           return id;

       }

       public void setId(int id) {

           this.id = id;

       }

       public String getName() {

           return name;

       }

       public void setName(String name) {

           this.name = name;

       }

       public String getPrice() {

           return price;

       }

       public void setPrice(String price) {

           this.price = price;

       }

       @Override

       public String toString() {

           return "Good{" +

                   "id=" + id +

                   ", name='" + name + '\'' +

                   ", price='" + price + '\'' +

                   '}';

       }

    }

    分析: 实体类没有什么特殊的操作,原来怎么操作现在还是怎么操作。

    4.2.创建GoodGenerator

    @Configuration

    public class GoodGenerator {

       public Flux<Good> findGoods(){

           List<Good> goods = new ArrayList<>();

           goods.add(new Good(1,"小米","2000"));

           goods.add(new Good(2,"华为","4000"));

           goods.add(new Good(3,"苹果","8000"));

           return Flux.fromIterable(goods);

       }

    }

    分析: 这里的方法返回的是Flux类型的数据,Flux是RP中最基础的数据类型之一,对应的是多值数据的返回操作,在RP中还有Mono数据类型,也是最基础的数据类型之一,对应单值数据的返回操作。

    注意:这里的GoodGenerator类要加上@Configuration注解。

    4.3.创建GoodHandler

    @Component

    @Configuration

    public class GoodHandler {

       private final Flux<Good> goods;

       public GoodHandler(GoodGenerator goodGenerator) {

           this.goods = goodGenerator.findGoods();

       }

       public Mono<ServerResponse> hello(ServerRequest request) {

           return ok().contentType(TEXT_PLAIN)

                   .body(BodyInserters.fromObject("Hello Spring!"));

       }

       public Mono<ServerResponse> echo(ServerRequest request) {

           return ok().contentType(APPLICATION_STREAM_JSON)

                   .body(this.goods,Good.class);

       }

    }

    分析: Handler主要用来处理请求操作,并将Mono<ServerResponse>返回,Mono<ServerResponse>中会封装响应数据,响应数据如果是字符串可以使用:

    ok().contentType(TEXT_PLAIN).body(BodyInserters.fromObject("Hello Spring!"));

    操作,如果是集合数据可以使用:

    ok().contentType(APPLICATION_STREAM_JSON).body(this.goods,Good.class)

    操作。

    4.4.创建GoodRouter

    @Configuration

    public class GoodRouter {

       @Bean

       public RouterFunction<ServerResponse> route(GoodHandler goodHandler) {

         return RouterFunctions

                 .route(RequestPredicates.GET("/good")

                         .and(RequestPredicates.accept(MediaType.TEXT_PLAIN)),goodHandler::hello)

                 .andRoute(RequestPredicates.GET("/goods")

                         .and(RequestPredicates.accept(MediaType.APPLICATION_STREAM_JSON)),goodHandler::echo);

       }

    }

    分析: GoodRouter主要用来设置请求路径和转化HTTP请求,可以使用route()方法和andRoute方法设置多个请求路径和转化操作。

    小结

    ​ HTTP请求会由GoodRouter转发给对应的Handler,Handler处理请求,并返回Mono<ServerResponse>,这里的Router类似@RequestMapping,Handler类似Controller

    相关文章

      网友评论

          本文标题:Spring 响应式编程

          本文链接:https://www.haomeiwen.com/subject/bseatktx.html