Java OkHttp发送网络请求与上传文件公用方法

1.引入okhttp依赖

<dependency>
    <groupId>com.squareup.okhttp3</groupId>
    <artifactId>okhttp</artifactId>
    <version>3.14.9</version>
</dependency>

2.注入bean和依赖配置信息

applcation.yml配置

okhttp:
  connect-timeout: 30
  read-timeout: 60
  write-timeout: 60
  keep-alive-duration: 300
  max-idle-connections: 30
import okhttp3.ConnectionPool;
import okhttp3.OkHttpClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.concurrent.TimeUnit;

/**
 *
 * @description:
 * @author: zhuyu
 * @date: 2022/4/8 10:21
 */
@Configuration
public class OkHttpConfiguration {

    @Autowired
    BusinessParamConfig paramConfig;

    /**
     * 连接超时时间(单位:秒)
     */
    @Value("${okhttp.connect-timeout}")
    private Integer connectTimeout;

    /**
     * 读超时时间(单位:秒)
     */
    @Value("${okhttp.read-timeout}")
    private Integer readTimeout;

    /**
     * 写超时时间(单位:秒)
     */
    @Value("${okhttp.write-timeout}")
    private Integer writeTimeout;

    /**
     * 连接池中整体的空闲连接的最大数量
     */
    @Value("${okhttp.max-idle-connections}")
    private Integer maxIdleConnections;

    /**
     * 连接空闲时间最多为 300 秒
     */
    @Value("${okhttp.keep-alive-duration}")
    private Long keepAliveDuration;


    @Bean
    public OkHttpClient okHttpClient() {
        return new OkHttpClient.Builder()
                .sslSocketFactory(sslSocketFactory(), x509TrustManager())
                // 是否开启缓存
                .retryOnConnectionFailure(false)
                .connectionPool(pool())
                .connectTimeout(connectTimeout, TimeUnit.SECONDS)
                .readTimeout(readTimeout, TimeUnit.SECONDS)
                .writeTimeout(writeTimeout,TimeUnit.SECONDS)
                .hostnameVerifier((hostname, session) -> true)
                // 设置代理
//            	.proxy(new Proxy(Proxy.Type.HTTP, new InetSocketAddress("127.0.0.1", 8888)))
                // 拦截器
                .addInterceptor(new OkHttpInterceptor(paramConfig))
                .build();
    }

    @Bean
    public X509TrustManager x509TrustManager() {
        return new X509TrustManager() {
            @Override
            public void checkClientTrusted(X509Certificate[] chain, String authType)
                    throws CertificateException {
            }
            @Override
            public void checkServerTrusted(X509Certificate[] chain, String authType)
                    throws CertificateException {
            }
            @Override
            public X509Certificate[] getAcceptedIssuers() {
                return new X509Certificate[0];
            }
        };
    }

    @Bean
    public SSLSocketFactory sslSocketFactory() {
        try {
            // 信任任何链接
            SSLContext sslContext = SSLContext.getInstance("TLS");
            sslContext.init(null, new TrustManager[]{x509TrustManager()}, new SecureRandom());
            return sslContext.getSocketFactory();
        } catch (NoSuchAlgorithmException | KeyManagementException e) {
            e.printStackTrace();
        }
        return null;
    }

    @Bean
    public ConnectionPool pool() {
        return new ConnectionPool(maxIdleConnections, keepAliveDuration, TimeUnit.SECONDS);
    }
}

3.添加okhttp拦截器,可以统一添加header头信息

import com.common.config.BusinessParamConfig;
import com.util.LogUtil;
import okhttp3.Interceptor;
import okhttp3.Request;
import okhttp3.Response;
import org.apache.commons.lang3.StringUtils;

import java.io.IOException;

/**
 * TODO
 *
 * @description:
 * @author: zhuyu
 * @date: 2022/4/18 11:24
 */
public class OkHttpInterceptor implements Interceptor {

    //注入业务配置组件
    BusinessParamConfig paramConfig;
    public OkHttpInterceptor(BusinessParamConfig paramConfig){
        this.paramConfig = paramConfig;
    }

