【怎样基于Okhttp3来实现各种各样的远程调用,表单、JSON、文件、文件流等待】

HTTP客户端工具 okhttp3 form/json/multipart

  • 提供表达、json、混合表单、混合表单文件流传输等HTTP请求调用
  • 支持自定义配置默认客户端,参数列表如下:
java 复制代码
     okhtt3.config.connectTimeout 连接超时,TimeUnit.SECONDS
     okhtt3.config.readTimeOut 读取超时,TimeUnit.SECONDS
     okhtt3.config.writeTimeOut 写超时,TimeUnit.SECONDS
     okhtt3.config.callTimeout 流程超时,TimeUnit.SECONDS
  • 写一个组件,第一步首先就是定义功能接口啦
java 复制代码
public interface Okhttp3 {
    String postRequest(OkHttpClient httpClient, RequestBody requestBody, String url, Map<String, String> headers) throws IOException;
}
  • 然后就是注入我们自定义的okhttpClient,自定义配置参数如下:
java 复制代码
@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
java 复制代码
@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请求,到文件上传,接着就是文件流传输等等,针对大文件的传入,直接通过网络流传递,避免内存问题。下面是各种需求的实现
java 复制代码
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();
        }
    }

}
相关推荐
小曲程序6 分钟前
vue3 封装request请求
java·前端·typescript·vue
陈王卜23 分钟前
django+boostrap实现发布博客权限控制
java·前端·django
小码的头发丝、24 分钟前
Spring Boot 注解
java·spring boot
java亮小白199729 分钟前
Spring循环依赖如何解决的?
java·后端·spring
飞滕人生TYF35 分钟前
java Queue 详解
java·队列
武子康1 小时前
大数据-230 离线数仓 - ODS层的构建 Hive处理 UDF 与 SerDe 处理 与 当前总结
java·大数据·数据仓库·hive·hadoop·sql·hdfs
武子康1 小时前
大数据-231 离线数仓 - DWS 层、ADS 层的创建 Hive 执行脚本
java·大数据·数据仓库·hive·hadoop·mysql
苏-言1 小时前
Spring IOC实战指南:从零到一的构建过程
java·数据库·spring
界面开发小八哥1 小时前
更高效的Java 23开发,IntelliJ IDEA助力全面升级
java·开发语言·ide·intellij-idea·开发工具
草莓base1 小时前
【手写一个spring】spring源码的简单实现--容器启动
java·后端·spring