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

devtools/2024/12/29 7:29:00/
http://www.w3.org/2000/svg" style="display: none;">

一、请求大数据

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.ppmy.cn/devtools/146331.html

相关文章

美食推荐系统|Java|SSM|JSP|

【技术栈】 1⃣️&#xff1a;架构: B/S、MVC 2⃣️&#xff1a;系统环境&#xff1a;Windowsh/Mac 3⃣️&#xff1a;开发环境&#xff1a;IDEA、JDK1.8、Maven、Mysql5.7 4⃣️&#xff1a;技术栈&#xff1a;Java、Mysql、SSM、Mybatis-Plus、JSP、jquery,html 5⃣️数据库可…

Hindsight Experience Replay (HER) 算法

Hindsight Experience Replay (HER) 算法简介 Hindsight Experience Replay (HER) 是一种强化学习中的技术&#xff0c;旨在解决稀疏奖励问题&#xff0c;特别适用于目标导向的任务&#xff08;例如机器人控制、物体抓取等&#xff09;。它的基本思想是&#xff1a;即使在一个…

未来具身智能的触觉革命!TactEdge传感器让机器人具备精细触觉感知,实现织物缺陷检测、灵巧操作控制

在我们的设想中&#xff0c;一个完美的机器人应当具备和人类一样的视觉、触觉、听觉、嗅觉和味觉。 通过以上「五感」感知并理解物理世界&#xff0c;同时借助强大的 AI 大脑实现对环境的精确响应&#xff0c;是打造智能机器人的核心&#xff0c;科技巨头特斯拉也认同这一点。…

GaussDB典型SQL调优点之自诊断和语句下推调优

SQL自诊断 用户在执行查询或者执行INSERT/DELETE/UPDATE/CREATE TABLE AS语句时&#xff0c;可能会遇到性能问题。 SQL自诊断的告警类型与GUC参数resource_track_level的设置有关系。如果resource_track_level设置为query&#xff0c;则可以诊断多列/单列统计信息未收集和SQL…

基于python对网页进行爬虫简单教程

python对网页进行爬虫 基于BeautifulSoup的爬虫—源码 """ 基于BeautifulSoup的爬虫###?一、BeautifulSoup简介1.?Beautiful?Soup提供一些简单的、python式的函数用来处理导航、搜索、修改分析树等功能。它是一个工具箱&#xff0c;通过解析文档为用户提供…

【再谈设计模式】享元模式~对象共享的优化妙手

一、引言 在软件开发过程中&#xff0c;我们常常面临着创建大量细粒度对象的情况&#xff0c;这可能会导致内存占用过高、性能下降等问题。享元模式&#xff08;Flyweight Pattern&#xff09;就像是一位空间管理大师&#xff0c;它能够在不影响功能的前提下&#xff0c;有效地…

深度解析:电商平台API接口的安全挑战与应对策略

随着电子商务的蓬勃发展&#xff0c;电商平台与外部服务、内部系统之间的数据交换和通信变得日益频繁。API&#xff08;应用程序编程接口&#xff09;接口作为这一过程中的关键枢纽&#xff0c;其安全性显得尤为重要。API接口不仅承载着商品管理、订单处理、支付结算、用户管理…

macos安装maven以及.bash_profile文件优化

文章目录 下载和安装maven本地仓库配置国内镜像仓库配置.bash_profile文件优化 下载和安装maven maven下载地址 存放在/Library/Java/env/maven目录 本地仓库配置 在maven-3.9.9目录下创建maven-repo目录作为本地文件仓库打开setting配置文件 在setting标签下&#xff0c;添…