springboot2学习-webflux1

 在spring boot2中引入了webflux,首先先了解下webflux的一些概念和特性,Spring Boot 2.0 WebFlux,那么什么是 Reactive Streams?。

Reactive Streams 是 JVM 中面向流的库标准和规范:

处理可能无限数量的元素
按顺序处理
组件之间异步传递
强制性非阻塞背压(Backpressure)


Backpressure(背压):背压是一种常用策略,使得发布者拥有无限制的缓冲区存储元素,用于确保发布者发布元素太快时,不会去压制订阅者。

Reactive Streams(响应式流)
一般由以下组成:
发布者:发布元素到订阅者
订阅者:消费元素
订阅:在发布者中,订阅被创建时,将与订阅者共享
处理器:发布者与订阅者之间处理数据
响应式编程


有了 Reactive Streams 这种标准和规范,利用规范可以进行响应式编程。那再了解下什么是 Reactive programming 响应式编程。响应式编程是基于异步和事件驱动的非阻塞程序,只是垂直通过在 JVM 内启动少量线程扩展,而不是水平通过集群扩展。这就是一个编程范例,具体项目中如何体现呢?


响应式项目编程实战中,通过基于 Reactive Streams 规范实现的框架 Reactor 去实战。Reactor 一般提供两种响应式 API :

Mono:实现发布者,并返回 0 或 1 个元素
Flux:实现发布者,并返回 N 个元素
Spring Webflux


Spring Boot Webflux 就是基于 Reactor 实现的。Spring Boot 2.0 包括一个新的 spring-webflux 模块。该模块包含对响应式 HTTP 和 WebSocket 客户端的支持,以及对 REST,HTML 和 WebSocket 交互等程序的支持。一般来说,Spring MVC 用于同步处理,Spring Webflux 用于异步处理。

Spring Boot Webflux 有两种编程模型实现,一种类似 Spring MVC 注解方式,另一种是使用其功能性端点方式。注解的会在下面快速入门用 Spring Webflux 功能性方式实现。


Spring Boot 2.0 WebFlux 特性

常用的 Spring Boot 2.0 WebFlux 生产的特性如下:
响应式 API
编程模型
适用性
内嵌容器
Starter 组件
还有对日志、Web、消息、测试及扩展等支持。


响应式 API:

Reactor 框架是 Spring Boot Webflux 响应库依赖,通过 Reactive Streams 并与其他响应库交互。提供了 两种响应式 API:Mono 和 Flux。一般是将 Publisher 作为输入,在框架内部转换成 Reactor 类型并处理逻辑,然后返回 Flux 或 Mono 作为输出。


适用性:

MVC 能满足场景的,就不需要更改为 WebFlux。
要注意容器的支持,可以看看下面内嵌容器的支持。
微服务体系结构,WebFlux 和 MVC 可以混合使用。尤其开发 IO 密集型服务的时候,选择 WebFlux 去实现。


编程模型:
Spring 5 web 模块包含了 Spring WebFlux 的 HTTP 抽象。类似 Servlet API , WebFlux 提供了 WebHandler API 去定义非阻塞 API 抽象接口。可以选择以下两种编程模型实现:
注解控制层。和 MVC 保持一致,WebFlux 也支持响应性 @RequestBody 注解。

功能性端点。基于 lambda 轻量级编程模型,用来路由和处理请求的小工具。和上面最大的区别就是,这种模型,全程控制了请求 - 响应的生命流程


内嵌容器:
跟 Spring Boot 大框架一样启动应用,但 WebFlux 默认是通过 Netty 启动,并且自动设置了默认端口为 8080。另外还提供了对 Jetty、Undertow 等容器的支持。开发者自行在添加对应的容器 Starter 组件依赖,即可配置并使用对应内嵌容器实例。
但是要注意,必须是 Servlet 3.1+ 容器,如 Tomcat、Jetty;或者非 Servlet 容器,如 Netty 和 Undertow。

Starter 组件:
跟 Spring Boot 大框架一样,Spring Boot Webflux 提供了很多 “开箱即用” 的 Starter 组件。Starter 组件是可被加载在应用中的 Maven 依赖项。只需要在 Maven 配置中添加对应的依赖配置,即可使用对应的 Starter 组件。例如,添加 spring-boot-starter-webflux 依赖,就可用于构建响应式 API 服务,其包含了 Web Flux 和 Tomcat 内嵌容器等。


开发中,很多功能是通过添加 Starter 组件的方式来进行实现。那么,Spring Boot 2.x 常用的 Starter 组件有哪些呢?
Spring Boot 2.0 WebFlux 组件:
Spring Boot WebFlux 官方提供了很多 Starter 组件,每个模块会有多种技术实现选型支持,来实现各种复杂的业务需求:
Web:Spring WebFlux
模板引擎:Thymeleaf
存储:Redis、MongoDB、Cassandra,不支持 MySQL
内嵌容器:Tomcat、Jetty、Undertow


以上的都是一些概念,下面开始webflux的hello world小demo:

一,创建webflux项目

适用IDEA创建一个spring boot项目,引入spring-boot-starter-webflux包,如下图:



pom.xml里面的配置如下:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>

	<groupId>com.jack</groupId>
	<artifactId>webflux1</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>jar</packaging>

	<name>webflux1</name>
	<description>Demo project for Spring Boot</description>

	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.0.1.RELEASE</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
		<java.version>1.8</java.version>
	</properties>

	<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>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>


</project>

spring-boot-starter-webflux 依赖,是我们核心需要学习 webflux 的包,里面默认包含了 spring-boot-starter-reactor-netty 、spring 5 webflux 包,也就是说默认是通过 netty 启动的。
reactor-test、spring-boot-starter-test 两个依赖搭配是用于单元测试。
spring-boot-maven-plugin 是 Spring Boot Maven 插件,可以运行、编译等调用。

