笔者在之前已经写了一系列的关于RestTemplate的文章,如下:

RestTemplate作为spring-web项目的一部分,在Spring 3.0版本开始被引入。根据Spring官方文档及源码中的介绍,RestTemplate在将来的版本中它可能会被弃用, 作为替代,Spring官方已在Spring 5中引入了WebClient作为非阻塞式Reactive HTTP客户端。

一、什么是响应式非阻塞IO

在开始为大家介绍webClient之前有必要为大家介绍一下响应式非阻塞IO与传统IO之前的区别。我们先留下一个问题:webClient发送与接收单个HTTP请求比RestTemplate更快么?答案是否定的。 看到这里有的同学已经蒙了,既然webClient没有更快,那官方为什么还推荐使用它?听我往下讲。

1.1.传统阻塞式IO模型

笔者用相对通俗的话为大家说明一下阻塞IO与非阻塞IO之间的区别。我们以软件开发团队的工作方式来做一个比喻。作为软件开发人员,我们肯定知道软件开发的基本流程:

  • 项目立项与可行性研究
  • 需求分析与设计
  • 代码开发
  • 迭代测试
  • 上线及配置管理、运维

在以Spring MVC或者struct为代表的框架都是基于sevlet的,其底层IO模型是阻塞IO模型。这种模型就好像你是公司的一个开发人员,上面的所有的5项工作全都由你一个人完成。如果公司有10个人,最多就只能同时进行10个需求。客户需求增多了也没有办法,只能让他们等着。如下图:一个请求占用一个线程,当线程池内的线程都被占用后新来的请求就只能等待。

1.2.响应式IO模型

spring 社区为了解决Spring MVC的阻塞模型在高并发场景下的性能瓶颈的问题,推出了Spring WebFlux,WebFlux底层实现是久经考验的netty非阻塞IO通信框架。该框架的请求处理与线程交互关系图如下:



boosGroup用于Accetpt连接建立事件并分发请求, workerGroup用于处理I/O读写事件。netty我就不细说了,还是用通俗的方式给大家讲一下:如果通俗的将上图中的各个任务池、线程池的组合比做一个软件开发公司,那么:

  • 项目立项及可研,由公司项目经理及顾问来完成
  • 需求分析与设计,由产品经理和架构师来完成
  • 代码研发,由项目经理带领开发人员来完成
  • 迭代测试,由测试团队来完成
  • 上线及配置管理、运维,可能由专门的devops团队来完成

这样一个公司内的所有人完成分工,就能在有限的资源的情况下,去接触更多的客户,谈更多的需求,合理的分配人力资源,达到并发处理能力最大化的极限水平。相比于一个员工从头到位的负责一个项目,它的组织性更强,分工更明确,合理的利用空闲资源,专业的人最专业的事。

这种人力资源的合理利用及组织方式和非阻塞IO模型有异曲同工之处,通过合理的将请求处理线程及任务进行分类,合理的利用系统的内存、CPU资源,达到单位时间内处理能力的最大化就是异步非阻塞IO的核心用意! 回到上文给大家留下的问题,webClient处理单个HTTP请求的响应时长并不比RestTemplate更快,但是它处理并发的能力更强。所以响应式非阻塞IO模型的核心意义在于:提高了单位时间内有限资源下的服务请求的并发处理能力,而不是缩短了单个服务请求的响应时长。

二、WebClient 的优势

上文为大家介绍完IO模型之后,我想大家已经可以明白了。与RestTemplate相比,WebClient优势如下:

  • 非阻塞响应式IO,单位时间内有限资源下支持更高的并发量
  • 支持使用Java 8 lambda表达式函数
  • 同时支持同步、异步与Streaming流式传输场景

三、项目引入WebClient

使用WebClient需要引入如下的Jar(可以在包含spring-boot-starter-web的Spring Boot项目中引入)

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>

那么问题又来了,熟悉Spring 开发的朋友应该都知道。spring-boot-starter-webflux和spring-boot-starter-web代表的是两套技术栈

  • spring-boot-starter-web可以实现目前比较成熟的基于servlet技术栈的Spring Boot应用
  • spring-boot-starter-webflux可以实现的是底层基于netty的响应式编程的技术栈的Spring Boot应用

二者可以共存么?答案是:

  • 作为服务端实现Spring Boot应用而言,二者在应用角度当然是不能共存的。截止20200820我写稿的时间,如果在一个项目里面将二者都引入了,开发服务端应用其实使用的还是spring-boot-starter-web的基于servlet的技术栈。
  • 作为HTTP客户端而言,如果我们只是要使用WebClient。无论怎样,引入spring-boot-starter-webflux就对了。

