目录
使用WebClient的优点:支持lambdas 的函数;支持更高的并发性和更少的硬件资源;支持同步和异步;支持流式传输。具体的使用方式如下:
1、导入对应的pom
![](https://i-blog.csdnimg.cn/blog_migrate/556b77fc9cd505c8f63ff52bb3174cdf.png)
<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-webflux -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
<version>3.2.4</version>
</dependency>
其中版本可以选择当前最新即可!
2、编写WebClientUtil请求工具类
(当然此步骤非必须,可以直接在需要发起请求的地方直接定义发起也可以)
import org.springframework.http.*;
import org.springframework.util.MultiValueMap;
import org.springframework.web.reactive.function.BodyInserters;
import org.springframework.web.reactive.function.client.ExchangeFilterFunction;
import org.springframework.web.reactive.function.client.ExchangeStrategies;
import org.springframework.web.reactive.function.client.WebClient;
import org.springframework.web.reactive.function.client.WebClientResponseException;
import reactor.core.publisher.Mono;
import java.time.Duration;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
/**
* Web 客户端实用程序
*
* @author xjs
* @date 2024/03/25
*/
public class WebClientUtil {
private static final WebClient WEB_CLIENT = WebClient.create();
// 默认JSON格式
//private static final WebClient WEB_CLIENT = WebClient.builder().defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE).build();
//==============================================================================================================================
/**
* 发起GET请求,支持Get parameter
*/
public static CompletableFuture<String> getParam(String url, HttpHeaders headers, MultiValueMap<String, String> queryParams) {
return Mono.from(WEB_CLIENT.get()
.uri(uriBuilder -> uriBuilder
.path(url)
.queryParams(queryParams)
.build())
.headers(httpHeaders -> httpHeaders.putAll(headers))
//.headers(h -> headers.forEach(h::add))
.retrieve()
.onStatus(HttpStatus::isError, clientResponse -> Mono.error(new RuntimeException("HTTP error status: " + clientResponse.statusCode())))
.bodyToMono(String.class))
.onErrorResume(error -> Mono.just("Error: " + error.getMessage())) // 如果有错误,返回错误信息
.toFuture();
}
/**
* 发起GET请求,支持Get parameter
* 可以用
*/
public static CompletableFuture<String> getNoParam(String url, HttpHeaders headers) {
return Mono.from(WEB_CLIENT.get()
.uri(url)
.headers(httpHeaders -> httpHeaders.putAll(headers))
//.headers(h -> headers.forEach(h::add))
.retrieve()
.onStatus(HttpStatus::isError, clientResponse -> Mono.error(new RuntimeException("HTTP error status: " + clientResponse.statusCode())))
.bodyToMono(String.class))
.onErrorResume(error -> Mono.just("Error: " + error.getMessage())) // 如果有错误,返回错误信息
.toFuture();
}
/**
* 发起POST请求,支持JSON body
*/
public static CompletableFuture<String> postJson2(String url, Object body, HashMap<String, String> headers) {
logRequest();
return Mono.from(WEB_CLIENT.post()
.uri(url)
.contentType(MediaType.APPLICATION_JSON)
.headers(h -> headers.forEach(h::add))
.bodyValue(body)
.retrieve()
.onStatus(HttpStatus::isError, clientResponse -> Mono.error(new RuntimeException("HTTP error status: " + clientResponse.statusCode())))
.bodyToMono(String.class))
.onErrorResume(error -> Mono.just("Error: " + error.getMessage())) // 如果有错误,返回错误信息
.toFuture();
}
/**
* 发起POST请求,支持表单数据
*/
public static CompletableFuture<String> postForm(String url, MultiValueMap<String, String> formData, Map<String, String> headers) {
return Mono.from(WEB_CLIENT.post()
.uri(url)
.headers(h -> headers.forEach(h::add))
.contentType(MediaType.APPLICATION_FORM_URLENCODED)
.body(BodyInserters.fromFormData(formData))
.retrieve()
.bodyToMono(String.class))
.toFuture();
}
//===========方法2======================================================================================================
public static <T> Mono<ResponseEntity<T>> sendRequest(String url, HttpMethod method, HashMap<String, String> headers, Object requestBody, Class<T> responseType) {
return WEB_CLIENT.method(method)
.uri(url)
.headers(h -> headers.forEach(h::add))
.body(BodyInserters.fromValue(requestBody))
.retrieve()
.toEntity(responseType);
}
public static CompletableFuture<String> postJson2(String url, Object body, HashMap<String, String> headers) {
return sendRequest(url, HttpMethod.POST, headers, body, String.class)
.doOnError(error -> System.err.println("An error occurred: " + error.getMessage()))
.filter(entity -> entity.getStatusCode().is2xxSuccessful()) // 检查状态码是否成功
.mapNotNull(ResponseEntity::getBody)
.onErrorResume(error -> Mono.just("Error: " + error.getMessage())) // 如果有错误,返回错误信息
.toFuture();
}
//===========方法3============================================================================================================================================================
private String baseUrl = "http://192.168.31.118:8091";
WebClient webClient = WebClient.builder()
.baseUrl(baseUrl)
.defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
// 使用了ExchangeStrategies来限制默认的解码器缓冲区的大小。这有助于避免处理大型响应时的内存问题。
.exchangeStrategies(ExchangeStrategies.builder()
.codecs(configurer -> configurer.defaultCodecs().maxInMemorySize(16 * 1024 * 1024))
.build())
.build();
/**
* put 请求
*
* @param url 网址
* @param requestBody 请求正文
* @return {@link Mono}<{@link String}>
*/
public Mono<String> putRequest(String url, Object requestBody) {
return webClient.put()
.uri(url)
.body(BodyInserters.fromValue(requestBody))
.retrieve()
.bodyToMono(String.class);
}
/**
* 删除请求
*
* @param url 网址
* @return {@link Mono}<{@link String}>
*/
public Mono<String> deleteRequest(String url) {
return webClient.delete()
.uri(url)
.retrieve()
.bodyToMono(String.class);
}
}
3、使用WebClientUtil发起请求
/**
* 获取配置中的请求地址
*/
@Value("${url.baseUrl}")
private String baseUrl;
//发起POST请求
@PostMapping("/postRequest")
public Object postRequest(@RequestBody RequestParms requestParms) {
// 设置请求头信息
HashMap<String, String> headers = new HashMap<>();
headers.put("Content-Type", "application/json");
CompletableFuture<String> postResponse = WebClientUtil.postJson(baseUrl, requestParms, headers);
// 异步处理响应
postResponse.thenAccept(response -> {
log.info("response: {}", response);
if (response.contains("code")) {
try {
JSONObject postResponseJson = JSONObject.parseObject(response);
int statusCode = postResponseJson.getIntValue("code");
log.info("statusCode = " + statusCode);
JSONArray data = postResponseJson.getJSONArray("data");
log.info("data = " + data);
} catch (Exception e) {
log.info("Failed to parse JSON: " + e.getMessage());
}
} else {
log.info("No 'code' field in the response: " + response);
}
});
return postResponse;
}
//发起GET请求
@GetMapping("/getRequest")
public Object getRequest(RequestParms requestParms) {
// 创建请求头
HttpHeaders headers = new HttpHeaders();
headers.add("Accept", "application/json, text/javascript, */*; q=0.01");
headers.add("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36");
// 创建请求参数
MultiValueMap<String, String> queryParams = new LinkedMultiValueMap<>();
queryParams.add("code", requestParms.getCode());
// 构建URL地址
UriComponentsBuilder uriBuilder = UriComponentsBuilder.fromUriString(url);
uriBuilder.queryParams(queryParams);
String newUrls = String.valueOf(uriBuilder.build().toUri());
// 发送GET请求
//CompletableFuture<String> getResponse = WebClientUtil.getParam(url, headers, queryParams);
CompletableFuture<String> getResponse = WebClientUtil.getNoParam(newUrls, headers);
getResponse.thenAccept(response -> {
log.info("response: {}", response);
if (response.contains("status")) {
try {
JSONObject postResponseJson = JSONObject.parseObject(response);
String status = postResponseJson.getString("status");
log.info("status = " + status);
JSONObject data = postResponseJson.getJSONObject("result");
log.info("data = " + data);
} catch (Exception e) {
log.info("Failed to parse JSON: " + e.getMessage());
}
} else {
log.info("No 'code' field in the response: " + response);
}
});
return getResponse;
}
至此,就可以完成发网络请求了!