呼市做无痛人流z首大网站,深圳市福田建设股份有限公司网站,金融系统网站模板,单位建设网站的请示Spring中网络请求客户端WebClient的使用详解_java_脚本之家
Spring5的WebClient使用详解-腾讯云开发者社区-腾讯云
在 Spring 5 之前#xff0c;如果我们想要调用其他系统提供的 HTTP 服务#xff0c;通常可以使用 Spring 提供的 RestTemplate 来访问#xff0c;不过由于 …Spring中网络请求客户端WebClient的使用详解_java_脚本之家
Spring5的WebClient使用详解-腾讯云开发者社区-腾讯云
在 Spring 5 之前如果我们想要调用其他系统提供的 HTTP 服务通常可以使用 Spring 提供的 RestTemplate 来访问不过由于 RestTemplate 是 Spring 3 中引入的同步阻塞式 HTTP 客户端因此存在一定性能瓶颈。根据 Spring 官方文档介绍在将来的版本中它可能会被弃用。
作为替代Spring 官方已在 Spring 5 中引入了 WebClient 作为非阻塞式 Reactive HTTP 客户端。下面通过样例演示如何使用 WebClient。 一、基本介绍 1.什么是 WebClient
从 Spring 5 开始Spring 中全面引入了 Reactive 响应式编程。而 WebClient 则是 Spring WebFlux 模块提供的一个非阻塞的基于响应式编程的进行 Http 请求的客户端工具。
由于 WebClient 的请求模式属于异步非阻塞能够以少量固定的线程处理高并发的 HTTP 请求。因此从 Spring 5 开始HTTP 服务之间的通信我们就可以考虑使用 WebClient 来取代之前的 RestTemplate。 2.WebClient 的优势
1与 RestTemplate 相比WebClient 有如下优势
非阻塞Reactive 的并支持更高的并发性和更少的硬件资源。提供利用 Java 8 lambdas 的函数 API。支持同步和异步方案。支持从服务器向上或向下流式传输。
2RestTemplate 不适合在非阻塞应用程序中使用因此 Spring WebFlux 应用程序应始终使用 WebClient。在大多数高并发场景中WebClient 也应该是 Spring MVC 中的首选并且用于编写一系列远程相互依赖的调用。 3.安装配置
编辑 pom.xml 文件添加 Spring WebFlux 依赖从而可以使用 WebClient。 1 2 3 4 dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-webflux/artifactId /dependency 二、创建 WebClient 实例
从 WebClient 的源码中可以看出WebClient 接口提供了三个不同的静态方法来创建 WebClient 实例 1.利用 create() 创建
1下面利用 create() 方法创建一个 WebClient 对象并利用该对象请求一个网络接口最后将结果以字符串的形式打印出来。
注意由于利用 create() 创建的 WebClient 对象没有设定 baseURL所以这里的 uri() 方法相当于重写 baseURL。 1 2 3 4 5 6 7 8 9 WebClient webClient WebClient.create(); MonoString mono webClient .get() // GET 请求 .uri(http://jsonplaceholder.typicode.com/posts/1) // 请求路径 .retrieve() // 获取响应体 .bodyToMono(String.class); //响应数据类型转换 System.out.println(mono.block()); 2.利用 create(String baseUrl) 创建
1下面利用 create(String baseUrl) 方法创建一个 WebClient 对象并利用该对象请求一个网络接口最后将结果以字符串的形式打印出来。
注意由于利用 create(String baseUrl) 创建的 WebClient 对象时已经设定了 baseURL所以 uri() 方法会将返回的结果和 baseUrl 进行拼接组成最终需要远程请求的资源 URL。 1 2 3 4 5 6 7 8 9 WebClient webClient WebClient.create(http://jsonplaceholder.typicode.com); MonoString mono webClient .get() // GET 请求 .uri(/posts/1) // 请求路径 .retrieve() // 获取响应体 .bodyToMono(String.class); //响应数据类型转换 System.out.println(mono.block()); 3.利用 builder 创建推荐
1下面使用 builder() 返回一个 WebClient.Builder然后再调用 build 就可以返回 WebClient 对象。并利用该对象请求一个网络接口最后将结果以字符串的形式打印出来。
注意由于返回的不是 WebClient 类型而是 WebClient.Builder我们可以通过返回的 WebClient.Builder 设置一些配置参数例如baseUrl、header、cookie 等然后再调用 build 就可以返回 WebClient 对象了 1 2 3 4 5 6 7 8 9 10 11 12 13 WebClient webClient WebClient.builder() .baseUrl(http://jsonplaceholder.typicode.com) .defaultHeader(HttpHeaders.USER_AGENT,Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko)) .defaultCookie(ACCESS_TOKEN, test_token) .build(); MonoString mono webClient .get() // GET 请求 .uri(/posts/1) // 请求路径 .retrieve() // 获取响应体 .bodyToMono(String.class); //响应数据类型转换 System.out.println(mono.block()); 三、GET 请求 1.获取 String 结果数据
下面代码将响应结果映射为一个 String 字符串并打印出来。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 RestController public class HelloController { // 创建 WebClient 对象 private WebClient webClient WebClient.builder() .baseUrl(http://jsonplaceholder.typicode.com) .build(); GetMapping(/test) public void test() { MonoString mono webClient .get() // GET 请求 .uri(/posts/1) // 请求路径 .retrieve() // 获取响应体 .bodyToMono(String.class); //响应数据类型转换 System.out.println(mono.block()); return; } } 2.将结果转换为对象
1当响应的结果是 JSON 时也可以直接指定为一个 ObjectWebClient 将接收到响应后把 JSON 字符串转换为对应的对象。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 RestController public class HelloController { // 创建 WebClient 对象 private WebClient webClient WebClient.builder() .baseUrl(http://jsonplaceholder.typicode.com) .build(); GetMapping(/test) public void test() { MonoPostBean mono webClient .get() // GET 请求 .uri(/posts/1) // 请求路径 .retrieve() // 获取响应体 .bodyToMono(PostBean.class); //响应数据类型转换 System.out.println(mono.block()); return; } }
2其中定义的实体 Bean 代码如下 1 2 3 4 5 6 7 8 9 Getter Setter ToString public class PostBean { private int userId; private int id; private String title; private String body; } 3.将结果转成集合
1假设接口返回的是一个 json 数组内容如下 2我们也可以将其转成对应的 Bean 集合 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 RestController public class HelloController { // 创建 WebClient 对象 private WebClient webClient WebClient.builder() .baseUrl(http://jsonplaceholder.typicode.com) .build(); GetMapping(/test) public void test() { FluxPostBean flux webClient .get() // GET 请求 .uri(/posts) // 请求路径 .retrieve() // 获取响应体 .bodyToFlux(PostBean.class); //响应数据类型转换 ListPostBean posts flux.collectList().block(); System.out.println(结果数 posts.size()); return; } } 4.参数传递的几种方式
下面 3 种方式的结果都是一样的。
1使用占位符的形式传递参数 1 2 3 4 5 MonoString mono webClient .get() // GET 请求 .uri(/{1}/{2}, posts, 1) // 请求路径 .retrieve() // 获取响应体 .bodyToMono(String.class); //响应数据类型转换
2另一种使用占位符的形式 1 2 3 4 5 6 7 8 9 String type posts; int id 1; MonoString mono webClient .get() // GET 请求 .uri(/{type}/{id}, type, id) // 请求路径 .retrieve() // 获取响应体 .bodyToMono(String.class); //响应数据类型转换 System.out.println(mono.block());
3我们也可以使用 map 装载参数 1 2 3 4 5 6 7 8 9 MapString,Object map new HashMap(); map.put(type, posts); map.put(id, 1); MonoString mono webClient .get() // GET 请求 .uri(/{type}/{id}, map) // 请求路径 .retrieve() // 获取响应体 .bodyToMono(String.class); //响应数据类型转换 5.subscribe 订阅非阻塞式调用
1前面的样例我们都是人为地使用 block 方法来阻塞当前程序。其实 WebClient 是异步的也就是说等待响应的同时不会阻塞正在执行的线程。只有在响应结果准备就绪时才会发起通知。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 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 ---); MonoString mono webClient .get() // GET 请求 .uri(/posts/1) // 请求路径 .retrieve() // 获取响应体 .bodyToMono(String.class); //响应数据类型转换 // 订阅异步处理结果 mono.subscribe(result - { System.out.println(result); }); System.out.println(--- end ---); return; } } 附使用 exchange() 方法获取完整的响应内容 1.方法介绍
1前面我们都是使用 retrieve() 方法直接获取到了响应的内容如果我们想获取到响应的头信息、Cookie 等可以在通过 WebClient 请求时把调用 retrieve() 改为调用 exchange()。
2通过 exchange() 方法可以访问到代表响应结果的对象通过该对象我们可以获取响应码、contentType、contentLength、响应消息体等。 2.使用样例
下面代码请求一个网络接口并将响应体、响应头、响应码打印出来。其中响应体的类型设置为 String。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 RestController public class HelloController { // 创建 WebClient 对象 private WebClient webClient WebClient.builder() .baseUrl(http://jsonplaceholder.typicode.com) .build(); GetMapping(/test) public void test() { MonoClientResponse mono webClient .get() // GET 请求 .uri(/posts/1) // 请求路径 .exchange(); // 获取完整的响应对象 ClientResponse response mono.block(); HttpStatus statusCode response.statusCode(); // 获取响应码 int statusCodeValue response.rawStatusCode(); // 获取响应码值 Headers headers response.headers(); // 获取响应头 // 获取响应体 MonoString 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; } } 四、POST 请求 1.发送一个 JSON 格式数据使用 json 字符串
1下面代码使用 post 方式发送一个 json 格式的字符串并将结果打印出来以字符串的形式。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 RestController public class HelloController { // 创建 WebClient 对象 private WebClient webClient WebClient.builder() .baseUrl(http://jsonplaceholder.typicode.com) .build(); GetMapping(/test) public void test() { // 需要提交的 json 字符串 String jsonStr {\userId\: 222,\title\: \abc\,\body\: \航歌\}; // 发送请求 MonoString mono webClient .post() // POST 请求 .uri(/posts) // 请求路径 .contentType(MediaType.APPLICATION_JSON_UTF8) .body(BodyInserters.fromObject(jsonStr)) .retrieve() // 获取响应体 .bodyToMono(String.class); //响应数据类型转换 // 输出结果 System.out.println(mono.block()); return; } } 2.发送一个 JSON 格式数据使用 Java Bean
1下面代码使用 post 方式发送一个 Bean 对象并将结果打印出来以字符串的形式。结果同上面是一样的 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 RestController public class HelloController { // 创建 WebClient 对象 private WebClient webClient WebClient.builder() .baseUrl(http://jsonplaceholder.typicode.com) .build(); GetMapping(/test) public void test() { // 要发送的数据对象 PostBean postBean new PostBean(); postBean.setUserId(222); postBean.setTitle(abc); postBean.setBody(航歌); // 发送请求 MonoString mono webClient .post() // POST 请求 .uri(/posts) // 请求路径 .contentType(MediaType.APPLICATION_JSON_UTF8) .syncBody(postBean) .retrieve() // 获取响应体 .bodyToMono(String.class); //响应数据类型转换 // 输出结果 System.out.println(mono.block()); return; } }
2上面发送的 Bean 对象实际上会转成如下格式的 JSON 数据提交 3.使用 Form 表单的形式提交数据
1下面样例使用 POST 方式发送 multipart/form-data 格式的数据 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 RestController public class HelloController { // 创建 WebClient 对象 private WebClient webClient WebClient.builder() .baseUrl(http://jsonplaceholder.typicode.com) .build(); GetMapping(/test) public void test() { //提交参数设置 MultiValueMapString, String map new LinkedMultiValueMap(); map.add(title, abc); map.add(body, 航歌); // 发送请求 MonoString mono webClient .post() // POST 请求 .uri(/posts) // 请求路径 .contentType(MediaType.APPLICATION_FORM_URLENCODED) .body(BodyInserters.fromFormData(map)) .retrieve() // 获取响应体 .bodyToMono(String.class); //响应数据类型转换 // 输出结果 System.out.println(mono.block()); return; } }
2上面代码最终会通过如下这种 form 表单方式提交数据 4.将结果转成自定义对象
上面样例我们都是将响应结果以 String 形式接收其实 WebClient 还可以自动将响应结果转成自定的对象或则数组。具体可以参考前面写的文章 5.设置 url 参数
1如果 url 地址上面需要传递一些参数可以使用占位符的方式 1 2 String url http://jsonplaceholder.typicode.com/{1}/{2}; String url http://jsonplaceholder.typicode.com/{type}/{id};
2具体的用法可以参考前面写的文章 6.subscribe 订阅非阻塞式调用
1前面的样例我们都是人为地使用 block 方法来阻塞当前程序。其实 WebClient 是异步的也就是说等待响应的同时不会阻塞正在执行的线程。只有在响应结果准备就绪时才会发起通知。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 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 ---); // 需要提交的 json 字符串 String jsonStr {\userId\: 222,\title\: \abc\,\body\: \航歌\}; MonoString mono webClient .post() // POST 请求 .uri(/posts) // 请求路径 .contentType(MediaType.APPLICATION_JSON_UTF8) .body(BodyInserters.fromObject(jsonStr)) .retrieve() // 获取响应体 .bodyToMono(String.class); //响应数据类型转换 // 订阅异步处理结果 mono.subscribe(result - { System.out.println(result); }); System.out.println(--- end ---); return; } }