四、WebClient 实例创建与基础用法

创建WebClient有如下三种方式,我们来一一为大家介绍。

  • WebClient.create()
  • WebClient.create(String baseUrl):指定了baseUrl,使用该客户端发送请求都基于baseUrl
  • WebClient.builder()返回一个WebClient.Builder,该对象可以做链式调用,传递更多的参数。

为了方便后续开发测试,首先介绍一个网站给大家。JSONPlaceholder是一个提供免费的在线REST API的网站,我们在开发时可以使用它提供的url地址测试下网络请求以及请求参数。或者当我们程序需要获取一些模拟数据、模拟图片时也可以使用它。

4.1. WebClient.create()

创建WebClient发送GET请求,接收String类型单个Mono对象(Mono英文:单声道、单体)。

public class SimpleTest {

  @Test
void testSimple() {
WebClient webClient = WebClient.create(); Mono<String> mono = webClient
.get() // 发送GET 请求
.uri("http://jsonplaceholder.typicode.com/posts/1") // 请求路径
.retrieve() // 获取响应结果
.bodyToMono(String.class); //响应数据类型转换 System.out.println("=====" + mono.block());
}
}

mono.block()方法仍然是阻塞式的数据响应接收方式,响应式的编程方法我们后面文章会为大家介绍。

4.2.WebClient.create(String baseUrl)

上面使用create()无参方法,在指定请求uri时每次都要指定完整的HTTP服务路径,如"http://jsonplaceholder.typicode.com/posts/1"。使用WebClient.create(String baseUrl)可以统一指定一个baseUrl,这样请求指定请求uri时,可以省略baseUrl部分,如"/posts/1"。

private WebClient webClient = WebClient.create("http://jsonplaceholder.typicode.com");

@Test
void testBaseUrl(){ Mono<String> mono = webClient
.get()
.uri("/posts/1") // 请求路径,注意省略了baseurl部分
.retrieve()
.bodyToMono(String.class); System.out.println("=====" + mono.block());
}

上面代码请求结果,和4.1结果是一样的

4.3.WebClient.builder()

使用builder()创建WebClient对象,可以一次性传递的参数内容就更加丰富了。cookies、headers等信息都可以使用builder来传递。

场景:比如你请求的服务端使用JWT token,每次请求都需要传递token。如果每次请求都单独去创建一个WebClient,然后指定Token,那就麻烦了。我们可以使用builder在WebClient实例化的时候,统一设置Token。

private WebClient webClient = WebClient
.builder()
.defaultHeader("JWT-Token", "xxxyyy3fsfsfsff-fjdskfa")
.build();

支持的可选配置如下:

  • uriBuilderFactory: 自定义UriBuilderFactory灵活配置使用Url
  • defaultHeader: 为HTTP请求设置Headers请求头
  • defaultCookie: 为HTTP请求设置Cookies
  • defaultRequest: 自定义Http Request
  • filter: 为HTTP请求增加客户端过滤器
  • exchangeStrategies: HTTP 读写信息自定义
  • clientConnector: HTTP客户端连接器设置

欢迎关注我的博客,里面有很多精品合集

  • 本文转载注明出处(必须带连接,不能只转文字):字母哥博客

觉得对您有帮助的话,帮我点赞、分享!您的支持是我不竭的创作动力! 。另外,笔者最近一段时间输出了如下的精品内容,期待您的关注。

