一、WebClient
1、概述
- WebClient 是 WebFlux 模块的一部分,专门用于发送 HTTP 请求和处理 HTTP 响应
2、WebClient 引入
- pom.xml,引入依赖,这里是 Spring Boot 项目中引入,通常不需要显式指定版本号
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
二、WebClient 基本使用
1、普通 GET 请求
(1)Server
@GetMapping("/testGet")
public String testGet() {
return "testGet Hello World";
}
(2)client
WebClient webClient = WebClient.create();
Mono<String> response = webClient.get()
.uri("http://127.0.0.1:9999/test/testGet")
.retrieve()
.bodyToMono(String.class);
response.subscribe(result -> {
System.out.println("请求成功,结果为:" + result);
}, throwable -> {
System.out.println("请求失败,结果为:" + throwable.getMessage());
});
请求成功,结果为:testGet Hello World
2、普通带参 GET 请求
(1)Server
@GetMapping("/testGetCarryData")
public String testGetCarryData(@RequestParam("str") String str) {
return "testGetCarryData " + str;
}
(2)Client
WebClient webClient = WebClient.create();
Mono<String> response = webClient.get()
.uri("http://127.0.0.1:9999/test/testGetCarryData?str=12345")
.retrieve()
.bodyToMono(String.class);
response.subscribe(result -> {
System.out.println("请求成功,结果为:" + result);
}, throwable -> {
System.out.println("请求失败,结果为:" + throwable.getMessage());
});
WebClient webClient = WebClient.create("http://127.0.0.1:9999");
Mono<String> response = webClient.get()
.uri(
uriBuilder ->
uriBuilder.path("/test/testGetCarryData")
.queryParam("str", "12345")
.build()
)
.retrieve()
.bodyToMono(String.class);
response.subscribe(result -> {
System.out.println("请求成功,结果为:" + result);
}, throwable -> {
System.out.println("请求失败,结果为:" + throwable.getMessage());
});
请求成功,结果为:testGetCarryData 12345
3、RESTFul GET 请求
(1)Entity
@Data
@NoArgsConstructor
@AllArgsConstructor
class User {
private int id;
private String name;
private int age;
}
(2)Server
@GetMapping("/testRestful/{id}")
public User testGetRestful(@PathVariable Integer id) {
HashMap<Integer, User> userMap = new HashMap<>();
userMap.put(1, new User(1, "jack", 10));
userMap.put(2, new User(2, "tom", 20));
userMap.put(3, new User(3, "smith", 30));
return userMap.get(id);
}
(3)Client
WebClient webClient = WebClient.create();
Mono<User> response = webClient.get()
.uri("http://127.0.0.1:9999/test/testGetRestful/{id}", 1)
.retrieve()
.bodyToMono(User.class);
response.subscribe(result -> {
System.out.println("请求成功,结果为:" + result);
}, throwable -> {
System.out.println("请求失败,结果为:" + throwable.getMessage());
});
请求成功,结果为:User(id=1, name=jack, age=10)
4、普通 POST 请求
(1)Entity
@Data
@NoArgsConstructor
@AllArgsConstructor
class User {
private int id;
private String name;
private int age;
}
(2)Server
@PostMapping("/testPost")
public User testPost(@RequestBody User user) {
HashMap<Integer, User> userMap = new HashMap<>();
userMap.put(1, new User(1, "jack", 10));
userMap.put(2, new User(2, "tom", 20));
userMap.put(3, new User(3, "smith", 30));
return userMap.get(user.getId());
}
(3)Client
User user = new User();
user.setId(1);
WebClient webClient = WebClient.create();
Mono<String> response = webClient.post()
.uri("http://127.0.0.1:9999/test/testPost")
.contentType(MediaType.APPLICATION_JSON)
.body(BodyInserters.fromValue(user))
.retrieve()
.bodyToMono(String.class);
response.subscribe(result -> {
System.out.println("请求成功,结果为:" + result);
}, throwable -> {
System.out.println("请求失败,结果为:" + throwable.getMessage());
});
请求成功,结果为:{"id":1,"name":"jack","age":10}
三、WebClient 异常请求
1、404 请求
WebClient webClient = WebClient.create();
Mono<String> response = webClient.get()
.uri("http://127.0.0.1:9999/test/testGet12345")
.retrieve()
.bodyToMono(String.class);
response.subscribe(result -> {
System.out.println("请求成功,结果为:" + result);
}, throwable -> {
System.out.println(throwable instanceof WebClientResponseException.NotFound);
System.out.println("请求失败,结果为:" + throwable.getMessage());
});
true
请求失败,结果为:404 Not Found from GET http://127.0.0.1:9999/test/testGet12345
2、超时请求
(1)Server
@GetMapping("/testTimeout")
public String testTimeout() {
try {
Thread.sleep(20 * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "testTimeout Hello World";
}
(2)Client
HttpClient httpClient = HttpClient.create()
.responseTimeout(Duration.ofSeconds(5))
.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 3000);
WebClient webClient = WebClient.builder()
.clientConnector(new ReactorClientHttpConnector(httpClient))
.baseUrl("http://127.0.0.1:9999")
.build();
Mono<String> response = webClient.get()
.uri("/test/testTimeout")
.retrieve()
.bodyToMono(String.class);
response.subscribe(result -> {
System.out.println("请求成功,结果为:" + result);
}, throwable -> {
System.out.println("请求失败,结果为:" + throwable.getMessage());
});
io.netty.handler.timeout.ReadTimeoutException: null
请求失败,结果为:null
四、WebClient 扩展
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()
.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 -> {
System.out.println("请求失败,结果为:" + throwable.getMessage());
});
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 -> {
System.out.println("请求失败,结果为:" + throwable.getMessage());
});
请求成功
result length is 846049
2、携带请求头
(1)Server
@GetMapping("/testRequestHeader")
public String testRequestHeader(HttpServletRequest request) {
String test = request.getHeader("test");
return "testRequestHeader " + test;
}
(2)Client
WebClient webClient = WebClient.builder()
.baseUrl("http://127.0.0.1:9999")
.filter((request, next) -> {
ClientRequest mutatedRequest = ClientRequest.from(request)
.header("test", "Hello World 123")
.build();
return next.exchange(mutatedRequest);
})
.build();
Mono<String> response = webClient.get()
.uri("/test/testRequestHeader")
.retrieve()
.bodyToMono(String.class);
response.subscribe(result -> {
System.out.println("请求成功,结果为:" + result);
}, throwable -> {
System.out.println("请求失败,结果为:" + throwable.getMessage());
});
WebClient webClient = WebClient.create();
Mono<String> response = webClient.get()
.uri("http://127.0.0.1:9999/test/testRequestHeader")
.header("test", "Hello World 123")
.retrieve()
.bodyToMono(String.class);
response.subscribe(result -> {
System.out.println("请求成功,结果为:" + result);
}, throwable -> {
System.out.println("请求失败,结果为:" + throwable.getMessage());
});
请求成功,结果为:testRequestHeader Hello World 123
3、请求头扩展
- 获取请求方式
String httpMethod = request.method().name().toUpperCase();
- 打印出所有请求头信息
HttpHeaders headers = request.headers();
headers.forEach((key, values) -> {
values.forEach(value -> System.out.println(key + ": " + value));
});
- 获取 url,例如,
https://127.0.0.1:12345/personList
就获取这部分 /personList
String url = request.url().getRawPath();
4、处理响应头
(1)Server
@GetMapping("/testResponseHeader")
public ResponseEntity<String> testResponseHeader() {
HttpHeaders headers = new HttpHeaders();
headers.add("test", "Hello World 123");
return new ResponseEntity<String>("testResponseHeader: Hello World", headers, HttpStatus.OK);
}
(2)Client
WebClient webClient = WebClient.builder()
.filter((clientRequest, next) -> {
return next.exchange(clientRequest).flatMap(clientResponse -> {
clientResponse.headers().asHttpHeaders().forEach((name, values) -> {
values.forEach(value -> System.out.println(name + ": " + value));
});
return Mono.just(clientResponse);
});
})
.build();
Mono<String> response = webClient.get()
.uri("http://127.0.0.1:9999/test/testResponseHeader")
.retrieve()
.bodyToMono(String.class);
response.subscribe(result -> {
System.out.println("请求成功,结果为:" + result);
}, throwable -> {
System.out.println("请求失败,结果为:" + throwable.getMessage());
});
test: Hello World 123
Content-Type: text/plain;charset=UTF-8
Content-Length: 30
Date: Wed, 21 Aug 2024 12:21:20 GMT
请求成功,结果为:testResponseHeader Hello World