    @Override
    public Response intercept(Chain chain) throws IOException {
        Request request = chain.request();
        //http请求添加统一headers
        Request.Builder builder = request.newBuilder();
        //此处最好先判断是否包含Content-Type,再添加,因为文件上传的Content-Type是multipart/form-data;
        builder.addHeader("Content-Type", "application/json; charset=UTF-8");
        if(StringUtils.isNotBlank(paramConfig.groupApiToken)){
            builder.addHeader("api-key", paramConfig.groupApiToken);
        }
        request = builder.build();
        try {
            return chain.proceed(request);
        } catch (Exception e) {
            throw e;
        }
    }
}

4.添加公用模版方法 OkHttpTemplate

import com.alibaba.fastjson.JSON;
import okhttp3.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.Map;

/**
 * OkHttp请求工具服务类
 *
 * @description:
 * @author: zhuyu
 * @date: 2022/4/8 10:46
 */
@Component
public class OkHttpTemplate {

    @Resource
    OkHttpClient okHttpClient;

    private OkHttpTemplate(){}

    private static Logger logger = LoggerFactory.getLogger(OkHttpTemplate.class);

    /**
     * "application/x-www-form-urlencoded",是默认的MIME内容编码类型,一般可以用于所有的情况,但是在传输比较大的二进制或者文本数据时效率低。
     * 这时候应该使用"multipart/form-data"。如上传文件或者二进制数据和非ASCII数据。
     */
    public static final MediaType MEDIA_TYPE_NORAML_FORM = MediaType.parse("application/x-www-form-urlencoded;charset=utf-8");
    public static final MediaType MEDIA_TYPE_MULTIPART_FORM = MediaType.parse("multipart/form-data;");
    public static final MediaType MEDIA_TYPE_STREAM = MediaType.parse("application/octet-stream");
    public static final MediaType MEDIA_TYPE_JSON = MediaType.parse("application/json;charset=utf-8");

    /**
     * 自定义回调接口
     */
    public interface NetCall {
        void success(Call call, Response response) throws IOException;

        void failed(Call call, IOException e);
    }

    public Request.Builder getRequestBuilder(){
        return new Request.Builder();
    }
    public Request.Builder getRequestBuilder(Map<String, String> headers){
        Request.Builder builder = getRequestBuilder();
        if(headers != null){
            for (Map.Entry<String,String> item : headers.entrySet()){
                builder.addHeader(item.getKey(), item.getValue());
            }
        }
        return builder;
    }

    /**
     * get请求
     *
     * @param url
     * @return
     */
    public String doGet(String url) {
        return doGet(url, null);
    }

    /**
     * get请求
     *
     * @param url
     * @param headers
     * @return
     */
    public String doGet(String url, Map<String, String> headers) {
        String result = "";
        try {
            //1 构造Request
            Request.Builder builder = getRequestBuilder(headers);
            Request request = builder.get().url(url).build();
            //2 将Request封装为Call
            Call call = okHttpClient.newCall(request);
            //3 执行Call,得到response
            Response response = call.execute();
            if (response.isSuccessful()) {
                result = response.body().string();
            }
        } catch (Exception e) {
            logger.error("doGet, url = " + url, e);
        }
        return result;
    }

    /**
     * get请求,异步回调
     *
     * @param url
     * @param headers
     * @param netCall
     * @return
     */
    public void doGetAsync(String url, Map<String, String> headers, final NetCall netCall) {
        try {
            //1 构造Request
            Request.Builder builder = getRequestBuilder(headers);
            Request request = builder.get().url(url).build();
            //2 将Request封装为Call
            Call call = okHttpClient.newCall(request);
            //3 执行Call
            call.enqueue(new Callback() {
                @Override
                public void onFailure(Call call, IOException e) {
                    netCall.failed(call, e);
                }

                @Override
                public void onResponse(Call call, Response response) throws IOException {
                    netCall.success(call, response);
                }
            });
        } catch (Exception e) {
            logger.error("doGetAsync, url = " + url, e);
        }
    }

    /**
     * post请求,同步方式
     *
     * @param url
     * @param bodyParams
     * @return
     */
    public String doPost(String url, Map<String, String> bodyParams) {
        return doPost(url, null, bodyParams);
    }

    /**
     * post请求,同步方式
     *
     * @param url
     * @param bodyParams
     * @param headers
     * @return
     */
    public String doPost(String url, Map<String, String> headers, Map<String, String> bodyParams) {
        String result = "";
        try {
            Request request = buildRequest(url, headers, bodyParams);
            //3 将Request封装为Call
            Call call = okHttpClient.newCall(request);
            //4 执行Call,得到response
            Response response = call.execute();
            if (response.isSuccessful()) {
                result = response.body().string();
            }
        } catch (Exception e) {
            logger.error("doPost, url = " + url + " , params : " + JSON.toJSONString(bodyParams), e);
        }
        return result;
    }

