【怎样基于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();
        }
    }

}
相关推荐
zww89491111 小时前
匿名树洞系统开发实战:从需求分析到部署指南
java·eclipse
黑马程序员毕设3 小时前
基于Java的医院药品管理系统的优化设计与实现
java·开发语言·spring boot·小程序·架构·课程设计·毕设
木井巳3 小时前
【BFS/DFS 解决 FloodFill 算法】太平洋大西洋水流问题
java·算法·leetcode·深度优先·广度优先·宽度优先·推荐算法
白山编程大哥3 小时前
Java 集合算法:从排序、查找到底层原理的实战指南
java·python·算法
devpotato3 小时前
缓存与数据库更新顺序不一致问题
java·数据库·redis
xcl09253 小时前
酒馆预约系统开发实战:从需求分析到上线全流程指南
java·spring boot·需求分析
Kyrie_kk4 小时前
Java--IO--Path文件访问
java·后端
qinqinzqq4 小时前
Maven POM 格式、Schema 与 XSD:一篇讲透
java·maven
o盟4 小时前
maven本地仓库有 总是去私仓中下载
java·maven·intellij-idea
devpotato4 小时前
Java 批量并发请求:从“能并发“到“结果按完成顺序可用“的三种写法与选型
java