zoukankan      html  css  js  c++  java
  • 精讲响应式WebClient第2篇-GET请求阻塞与非阻塞调用方法详解

    本文是精讲响应式WebClient第2篇,前篇的blog访问地址如下:

    在上一篇文章为大家介绍了响应式IO模型和WebClient的基本用法。本节来继续深入的为大家介绍:如何使用WebClient作为Http客户端发送GET请求与进行响应结果的接收。

    一、block()阻塞式获取响应结果

    WebClient客户端既支持同步异步、阻塞与非阻塞IO,我们先来为大家介绍一下同步阻塞式的编程方式。即:在请求发送之后使用block()方法,阻塞当前线程等待获取响应结果。

    1.1.使用Mono接收单个对象

    创建测试用例,成员变量WebClient,以 "http://jsonplaceholder.typicode.com" 为访问服务基础路径,该网站是一个免费提供RESTful API进行接口测试的一个网站。

    public class GetTest {
    
      //创建webClient
      private WebClient webClient = WebClient.builder()
              .baseUrl("http://jsonplaceholder.typicode.com")
              .build();
    
    
      @Test
      public void testMono() {
        Mono<PostDTO> mono = webClient
                .get()    // 发送GET 请求
                .uri("/posts/1")  //服务请求路径,基于baseurl
                .retrieve() // 获取响应体
                .bodyToMono(PostDTO.class); //响应数据类型转换
        System.out.println(mono.block());
      }
    
    }
    
    • get() 方法表示使用HTTP GET method
    • uri() 指定服务接口路径,以baseurl为基础
    • retrieve() 获取响应体,即HTTP body
    • bodyToMono()将响应体转换为一个对象,Mono英文是单声道、单体的意思,用于接收单个对象

    通过浏览器访问 "http://jsonplaceholder.typicode.com/posts/1" 得到JSON响应结果,和我们通过程序打印出的响应结果数据内容一致。程序控制台截图如下:

    接收响应结果的java POJO实体对象如下:

    import lombok.Data;
    
    @Data
    public class PostDTO {
        private int userId;
        private int id;
        private String title;
        private String body;
    }
    

    1.2.使用Flux接收集合对象

    访问http://jsonplaceholder.typicode.com/posts 可以获得JSON数组方式的请求结果如图(一共100条我截图截取3条记录):


    所以我们需要通过bodyToFlux方法将请求结果转为Flux<PostDTO>,通过flux.collectList().block();接收响应数据为 List<PostDTO>集合。Flux英文含义:流动的,用于接收集合元素响应结果。

    @Test
    public void testFlux() {
      Flux<PostDTO> flux = webClient
              .get() // 发送GET 请求
              .uri("/posts")  //服务请求路径,基于baseurl
              .retrieve() // 获取响应体
              .bodyToFlux(PostDTO.class); //响应数据类型转换
      List<PostDTO> posts = flux.collectList().block();
      assert posts != null;
      System.out.println("获取posts集合元素数量:" + posts.size());
    }
    

    控制台打印结果如下:

    二、subscribe()非阻塞式获取响应结果

    与block()阻塞式获取响应结果不同,使用subscribe()异步订阅响应结果,不会阻塞主线程继续向下执行。获取到响应结果之后,由回调函数handleResponse处理响应结果。

    @Test
    public void testSubscribe() throws InterruptedException {
      Mono<PostDTO> mono = webClient
              .get()    // 发送GET 请求
              .uri("/posts/1")  //服务请求路径,基于baseurl
              .retrieve() // 获取响应体
              .bodyToMono(PostDTO.class); //响应数据类型转换
    
      //异步非阻塞处理响应结果
      mono.subscribe(GetTest::handleResponse);
      //为了避免测试用例主线程执行完成,导致看不到异步处理结果
      Thread.currentThread().sleep(10000);
    }
    
    //响应结果处理回调方法
    private static void handleResponse(PostDTO postDTO) {
      System.out.println("handle response:=======================");
      System.out.println(postDTO);
    }
    

    控制台打印输出结果如下:

    三、exchange()获取HTTP响应完整内容

    上文中retrieve()只能获取HTTP报文中的Body,也就是响应体。如果我们想获取HTTP报文中的状态码、headers、cookies等信息,需要使用exchange()方法。

    @Test
    public void testExchange() {
      Mono<ClientResponse> mono = webClient
              .get()    // 发送GET 请求
              .uri("/posts/1")  //服务请求路径,基于baseurl
              .exchange();
    
      System.out.println(mono.block());
    
    
      // 获取完整的响应对象
      ClientResponse response = mono.block();
    
      assert response != null;
      HttpStatus httpStatus = response.statusCode(); // 获取响应状态
      int statusCodeValue = response.rawStatusCode(); // 获取响应状态码
      ClientResponse.Headers headers = response.headers(); // 获取响应头
    
      // 获取响应体
      Mono<PostDTO> resultMono = response.bodyToMono(PostDTO.class);
      PostDTO postDTO = resultMono.block();
    
      // 输出结果
      System.out.println("响应状态:" + httpStatus);
      System.out.println("响应状态码值:" + statusCodeValue);
      System.out.println("HTTP Headers:" + headers.asHttpHeaders());
      System.out.println("响应体:" + postDTO);
    }
    

    HTTP报文信息详情控制台打印结果

    四、占位符传参

    非占位符传参,写死的参数方式不灵活

    .uri("/posts/1")  //服务请求路径,基于baseurl
    

    第一种占位符传参:数字顺序占位符

    Mono<String> mono = webClient.uri("/{1}/{2}", "posts", "1") 
    

    第二种占位符传参:参数名称占位符

    String type = "posts";
    int id = 1;
     
    Mono<String> mono = webClient.uri("/{type}/{id}", type, id)  
    

    第三种通过map传参

    Map<String,Object> map = new HashMap<>();
    map.put("type", "posts");
    map.put("id", 1);
     
    Mono<String> mono = webClient
    .uri("/{type}/{id}", map) 
    

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

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

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

  • 相关阅读:
    StringBuider 在什么条件下使用效率更高?
    Hibernate 与 Mybatis 如何共存?打破你的认知!
    牛逼!OpenJDK 源码要迁移到 GitHub 了!
    别在网上乱找代码了,找了一段代码突然爆了!!!
    8 条关于 Web 前端性能的优化建议
    关于 equals 和 hashCode,看这一篇真的够了!
    Python web之Python如何调用REST服务?
    ArcGIS Server如何发布gp服务
    ArcGIS坐标单位转换(米和度分秒之间是如何转换的?)
    ArcGIS MapServer和FeatureServer的区别
  • 原文地址:https://www.cnblogs.com/zimug/p/13539042.html
Copyright © 2011-2022 走看看