半亩花草 发表于 2024-9-13 02:21:46

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<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();
});
二、不使用缓冲区哀求图片

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<T> {
    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<Computer>> response = webClient.get()
      .uri("http://127.0.0.1:9999/test/testGeneric")
      .retrieve()
      .bodyToMono(new ParameterizedTypeReference<Person<Computer>>() {
      });

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.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<DataBuffer>
      .reduce(new org.apache.tomcat.util.http.fileupload.ByteArrayOutputStream(), (baos, dataBuffer) -> {
            try {
                byte[] bytes = new byte;
                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.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.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();
});

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页: [1]
查看完整版本: WebClient HTTP 哀求问题处理模板(泛型相应、忽略 SSL 证书等)