当前位置: 首页 > article >正文

WebClient HTTP 请求问题处理模板(泛型响应、忽略 SSL 证书等)

一、请求大数据

1、问题案例
(1)Server
  • 该接口返回一段大小为 1MB 的字符串

    @GetMapping(“/testBigData”)
    public String testBigData() {
    int targetSize = 1024 * 1024; // 1MB
    StringBuilder sb = new StringBuilder(targetSize);
    for (int i = 0; i < targetSize; i++) sb.append(‘A’);
    String largeString = sb.toString();
    return largeString;
    }

(2)Client
WebClient webClient = WebClient.create();

Mono<String> response = webClient.get()
        .uri("http://127.0.0.1:9999/test/testBigData")
        .retrieve()
        .bodyToMono(String.class);

response.subscribe(result -> {
    System.out.println("请求成功,结果长度为:" + result.length());
}, throwable -> {
    throwable.printStackTrace();
});
  • 输出结果,因为数据量超过了设定的最大限制而报错

    org.springframework.web.reactive.function.client.WebClientResponseException: 200 OK from GET http://127.0.0.1:9999/test/testBigData
    Caused by: org.springframework.core.io.buffer.DataBufferLimitException: Exceeded limit on max bytes to buffer : 262144

2、处理策略
  • 调整数据量的最大限制

    int size = 2 * 1024 * 1024;
    ExchangeStrategies strategies = ExchangeStrategies.builder()
    .codecs(codecs -> codecs.defaultCodecs().maxInMemorySize(size))
    .build();

    WebClient webClient = WebClient.builder()
    .exchangeStrategies(strategies)
    .build();

    Mono response = webClient.get()
    .uri(“http://127.0.0.1:9999/test/testBigData”)
    .retrieve()
    .bodyToMono(String.class);

    response.subscribe(result -> {
    System.out.println(“请求成功,结果长度为:” + result.length());
    }, throwable -> {
    throwable.printStackTrace();
    });


二、不使用缓冲区请求图片

1、问题案例
(1)Server
  • application.yaml

    server:
    port: 9999
    spring:
    mvc:
    static-path-pattern: /file/download/**
    web:
    resources:
    static-locations: file:D:/fileUpload/

(2)Client
WebClient webClient = WebClient.create();

Mono<byte[]> response = webClient.get()
        .uri("http://127.0.0.1:9999/file/download/1.png")
        .accept(MediaType.IMAGE_JPEG, MediaType.IMAGE_PNG)
        .retrieve()
        .bodyToMono(byte[].class);

response.subscribe(result -> {
    System.out.println("请求成功");
    if (result != null) System.out.println("result length is " + result.length);
}, throwable -> {
    throwable.printStackTrace();
});
  • 输出结果,不使用 DataBuffer,会因为数据量超过了设定的最大限制而报错

    org.springframework.web.reactive.function.client.WebClientResponseException: 200 OK from GET http://127.0.0.1:9999/file/download/1.png
    Caused by: org.springframework.core.io.buffer.DataBufferLimitException: Exceeded limit on max bytes to buffer : 262144

2、处理策略
  • 调整数据量的最大限制

    int size = 10 * 1024 * 1024;
    ExchangeStrategies strategies = ExchangeStrategies.builder()
    .codecs(codecs -> codecs.defaultCodecs().maxInMemorySize(size))
    .build();

    WebClient webClient = WebClient.builder()
    .exchangeStrategies(strategies)
    .build();

    Mono<byte[]> response = webClient.get()
    .uri(“http://127.0.0.1:9999/file/download/1.png”)
    .accept(MediaType.IMAGE_JPEG, MediaType.IMAGE_PNG)
    .retrieve()
    .bodyToMono(byte[].class);

    response.subscribe(result -> {
    System.out.println(“请求成功”);
    if (result != null) System.out.println("result length is " + result.length);
    }, throwable -> {
    throwable.printStackTrace();
    });


三、泛型响应

1、问题案例
(1)Entity
  • Person.java

    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    public class Person {
    private String name;
    private int age;
    private T thing;
    }

  • Computer.java

    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    public class Computer {
    private String name;
    private Double price;
    }

(2)Server
@GetMapping("/testGeneric")
public Person<Computer> testGeneric() {
    Computer computer = new Computer("联想电脑", 8999.0);
    Person<Computer> person = new Person<Computer>("张三", 20, computer);
    return person;
}
(3)Client
WebClient webClient = WebClient.create();

Mono<Person> response = webClient.get()
        .uri("http://127.0.0.1:9999/test/testGeneric")
        .retrieve()
        .bodyToMono(Person.class);

response.subscribe(person -> {
    System.out.println("请求成功");
    System.out.println(person);
    Computer computer = (Computer) person.getThing();
    System.out.println(computer);
}, throwable -> {
    System.out.println("请求失败,结果为:" + throwable.getMessage());
});
  • 输出结果,对于嵌套的泛型强转失败

    请求成功
    Person(name=张三, age=20, thing={name=联想电脑, price=8999.0})
    请求失败,结果为:class java.util.LinkedHashMap cannot be cast to class com.zy.api.Computer (java.util.LinkedHashMap is in module java.base of loader ‘bootstrap’; com.zy.api.Computer is in unnamed module of loader ‘app’)

2、处理策略
  • 正确指示 bodyToMono 方法

    WebClient webClient = WebClient.create();

    Mono<Person> response = webClient.get()
    .uri(“http://127.0.0.1:9999/test/testGeneric”)
    .retrieve()
    .bodyToMono(new ParameterizedTypeReference<Person>() {
    });

    response.subscribe(person -> {
    System.out.println(“请求成功”);
    System.out.println(person);
    Computer computer = person.getThing();
    System.out.println(computer);
    }, throwable -> {
    System.out.println(“请求失败,结果为:” + throwable.getMessage());
    });


四、跟随重定向响应

1、问题案例
(1)Server
server:
  port: 9999
spring:
  mvc:
    static-path-pattern: /file/download/**
  web:
    resources:
      static-locations: file:D:/fileUpload/


@GetMapping("/testRedirect2Image")
public ResponseEntity testRedirect2Image() {
    return ResponseEntity.status(HttpStatus.SEE_OTHER)
            .header("Location", "http://127.0.0.1:9999/file/download/1.png")
            .build();
}
(2)Client
WebClient webClient = WebClient.create();

webClient.get()
        .uri("http://127.0.0.1:9999/test/testRedirect2Image")
        .accept(MediaType.IMAGE_JPEG, MediaType.IMAGE_PNG) // 指定了客户端期望接受的响应内容类型
        .retrieve() // 获取响应
        .bodyToFlux(DataBuffer.class) // 将响应体转换为 Flux<DataBuffer>
        .reduce(new org.apache.tomcat.util.http.fileupload.ByteArrayOutputStream(), (baos, dataBuffer) -> {
            try {
                byte[] bytes = new byte[dataBuffer.readableByteCount()];
                dataBuffer.read(bytes);
                baos.write(bytes);
                DataBufferUtils.release(dataBuffer);
            } catch (IOException e) {
                e.printStackTrace();
                DataBufferUtils.release(dataBuffer);
                return null;
            }
            return baos;
        })
        .map(byteArrayOutputStream -> {
            if (byteArrayOutputStream == null) return null;
            return byteArrayOutputStream.toByteArray();
        })
        .subscribe(result -> {
            if (result == null) {
                System.out.println("result is null");
                return;
            }
            System.out.println("result length: " + result.length);
        }, throwable -> {
            throwable.printStackTrace();
        });
  • 输出结果,默认不会跟随重定向响应

    result length: 0

2、处理策略
  • 收到开启跟随重定向响应

    HttpClient httpClient = HttpClient.create()
    .followRedirect(true); // 允许跟随重定向

    WebClient webClient = WebClient.builder()
    .clientConnector(new ReactorClientHttpConnector(httpClient))
    .build();

    webClient.get()
    .uri(“http://127.0.0.1:9999/test/testRedirect2Image”)
    .accept(MediaType.IMAGE_JPEG, MediaType.IMAGE_PNG) // 指定了客户端期望接受的响应内容类型
    .retrieve() // 获取响应
    .bodyToFlux(DataBuffer.class) // 将响应体转换为 Flux
    .reduce(new org.apache.tomcat.util.http.fileupload.ByteArrayOutputStream(), (baos, dataBuffer) -> {
    try {
    byte[] bytes = new byte[dataBuffer.readableByteCount()];
    dataBuffer.read(bytes);
    baos.write(bytes);
    DataBufferUtils.release(dataBuffer);
    } catch (IOException e) {
    e.printStackTrace();
    DataBufferUtils.release(dataBuffer);
    return null;
    }
    return baos;
    })
    .map(byteArrayOutputStream -> {
    if (byteArrayOutputStream == null) return null;
    return byteArrayOutputStream.toByteArray();
    })
    .subscribe(result -> {
    if (result == null) {
    System.out.println(“result is null”);
    return;
    }
    System.out.println("result length: " + result.length);
    }, throwable -> {
    throwable.printStackTrace();
    });


五、SSL 证书

1、问题案例
WebClient webClient = WebClient.create();

Mono<byte[]> response = webClient.get()
        .uri(url)
        .accept(MediaType.IMAGE_JPEG, MediaType.IMAGE_PNG)
        .retrieve()
        .bodyToFlux(DataBuffer.class)
        .reduce(new ByteArrayOutputStream(), (baos, dataBuffer) -> {
            try {
                byte[] bytes = new byte[dataBuffer.readableByteCount()];
                dataBuffer.read(bytes);
                baos.write(bytes);
                DataBufferUtils.release(dataBuffer);
            } catch (IOException e) {
                e.printStackTrace();
                DataBufferUtils.release(dataBuffer);
                return null;
            }
            return baos;
        })
        .map(byteArrayOutputStream -> {
            if (byteArrayOutputStream == null) return null;
            return byteArrayOutputStream.toByteArray();
        });

response.subscribe(result -> {
    System.out.println("请求成功");
    if (result != null) System.out.println("result length is " + result.length);
}, throwable -> {
    throwable.printStackTrace();
});
  • 输出结果

    org.springframework.web.reactive.function.client.WebClientRequestException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

2、忽略 SSL 证书
SslContext context = SslContextBuilder.forClient().trustManager(InsecureTrustManagerFactory.INSTANCE).build();

HttpClient httpClient = HttpClient.create().secure(t -> t.sslContext(context));

WebClient webClient = WebClient.builder()
        .clientConnector(new ReactorClientHttpConnector(httpClient))
        .build();

Mono<byte[]> response = webClient.get()
        .uri(url)
        .accept(MediaType.IMAGE_JPEG, MediaType.IMAGE_PNG)
        .retrieve()
        .bodyToFlux(DataBuffer.class)
        .reduce(new ByteArrayOutputStream(), (baos, dataBuffer) -> {
            try {
                byte[] bytes = new byte[dataBuffer.readableByteCount()];
                dataBuffer.read(bytes);
                baos.write(bytes);
                DataBufferUtils.release(dataBuffer);
            } catch (IOException e) {
                e.printStackTrace();
                DataBufferUtils.release(dataBuffer);
                return null;
            }
            return baos;
        })
        .map(byteArrayOutputStream -> {
            if (byteArrayOutputStream == null) return null;
            return byteArrayOutputStream.toByteArray();
        });

response.subscribe(result -> {
    System.out.println("请求成功");
    if (result != null) System.out.println("result length is " + result.length);
}, throwable -> {
    throwable.printStackTrace();
});

http://www.kler.cn/a/450764.html

相关文章:

  • OpenCV学习——图像融合
  • 【踩坑记录】C编程变量未初始化导致的程序异常
  • stm32定时器输出比较----驱动步进电机
  • C++ Learning string类的使用
  • windows11家庭版安装docker无法识别基于wsl2的Ubuntu
  • 蓝桥杯嵌入式备赛教程(1、led,2、lcd,3、key)
  • 《信管通低代码信息管理系统开发平台》Windows环境安装说明
  • 电感降额和选型规范
  • 点亮核心板小灯 STM32U575
  • 瑞吉外卖项目学习笔记(七)新增菜品、(批量)删除菜品
  • PHP医院安全(不良)事件管理系统源码,通过运用RCA分析工具,借助柏拉图、鱼骨图等分析工具,分析问题产生的根本原因
  • NLP 中文拼写检测纠正论文-01-介绍了SIGHAN 2015 包括任务描述,数据准备, 绩效指标和评估结果
  • TCP协议【学习指南】
  • GPT Code Interpreter
  • AIDD - 基于多层图注意力神经网络的药物-靶点相互作用预测模型研究
  • Java文字识别OCR API-手写文字识别-生僻字识别-应用场景
  • 视频汇聚融合云平台Liveweb一站式解决视频资源管理痛点
  • 京准电钟解读,NTP网络授时服务器如何提升DCS系统效率
  • 《Vue3 三》Vue 中的 options 选项
  • 使用Qwn2-VL模型批量标注图像内容(图像理解)
  • php中 cli和cgi的区别
  • python 聚类实战
  • 美国加州房价数据分析01
  • 软件测试面试题和简历模板(面试前准备篇)
  • 力扣第115题:不同的子序列 — C语言解法
  • golang , chan学习