    /**
     * post请求,异步回调
     *
     * @param url
     * @param bodyParams
     * @param netCall
     */
    public void doPostAsync(String url, Map<String, String> bodyParams, final NetCall netCall) {
        doPostAsync(url, null, bodyParams, netCall);
    }

    /**
     * post请求,异步回调
     *
     * @param url
     * @param bodyParams
     * @param headers
     * @param netCall
     */
    public void doPostAsync(String url, Map<String, String> headers, Map<String, String> bodyParams, final NetCall netCall) {
        try {
            Request request = buildRequest(url, headers, bodyParams);
            //3 将Request封装为Call
            Call call = okHttpClient.newCall(request);
            //4 执行Call
            call.enqueue(new Callback() {
                @Override
                public void onFailure(Call call, IOException e) {
                    netCall.failed(call, e);
                }

                @Override
                public void onResponse(Call call, Response response) throws IOException {
                    netCall.success(call, response);
                }
            });
        } catch (Exception e) {
            logger.error("doPostAsync, url = " + url + " , params : " + JSON.toJSONString(bodyParams), e);
        }
    }

    /**
     * post请求
     *
     * @param url
     * @param json
     * @return
     * @throws IOException
     */
    public String postJson(String url, String json) {
        return postJson(url, json, null);
    }

    /**
     * post请求
     *
     * @param url
     * @param json
     * @param headers
     * @return
     */
    public String postJson(String url, String json, Map<String, String> headers) {
        String result = "";
        try {
            Request request = buildRequest(url, headers, json);
            Response response = okHttpClient.newCall(request).execute();
            if (response.isSuccessful()) {
                result = response.body().string();
            }
        } catch (Exception e) {
            logger.error("postJson, url = " + url + " , json : " + json + " , headers : " + JSON.toJSONString(headers), e);
        }
        return result;
    }

    /**
     * post请求,异步回调
     *
     * @param url
     * @param json
     * @param netCall
     * @throws IOException
     */
    public void postJsonAsync(String url, String json, final NetCall netCall) {
        postJsonAsync(url, json, null, netCall);
    }

    /**
     * post请求,异步回调
     *
     * @param url
     * @param json
     * @param netCall
     * @throws IOException
     */
    public void postJsonAsync(String url, String json, Map<String, String> headers, final NetCall netCall) {
        try {
            //2 构造Request
            Request request = buildRequest(url, headers, json);
            //3 将Request封装为Call
            Call call = okHttpClient.newCall(request);
            //4 执行Call
            call.enqueue(new Callback() {
                @Override
                public void onFailure(Call call, IOException e) {
                    netCall.failed(call, e);
                }

                @Override
                public void onResponse(Call call, Response response) throws IOException {
                    netCall.success(call, response);
                }
            });
        } catch (Exception e) {
            logger.error("postJsonAsync, url = " + url + " , json : " + json + " , headers : " + JSON.toJSONString(headers) , e);
        }
    }

    /**
     * put请求
     *
     * @param url
     * @param json
     * @return
     * @throws IOException
     */
    public String putJson(String url, String json) {
        return putJson(url, json, null);
    }

    /**
     * put请求
     *
     * @param url
     * @param json
     * @param headers
     * @return
     */
    public String putJson(String url, String json, Map<String, String> headers) {
        String result = "";
        try {
            //1构造RequestBody
            RequestBody body = RequestBody.create(MEDIA_TYPE_JSON, json);
            Request.Builder builder = getRequestBuilder(headers);
            //2 构造Request
            Request request = builder.url(url).put(body).build();

            Response response = okHttpClient.newCall(request).execute();
            if (response.isSuccessful()) {
                result = response.body().string();
            }
        } catch (Exception e) {
            logger.error("putJson, url = " + url + " , json : " + json + " , headers : " + JSON.toJSONString(headers), e);
        }
        return result;
    }

