【怎样基于Okhttp3来实现各种各样的远程调用,表单、JSON、文件、文件流等待】
HTTP客户端工具 okhttp3 form/json/multipart
- 提供表达、json、混合表单、混合表单文件流传输等HTTP请求调用
- 支持自定义配置默认客户端,参数列表如下:
okhtt3.config.connectTimeout 连接超时,TimeUnit.SECONDS
okhtt3.config.readTimeOut 读取超时,TimeUnit.SECONDS
okhtt3.config.writeTimeOut 写超时,TimeUnit.SECONDS
okhtt3.config.callTimeout 流程超时,TimeUnit.SECONDS
- 写一个组件,第一步首先就是定义功能接口啦
public interface Okhttp3 {
String postRequest(OkHttpClient httpClient, RequestBody requestBody, String url, Map<String, String> headers) throws IOException;
}
- 然后就是注入我们自定义的okhttpClient,自定义配置参数如下:
@ConfigurationProperties(prefix = "okhtt3.config")
public class DefaultOkhttp3ClientProperties {
private Integer connectTimeout = 2;
private Integer readTimeout = 10;
private Integer writeTimeout = 10;
private Integer callTimeOut = 20;
public Integer getConnectTimeout() {
return connectTimeout;
}
public void setConnectTimeout(Integer connectTimeout) {
this.connectTimeout = connectTimeout;
}
public Integer getReadTimeout() {
return readTimeout;
}
public void setReadTimeout(Integer readTimeout) {
this.readTimeout = readTimeout;
}
public Integer getWriteTimeout() {
return writeTimeout;
}
public void setWriteTimeout(Integer writeTimeout) {
this.writeTimeout = writeTimeout;
}
public Integer getCallTimeOut() {
return callTimeOut;
}
public void setCallTimeOut(Integer callTimeOut) {
this.callTimeOut = callTimeOut;
}
}
- 注入自定义客户端,支持HTTP/HTTPS
@Configuration
@EnableConfigurationProperties(DefaultOkhttp3ClientProperties.class)
public class Okhttp3Configuration {
@Bean
public DefaultOkhttp3 defaultOkhttp3() {
return new DefaultOkhttp3();
}
@Bean
@ConditionalOnMissingBean
public OkHttpClient okHttpClient(@Autowired DefaultOkhttp3ClientProperties defaultOkhttp3ClientProperties) {
X509TrustManager x509TrustManager = trustManager();
final SSLContext sslContext;
try {
sslContext = SSLContext.getInstance("SSL");
sslContext.init(null, new TrustManager[]{x509TrustManager}, new java.security.SecureRandom());
} catch (Exception e) {
throw new RuntimeException(e);
}
final SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();
OkHttpClient.Builder builder = new OkHttpClient.Builder();
builder.sslSocketFactory(sslSocketFactory, x509TrustManager);
builder.hostnameVerifier((hostname, session) -> true);
builder.connectTimeout(defaultOkhttp3ClientProperties.getConnectTimeout(), TimeUnit.SECONDS);
builder.readTimeout(defaultOkhttp3ClientProperties.getReadTimeout(), TimeUnit.SECONDS);
builder.writeTimeout(defaultOkhttp3ClientProperties.getWriteTimeout(), TimeUnit.SECONDS);
builder.callTimeout(defaultOkhttp3ClientProperties.getCallTimeOut(), TimeUnit.SECONDS);
return builder.build();
}
private static X509TrustManager trustManager() {
return new X509TrustManager() {
@Override
public void checkClientTrusted(X509Certificate[] chain, String authType) {
}
@Override
public void checkServerTrusted(X509Certificate[] chain, String authType) {
}
@Override
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[0];
}
};
}
}
- 下面就是我们应对何种复杂业务的实现了,简单的表单请求、JSON请求,到文件上传,接着就是文件流传输等等,针对大文件的传入,直接通过网络流传递,避免内存问题。下面是各种需求的实现
public class DefaultOkhttp3 implements Okhttp3 {
@Override
public String postRequest(OkHttpClient httpClient, RequestBody requestBody, String url, Map<String, String> headers) throws IOException {
Call call = makeRequestCall(httpClient, requestBody, url, headers);
return postRequest(call);
}
public String buildUrlIncludeQueryParams(String url, Map<String, String> queryParams) {
HttpUrl.Builder builder = Objects.requireNonNull(HttpUrl.parse(url)).newBuilder();
queryParams.forEach(builder::addQueryParameter);
return builder.build().toString();
}
public RequestBody buildJsonRequestBody(String json) {
return RequestBody.create(json, MediaType.parse("application/json; charset=utf-8"));
}
public RequestBody buildFormRequestBody(Map<String, String> formBody) {
FormBody.Builder builder = new FormBody.Builder();
formBody.forEach(builder::add);
return builder.build();
}
public RequestBody buildMultipartRequestBodyOfFiles(Map<String, String> formBody, Map<String, FilePat> fileMap) {
MultipartBody.Builder builder = new MultipartBody.Builder();
builder.setType(MultipartBody.FORM);
formBody.forEach(builder::addFormDataPart);
fileMap.forEach((k, v) -> builder.addFormDataPart(k, v.getFile().getName(), RequestBody.create(v.getFile(), v.getMediaType())));
return builder.build();
}
public RequestBody buildMultipartFilesRequestBody(Map<String, String> formBody, Map<String, MultipartFile> fileMap) {
MultipartBody.Builder builder = new MultipartBody.Builder();
builder.setType(MultipartBody.FORM);
formBody.forEach(builder::addFormDataPart);
fileMap.forEach((k, v) -> {
try {
builder.addFormDataPart(k, v.getName(), RequestBody.create(v.getBytes(), MediaType.get(Objects.requireNonNull(v.getContentType()))));
} catch (IOException e) {
throw new RuntimeException(e);
}
});
return builder.build();
}
public RequestBody buildMultipartFilesInputStreamRequestBody(Map<String, String> formBody, Map<String, MultipartFile> fileMap) {
MultipartBody.Builder builder = new MultipartBody.Builder();
builder.setType(MultipartBody.FORM);
formBody.forEach(builder::addFormDataPart);
fileMap.forEach((k, v) -> {
builder.addFormDataPart(k, v.getOriginalFilename(), new RequestBody() {
@NotNull
@Override
public MediaType contentType() {
return MediaType.get(Objects.requireNonNull(v.getContentType()));
}
@Override
public long contentLength() {
return v.getSize();
}
@Override
public void writeTo(@NotNull BufferedSink bufferedSink) throws IOException {
try (InputStream inputStream = v.getInputStream()) {
byte[] buffer = new byte[2048];
int len;
while ((len = inputStream.read(buffer)) != -1) {
bufferedSink.write(buffer, 0, len);
bufferedSink.flush();
}
}
}
});
});
return builder.build();
}
public static class FilePat {
private File file;
private MediaType mediaType;
public File getFile() {
return file;
}
public void setFile(File file) {
this.file = file;
}
public MediaType getMediaType() {
return mediaType;
}
public void setMediaType(MediaType mediaType) {
this.mediaType = mediaType;
}
}
private Call makeRequestCall(OkHttpClient httpClient, RequestBody body, String reqUrl, Map<String, String> headers) {
Request.Builder reqBuilder = new Request.Builder();
reqBuilder.url(reqUrl).post(body);
if (headers != null && !headers.isEmpty()) {
for (Map.Entry<String, String> entry : headers.entrySet()) {
reqBuilder.header(entry.getKey(), entry.getValue());
}
}
return httpClient.newCall(reqBuilder.build());
}
private String postRequest(Call call) throws IOException {
try (Response resp = call.execute()) {
ResponseBody rb = resp.body();
if (resp.code() != 200) {
String msg = null;
if (rb != null) {
msg = rb.string();
}
throw new IOException("http code: " + resp.code() + (msg != null ? ",msg:" + msg : ""));
}
if (rb == null) {
throw new IllegalStateException("http response body is null");
}
return rb.string();
}
}
}
原文地址:https://blog.csdn.net/zzwforbid_404/article/details/142595067
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!