SpringBoot - 网络请求客户端WebClient使用详解2(GET请求)
三、GET 请求
1,获取 String 结果数据
下面代码将响应结果映射为一个 String 字符串,并打印出来。
@RestController public class HelloController { // 创建 WebClient 对象 private WebClient webClient = WebClient.builder() .baseUrl("http://jsonplaceholder.typicode.com") .build(); @GetMapping("/test") public void test() { Mono<String> mono = webClient .get() // GET 请求 .uri("/posts/1") // 请求路径 .retrieve() // 获取响应体 .bodyToMono(String.class); //响应数据类型转换 System.out.println(mono.block()); return; } }

2,将结果转换为对象
(1)当响应的结果是 JSON 时,也可以直接指定为一个 Object,WebClient 将接收到响应后把 JSON 字符串转换为对应的对象。
@RestController public class HelloController { // 创建 WebClient 对象 private WebClient webClient = WebClient.builder() .baseUrl("http://jsonplaceholder.typicode.com") .build(); @GetMapping("/test") public void test() { Mono<PostBean> mono = webClient .get() // GET 请求 .uri("/posts/1") // 请求路径 .retrieve() // 获取响应体 .bodyToMono(PostBean.class); //响应数据类型转换 System.out.println(mono.block()); return; } }

(2)其中定义的实体 Bean 代码如下:
@Getter @Setter @ToString public class PostBean { private int userId; private int id; private String title; private String body; }
3,将结果转成集合
(1)假设接口返回的是一个 json 数组,内容如下:

(2)我们也可以将其转成对应的 Bean 集合:
@RestController public class HelloController { // 创建 WebClient 对象 private WebClient webClient = WebClient.builder() .baseUrl("http://jsonplaceholder.typicode.com") .build(); @GetMapping("/test") public void test() { Flux<PostBean> flux = webClient .get() // GET 请求 .uri("/posts") // 请求路径 .retrieve() // 获取响应体 .bodyToFlux(PostBean.class); //响应数据类型转换 List<PostBean> posts = flux.collectList().block(); System.out.println("结果数:" + posts.size()); return; } }

4,参数传递的几种方式
下面 3 种方式的结果都是一样的。
(1)使用占位符的形式传递参数:
Mono<String> mono = webClient .get() // GET 请求 .uri("/{1}/{2}", "posts", "1") // 请求路径 .retrieve() // 获取响应体 .bodyToMono(String.class); //响应数据类型转换
(2)另一种使用占位符的形式:
String type = "posts"; int id = 1; Mono<String> mono = webClient .get() // GET 请求 .uri("/{type}/{id}", type, id) // 请求路径 .retrieve() // 获取响应体 .bodyToMono(String.class); //响应数据类型转换 System.out.println(mono.block());
(3)我们也可以使用 map 装载参数:
Map<String,Object> map = new HashMap<>(); map.put("type", "posts"); map.put("id", 1); Mono<String> mono = webClient .get() // GET 请求 .uri("/{type}/{id}", map) // 请求路径 .retrieve() // 获取响应体 .bodyToMono(String.class); //响应数据类型转换
5,subscribe 订阅(非阻塞式调用)
(1)前面的样例我们都是人为地使用 block 方法来阻塞当前程序。其实 WebClient 是异步的,也就是说等待响应的同时不会阻塞正在执行的线程。只有在响应结果准备就绪时,才会发起通知。
@RestController public class HelloController { // 创建 WebClient 对象 private WebClient webClient = WebClient.builder() .baseUrl("http://jsonplaceholder.typicode.com") .build(); @GetMapping("/test") public void test() { System.out.println("--- begin ---"); Mono<String> mono = webClient .get() // GET 请求 .uri("/posts/1") // 请求路径 .retrieve() // 获取响应体 .bodyToMono(String.class); //响应数据类型转换 // 订阅(异步处理结果) mono.subscribe(result -> { System.out.println(result); }); System.out.println("--- end ---"); return; } }
(2)运行结果如下:

附:使用 exchange() 方法获取完整的响应内容
1,方法介绍
(1)前面我们都是使用 retrieve() 方法直接获取到了响应的内容,如果我们想获取到响应的头信息、Cookie 等,可以在通过 WebClient 请求时把调用 retrieve() 改为调用 exchange()。(2)通过 exchange() 方法可以访问到代表响应结果的对象,通过该对象我们可以获取响应码、contentType、contentLength、响应消息体等。
2,使用样例
下面代码请求一个网络接口,并将响应体、响应头、响应码打印出来。其中响应体的类型设置为 String。
@RestController public class HelloController { // 创建 WebClient 对象 private WebClient webClient = WebClient.builder() .baseUrl("http://jsonplaceholder.typicode.com") .build(); @GetMapping("/test") public void test() { Mono<ClientResponse> mono = webClient .get() // GET 请求 .uri("/posts/1") // 请求路径 .exchange(); // 获取完整的响应对象 ClientResponse response = mono.block(); HttpStatus statusCode = response.statusCode(); // 获取响应码 int statusCodeValue = response.rawStatusCode(); // 获取响应码值 Headers headers = response.headers(); // 获取响应头 // 获取响应体 Mono<String> resultMono = response.bodyToMono(String.class); String body = resultMono.block(); // 输出结果 System.out.println("statusCode:" + statusCode); System.out.println("statusCodeValue:" + statusCodeValue); System.out.println("headers:" + headers.asHttpHeaders()); System.out.println("body:" + body); return; } }