创建成功以后,启动成功后的输出如下:

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v2.0.1.RELEASE)

2018-04-21 22:25:25.294  INFO 16920 --- [           main] com.jack.webflux1.Webflux1Application    : Starting Webflux1Application on wj with PID 16920 (E:\webworkspace\IdeaProjects\springcloud4\webflux1\target\classes started by Administrator in E:\webworkspace\IdeaProjects\springcloud4)
2018-04-21 22:25:25.299  INFO 16920 --- [           main] com.jack.webflux1.Webflux1Application    : No active profile set, falling back to default profiles: default
2018-04-21 22:25:25.342  INFO 16920 --- [           main] onfigReactiveWebServerApplicationContext : Refreshing org.springframework.boot.web.reactive.context.AnnotationConfigReactiveWebServerApplicationContext@1198b989: startup date [Sat Apr 21 22:25:25 GMT+08:00 2018]; root of context hierarchy
2018-04-21 22:25:26.354  INFO 16920 --- [           main] o.s.w.r.handler.SimpleUrlHandlerMapping  : Mapped URL path [/webjars/**] onto handler of type [class org.springframework.web.reactive.resource.ResourceWebHandler]
2018-04-21 22:25:26.354  INFO 16920 --- [           main] o.s.w.r.handler.SimpleUrlHandlerMapping  : Mapped URL path [/**] onto handler of type [class org.springframework.web.reactive.resource.ResourceWebHandler]
2018-04-21 22:25:26.425  INFO 16920 --- [           main] o.s.w.r.r.m.a.ControllerMethodResolver   : Looking for @ControllerAdvice: org.springframework.boot.web.reactive.context.AnnotationConfigReactiveWebServerApplicationContext@1198b989: startup date [Sat Apr 21 22:25:25 GMT+08:00 2018]; root of context hierarchy
2018-04-21 22:25:26.756  INFO 16920 --- [           main] o.s.j.e.a.AnnotationMBeanExporter        : Registering beans for JMX exposure on startup
2018-04-21 22:25:27.272  INFO 16920 --- [ctor-http-nio-1] r.ipc.netty.tcp.BlockingNettyContext     : Started HttpServer on /0:0:0:0:0:0:0:0:8080
2018-04-21 22:25:27.272  INFO 16920 --- [           main] o.s.b.web.embedded.netty.NettyWebServer  : Netty started on port(s): 8080
2018-04-21 22:25:27.275  INFO 16920 --- [           main] com.jack.webflux1.Webflux1Application    : Started Webflux1Application in 2.324 

 看输出,可以看到,默认使用netty作为容器启动,默认端口为8080


二,代码编写

1,编写处理器类handler

package com.jack.webflux1.handler;

import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import org.springframework.web.reactive.function.BodyInserters;
import org.springframework.web.reactive.function.server.ServerRequest;
import org.springframework.web.reactive.function.server.ServerResponse;
import reactor.core.publisher.Mono;

/**
 * create by jack 2018/4/21
 */
@Component
public class HelloWorldHandler {
    /**
     * ServerResponse 是对响应的封装,可以设置响应状态、响应头、响应正文。
     * 比如 ok 代表的是 200 响应码、MediaType 枚举是代表这文本内容类型、返回的是 String 的对象。
     这里用 Mono 作为返回对象,是因为返回包含了一个 ServerResponse 对象,而不是多个元素
     * @param request
     * @return
     */
    public Mono<ServerResponse> helloWorld(ServerRequest request) {
        return ServerResponse.ok().contentType(MediaType.TEXT_PLAIN)
                .body(BodyInserters.fromObject("Hello, World Flux!"));
    }
}
2,编写router

2,编写router路由器

package com.jack.webflux1.router;

import com.jack.webflux1.handler.HelloWorldHandler;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.MediaType;
import org.springframework.web.reactive.function.server.RequestPredicates;
import org.springframework.web.reactive.function.server.RouterFunction;
import org.springframework.web.reactive.function.server.RouterFunctions;
import org.springframework.web.reactive.function.server.ServerResponse;

/**
 * create by jack 2018/4/21
 * 配置路由
 */
@Configuration
public class HelloWorldRouter {

    /**
     * RouterFunctions 对请求路由处理类,即将请求路由到处理器,这里将一个 GET 请求 /helloWorld 路由到处理器
     * cityHandler 的 helloCity 方法上。跟 Spring MVC 模式下的 HandleMapping 的作用类似。
     RouterFunctions.route(RequestPredicate, HandlerFunction) 方法,
     对应的入参是请求参数和处理函数,如果请求匹配,就调用对应的处理器函数。
     * @param helloWorldHandler
     * @return
     */
    @Bean
    public RouterFunction<ServerResponse> routeHelloWorld(HelloWorldHandler helloWorldHandler) {
        return RouterFunctions
                .route(RequestPredicates.GET("/helloWorld")
                                .and(RequestPredicates.accept(MediaType.TEXT_PLAIN)),
                        helloWorldHandler::helloWorld);
    }
}


上面的代码就编写完成了,进行请求,返回Hello, World Flux!


三,测试

启动应用,使用postman进行测试,url为:http://localhost:8080/helloWorld


返回结果如下图:



源码地址:https://github.com/wj903829182/springcloud5/tree/master/webflux1

学习来源参考:http://gitbook.cn/gitchat/column/5acda6f6d7966c5ae1086f2b/topic/5acda9d9d7966c5ae1087053

欢迎加群:331227121,一起学习交流

猜你喜欢

转载自blog.csdn.net/wj903829182/article/details/80033912