    /**
     * post文件上传
     *
     * @param url              接口地址
     * @param headers          headers参数
     * @param params           参数
     * @param fileKey          服务端接口参数key
     * @param files            文件集合
     */
    public String postFileUpload(String url, Map<String, String> headers, Map<String, String> params, String fileKey, List<File> files) {
        String result = "";
        try {
            // form 表单形式上传
            MultipartBody.Builder builder = new MultipartBody.Builder();
            builder.setType(MultipartBody.FORM);

            //添加参数
            if (params != null) {
                for (Map.Entry<String, String> entry : params.entrySet()) {
                    builder.addFormDataPart(entry.getKey(), entry.getValue());
                }
            }
            //添加文件,并约定key如“upload”作为后台接受的参数key
            if (files != null) {
                for (File file : files) {
                    builder.addFormDataPart(fileKey, file.getName(), RequestBody.create(MEDIA_TYPE_MULTIPART_FORM, file));
                }
            }
            RequestBody requestBody = builder.build();
            Request.Builder requestBuilder = getRequestBuilder(headers);
            requestBuilder.addHeader("Content-Type","multipart/form-data;");

            Request request = requestBuilder.url(url).post(requestBody).build();
            Response response = okHttpClient.newCall(request).execute();
            if (response != null && response.isSuccessful()) {
                result = response.body().string();
            }
        } catch (Exception e) {
            logger.error("postFileUpload, url = " + url + " , params : " + JSON.toJSONString(params) , e);
        }
        return result;
    }


    /**
     * post文件上传
     *
     * @param url              接口地址
     * @param headers          headers参数
     * @param params           参数
     * @param fileKey          服务端接口参数key
     * @param files            文件集合
     * @param netCall          回调函数
     */
    public void postFileUploadAsync(String url, Map<String, String> headers, Map<String, String> params, String fileKey, List<File> files,final NetCall netCall) {
        try {
            MultipartBody.Builder builder = new MultipartBody.Builder();
            builder.setType(MultipartBody.FORM);
            //添加参数
            if (params != null) {
                for (Map.Entry<String, String> entry : params.entrySet()) {
                    builder.addFormDataPart(entry.getKey(), entry.getValue());
                }
            }
            //添加文件,并约定key如“upload”作为后台接受的参数key
            if (files != null) {
                for (File file : files) {
                    builder.addFormDataPart(fileKey, file.getName(), RequestBody.create(MEDIA_TYPE_MULTIPART_FORM, file));
                }
            }
            RequestBody requestBody = builder.build();
            Request.Builder requestBuilder = getRequestBuilder(headers);
            requestBuilder.addHeader("Content-Type","multipart/form-data;");

            Request request = requestBuilder.url(url).post(requestBody).build();
            Call call = okHttpClient.newCall(request);
            //4 执行Call
            call.enqueue(new Callback() {
                @Override
                public void onFailure(Call call, IOException e) {
                    netCall.failed(call, e);
                }

                @Override
                public void onResponse(Call call, Response response) throws IOException {
                    netCall.success(call, response);
                }
            });
        } catch (Exception e) {
            logger.error("postFileUploadAsync, url = " + url + " , params : " + JSON.toJSONString(params) , e);
        }
    }

    /**
     * buildRequest by json
     * @param url
     * @param headers
     * @param json
     * @return
     */
    public Request buildRequest(String url, Map<String, String> headers, String json) {
        //1构造RequestBody
        RequestBody body = RequestBody.create(MEDIA_TYPE_JSON, json);
        Request.Builder builder = getRequestBuilder(headers);
        //2 构造Request
        Request request = builder.url(url).post(body).build();
        return request;
    }

    /**
     * buildRequest by map
     * @param url
     * @param headers
     * @param bodyParams
     * @return
     */
    public Request buildRequest(String url, Map<String, String> headers, Map<String, String> bodyParams) {
        //1构造RequestBody
        RequestBody body = setRequestBody(bodyParams);
        Request.Builder builder = getRequestBuilder(headers);
        //2 构造Request
        Request request = builder.url(url).post(body).build();
        return request;
    }

    /**
     * post的请求参数,构造RequestBody
     *
     * @param bodyParams
     * @return
     */
    private RequestBody setRequestBody(Map<String, String> bodyParams) {
        RequestBody body = null;
        okhttp3.FormBody.Builder formBuilder = new okhttp3.FormBody.Builder();
        if (bodyParams != null) {
            for (Map.Entry<String, String> item : bodyParams.entrySet()) {
                formBuilder.add(item.getKey(), item.getValue());
            }
        }
        body = formBuilder.build();
        return body;
    }
}

猜你喜欢

转载自blog.csdn.net/zhuyu19911016520/article/details/126299058