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

}
相关推荐
奋进的芋圆15 小时前
Java 延时任务实现方案详解(适用于 Spring Boot 3)
java·spring boot·redis·rabbitmq
sxlishaobin15 小时前
设计模式之桥接模式
java·设计模式·桥接模式
model200515 小时前
alibaba linux3 系统盘网站迁移数据盘
java·服务器·前端
荒诞硬汉16 小时前
JavaBean相关补充
java·开发语言
提笔忘字的帝国16 小时前
【教程】macOS 如何完全卸载 Java 开发环境
java·开发语言·macos
2501_9418824816 小时前
从灰度发布到流量切分的互联网工程语法控制与多语言实现实践思路随笔分享
java·开发语言
華勳全栈17 小时前
两天开发完成智能体平台
java·spring·go
alonewolf_9917 小时前
Spring MVC重点功能底层源码深度解析
java·spring·mvc
沛沛老爹17 小时前
Java泛型擦除:原理、实践与应对策略
java·开发语言·人工智能·企业开发·发展趋势·技术原理
专注_每天进步一点点17 小时前
【java开发】写接口文档的札记
java·开发语言