精讲响应式webclient第1篇-响应式非阻塞IO与基础用法的更多相关文章

  1. 精讲响应式WebClient第2篇-GET请求阻塞与非阻塞调用方法详解

    本文是精讲响应式WebClient第2篇,前篇的blog访问地址如下: 精讲响应式webclient第1篇-响应式非阻塞IO与基础用法 在上一篇文章为大家介绍了响应式IO模型和WebClient的基本 ...

  2. 精讲响应式WebClient第3篇-POST、DELETE、PUT方法使用

    本文是精讲响应式WebClient第3篇,前篇的blog访问地址如下: 精讲响应式webclient第1篇-响应式非阻塞IO与基础用法 精讲响应式WebClient第2篇-GET请求阻塞与非阻塞调用方 ...

  3. 精讲响应式WebClient第4篇-文件上传与下载

    本文是精讲响应式WebClient第4篇,前篇的blog访问地址如下: 精讲响应式webclient第1篇-响应式非阻塞IO与基础用法 精讲响应式WebClient第2篇-GET请求阻塞与非阻塞调用方 ...

  4. 精讲响应式WebClient第5篇-请求超时设置与异常处理

    本文是精讲响应式WebClient第5篇,前篇的blog访问地址如下: 精讲响应式webclient第1篇-响应式非阻塞IO与基础用法 精讲响应式WebClient第2篇-GET请求阻塞与非阻塞调用方 ...

  5. 精讲响应式WebClient第6篇-请求失败自动重试机制,强烈建议你看一看

    本文是精讲响应式WebClient第6篇,前篇的blog访问地址如下: 精讲响应式webclient第1篇-响应式非阻塞IO与基础用法 精讲响应式WebClient第2篇-GET请求阻塞与非阻塞调用方 ...

  6. Python学习-day10(番外篇) 阻塞IO 非阻塞IO 同步IO 异步IO

    这个章节的内容是关于IO的概念,谈一谈什么是 阻塞IO 非阻塞IO 同步IO 异步IO.以下摘要是我对这四种IO的一个形象理解. 场景是去去银行办理业务.节点有三个,1)到银行提交申请:2)取号:3) ...

  7. 什么是阻塞式和非阻塞io流?

    阻塞IO:socket 的阻塞模式意味着必须要做完IO 操作(包括错误)才会返回. 非阻塞IO:非阻塞模式下无论操作是否完成都会立刻返回,需要通过其他方式来判断具体操作是否成功. 两者区别: 所谓阻塞 ...

  8. [日常摘要] -- 阻塞IO与非阻塞IO篇

    NIO操作过程 非阻塞读/写操作 读-- 从通道读取数据到buffer,同时可以继续做别的事情,但数据都到buffer之后,线程再继续处理数据 写-- 一个线程请求写入一些数据到某通道,但不需要等待它 ...

  9. 小书MybatisPlus第7篇-代码生成器的原理精讲及使用方法

    本文是本系列文章的第七篇,前6篇访问地址如下: 小书MybatisPlus第1篇-整合SpringBoot快速开始增删改查 小书MybatisPlus第2篇-条件构造器的应用及总结 小书Mybatis ...

随机推荐

  1. 如何查看预收录在arXiv上论文的LaTeX源文件并编译

    arXiv 是一个收集物理学.数学.计算机科学与生物学论文预印本的网站. 对于理科生来说,经常需要在上面搜索下载一些论文,正常情况下,一般人下载的只是 pdf 文件,其实可以在 arXiv 上下载编译 ...

  2. kafka笔记——入门介绍

    中文文档 目录 kafka的优势 首先几个概念 kafka的四大核心API kafka的基本术语 主题和日志(Topic和Log) 每个分区都是一个顺序的,不可变的队列,并且可以持续的添加,分区中的每 ...

  3. OnePill本地保存用户的结构

    sharedPreferences存储的数据 int Code code 表示当前用户的类别:医生为1,用户为2. Sting user user 存储当前user的json字符串 String do ...

  4. IO流——转换流、缓冲流

    一.转换流 1. OutputStreamWriter类 属于字符输出流,OutputStreamWriter 是字符流通向字节流的桥梁:可使用指定的字符编码表,将要写入流中的字符编码成字节. 它的作 ...

  5. 史蒂夫-乔布斯(Steve Jobs)斯坦福大学演讲稿(中英对照)

    这是苹果公司和Pixar动画工作室的CEO Steve Jobs于2005年6月12号在斯坦福大学的毕业典礼上面的演讲稿. Thank you. I'm honored to be with you ...

  6. isinstance方法判断可迭代和迭代器

    from collections import Iterable print(isinstance([],Iterable)) print(isinstance( {}, Iterable)) pri ...

  7. SUM and COUNT -- SQLZOO

    SUM and COUNT 注意:where语句中对表示条件的需要用单引号, 下面的译文使用的是有道翻译如有不正确,请直接投诉有道 01.Show the total population of th ...

  8. 2020牛客暑假多校训练营 第二场 E Exclusive OR FWT

    LINK:Exclusive OR 没做出 原因前面几篇说过了. 根据线性基的知识容易推出 不超过\(w=log Mx\)个数字即可拼出最大值 其中Mx为值域. 那么考虑w+2个数字显然也为最大值.. ...

  9. C/C++编程笔记:C语言成绩管理系统!链式结构的管理系统源码分享

    最近很多同学因为学校的要求,需要完成自己的那个C语言课程设计,于是就有很多人私信或者加我私聊我,问的最多的还是<学生成绩管理系统>,其实当你项目写多了你就会发现:其实各类的管理系统都离不开 ...

  10. ORCHESTRATOR介绍及使用

    ORCHESTRATOR 一简介 MySQL高可用性和复制拓扑管理工具,支持复制拓扑结构的调整,自动故障转移和手动主从切换等.后端数据库用MySQL或SQLite存储元数据,并提供Web界面展示MyS ...