1.参考
1.Spring WebClient 教程
2.Netty客户端-配置DNSResolution超时
2.创建WebClient
/**
* 创建 webclient实例
* @return webclient实例
*/
public WebClient buildWebClient(){
return WebClient.builder()
.clientConnector(new ReactorClientHttpConnector(buildHttpClient()))
.build();
}
/**
* 创建 http client 实例
*
* 通过 ChannelOption.CONNECT_TIMEOUT_MILLIS 选项设置连接超时间。
* 分别使用 ReadTimeoutHandler 和写 WriteTimeoutHandler 设置读、写超时。
* 使用 responseTimeout 指令配置响应超时。
*
* @return HttpClient
*/
private HttpClient buildHttpClient() {
try{
SslContext sslContext = SslContextBuilder
.forClient()
.trustManager(InsecureTrustManagerFactory.INSTANCE)
.build();
return HttpClient.create()
// 忽略https 安全证书检查 可选项
.secure(t -> t.sslContext(sslContext))
// 设置DNS查询超时时间 解决 io.netty.resolver.dns.DnsNameResolverTimeoutException
.resolver(spec -> spec.queryTimeout(Duration.ofSeconds(20)))
.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 30 * 1000)
.responseTimeout(Duration.ofMillis(30 * 1000L))
.doOnConnected(conn ->
conn.addHandlerLast(new ReadTimeoutHandler(30 * 1000L, TimeUnit.MILLISECONDS))
.addHandlerLast(new WriteTimeoutHandler(30 * 1000L, TimeUnit.MILLISECONDS)));
}catch (SSLException e){
log.error("创建HttpClient出错{}", e.getMessage());
throw exception(CREATE_HTTP_CLIENT_FAIL);
}
}
3.发送post与get请求
public String getWeb(){
String res = buildWebClient()
.get()
.uri( 请求的地址(http://localhost:12345/api/get),
// 构造query参数
uriBuilder -> uriBuilder
.queryParam("参数名1", "值1")
.queryParam("参数名2", "值2")
.build()
)
// 请求头
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
.exchangeToMono(response -> response.bodyToMono(String.class))
.block();
return res;
}
public String postWeb(){
String res = buildWebClient()
.post()
.uri( 请求的地址(http://localhost:12345/api/get))
// 请求头
.bodyValue(body参数)
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
.exchangeToMono(response -> response.bodyToMono(String.class))
.block();
return res;
}
在获取响应中,.exchangeToMono(response -> response.bodyToMono(String.class))可以有更加详细的写法
.exchangeToMono(response -> {
if (response.statusCode().equals(HttpStatus.OK)) {
return response.bodyToMono(String.class);
} else if (response.statusCode().is4xxClientError()) {
return Mono.just("Error response");
} else {
return response.createException()
.flatMap(Mono::error);
}
});
4.个人遇到的问题
1.io.netty.resolver.dns.DnsNameResolverTimeoutException异常
在发送http请求时,不是直接的ip,需要DNS解析,我在发送请求的时候,总是报DNS解析超时。解决办法就是创建httpClient时,延长DNS查询时间。
.resolver(spec -> spec.queryTimeout(Duration.ofSeconds(20)))
2.响应解析
因为获取的响应是String形式的,如何把String解析成想要获取的信息了,个人的做法是通过JSONObject和JSON.parseArray解析。
/**
* 解析返回 并封装
* @param response 返回
* @return 封装后的响应
*/
private BaseResponse<String> parseResponse(String response){
try {
JSONObject json = JsonUtils.parseObject(response);
// code 为200 表明成功
int code = json.get("code", Integer.class);
if (code == HttpStatus.OK.value()) {
String data = json.get("result", String.class);
return BaseResponse.success(data);
} else {
log.error("接口访问失败{}", response);
return BaseResponse.fail(code, json.getStr("message"));
}
}catch (Exception e){
log.error("解析{}响应出错,{}", response, e.getMessage());
return BaseResponse.fail(e.getMessage());
}
}