🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
## 一、WebFlux概述 WebFlux是Spring5引入的一种基于响应式非阻塞IO编程模型的,替代SpringMVC基于Servlet编程模型的一种新技术; WebFlux底层实现是久经考验的netty非阻塞IO通信框架; 响应式非阻塞IO模型的核心意义在于:提高了单位时间内有限资源下的服务请求的并发处理能力,而不是缩短了单个服务请求的响应时长; WebClient是与响应式编程配套的Spring 5客户端框架; ## 二、基本方法 ### **创建WebClient** * `WebClient.create()` * `WebClient.create(String baseUrl)`:指定了baseUrl,使用该客户端发送请求都基于baseUrl * `WebClient.builder()`返回一个WebClient.Builder,该对象可以做链式调用,传递更多的参数 ### **URL传参方法** 数字顺序占位符: ``` Mono<String> mono = webClient.uri("/{1}/{2}", "posts", "1") ``` 参数名称占位符: ``` String type = "posts"; int id = 1; Mono<String> mono = webClient.uri("/{type}/{id}", type, id) ``` 通过map传参: ``` Map<String,Object> map = new HashMap<>(); map.put("type", "posts"); map.put("id", 1); Mono<String> mono = webClient.uri("/{type}/{id}", map) ``` ## 三、获取响应体 ### **block()阻塞式获取响应结果** 在请求发送之后使用block()方法,阻塞当前线程等待获取响应结果,就是阻塞式获取响应结果; 单个对象用: ``` mono.block() ``` 例如: ``` Mono<PostDTO> mono = webClient.get().uri("/posts/1").retrieve().bodyToMono(PostDTO.class); System.out.println(mono.block()); ``` 或者列表对象用: ``` flux.collectList().block() ``` 例如: ``` Flux<PostDTO> flux = webClient.get().uri("/posts").retrieve() .bodyToFlux(PostDTO.class); List<PostDTO> posts = flux.collectList().block(); System.out.println("获取posts集合元素数量:" + posts.size()); ``` ### **subscribe()非阻塞式获取响应结果** 与block()阻塞式获取响应结果不同,使用subscribe()异步订阅响应结果,不会阻塞主线程继续向下执行。获取到响应结果之后,由回调函数handleResponse处理响应结果; ``` public void testSubscribe() throws InterruptedException { Mono<PostDTO> mono = webClient.get().uri("/posts/1").retrieve().bodyToMono(PostDTO.class); mono.subscribe(GetTest::handleResponse); } //响应结果处理回调方法 private static void handleResponse(PostDTO postDTO) { System.out.println("handle response:======================="); System.out.println(postDTO); } ``` ## 四、获取HTTP响应完整内容 retrieve()只能获取HTTP报文中的Body,也就是响应体。如果我们想获取HTTP报文中的状态码、headers、cookies等信息,需要使用exchange()方法; ``` @Test public void testExchange() { Mono<ClientResponse> mono = webClient.get().uri("/posts/1").exchange(); System.out.println(mono.block()); // 获取完整的响应对象 ClientResponse response = mono.block(); assert response != null; HttpStatus httpStatus = response.statusCode(); // 获取响应状态 int statusCodeValue = response.rawStatusCode(); // 获取响应状态码 ClientResponse.Headers headers = response.headers(); // 获取响应头 // 获取响应体 Mono<PostDTO> resultMono = response.bodyToMono(PostDTO.class); PostDTO postDTO = resultMono.block(); // 输出结果 System.out.println("响应状态:" + httpStatus); System.out.println("响应状态码值:" + statusCodeValue); System.out.println("HTTP Headers:" + headers.asHttpHeaders()); System.out.println("响应体:" + postDTO); } ``` ## 五、POST方法 POST相对GET,比较繁琐一些; ### **发送JSON字符串数据** ``` String jsonStr = "{\"1\": 1,\"title\": \"a\",\"body\": \"test\"}"; Mono<String> mono = webClient.post().uri("/posts").contentType(MediaType.APPLICATION_JSON).body(BodyInserters.fromValue(jsonStr)).retrieve().bodyToMono(String.class); ``` ### **发送JSON对象数据** ``` PostDTO postDTO = new PostDTO(); postDTO.setUserId(1); postDTO.setTitle("a"); postDTO.setBody("test"); Mono<PostDTO> mono = webClient.post().uri("/posts").contentType(MediaType.APPLICATION_JSON).bodyValue(postDTO).retrieve().bodyToMono(PostDTO.class); ``` ### **发送表单数据** ``` MultiValueMap<String, String> map = new LinkedMultiValueMap<>(); map.add("para1", "paraVal1); map.add("para2", "paraVal2); Mono<String> mono = webClient.post().uri("/posts") .contentType(MediaType.APPLICATION_FORM_URLENCODED) .body(BodyInserters.fromFormData(map)).retrieve().bodyToMono(String.class); ``` ## 六、异常处理 ``` Mono<String> mono = getWebClient().get().uri("/postss/1").retrieve().onStatus(e -> e.is4xxClientError(), resp -> { System.out.println("发生客户端输入错误:" + resp.statusCode().value() + " "+ resp.statusCode().getReasonPhrase()); return Mono.error(new RuntimeException("请求失败")); }) .onStatus(e -> e.is5xxServerError(), resp -> { System.out.println("发生服务端错误:" + resp.statusCode().value() + " " + resp.statusCode().getReasonPhrase()); return Mono.error(new RuntimeException("服务器异常")); }) .bodyToMono(String.class); ```