一、请求大数据
1、问题案例
(1)Server
@GetMapping ( "/testBigData" )
public String testBigData ( ) {
int targetSize = 1024 * 1024 ;
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
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
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Person < T > {
private String name;
private int age;
private T thing;
}
@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、处理策略
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 )
. 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 )
. 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 ( ) ;
} ) ;