JAVA——Okhttp封装工具类

基本概念

OKhttp:一个处理网络请求的开源项目,是安卓端最火热的轻量级框架。 

Maven

        <!--OK HTTP Client-->
        <dependency>
            <groupId>com.squareup.okhttp3</groupId>
            <artifactId>okhttp</artifactId>
            <version>4.8.1</version>
        </dependency>
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-collections4</artifactId>
            <version>4.2</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.7.9</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.9</version>
        </dependency>
        <dependency>
            <groupId>org.jsoup</groupId>
            <artifactId>jsoup</artifactId>
            <version>1.9.2</version>
        </dependency>
        <dependency>
            <groupId>org.bouncycastle</groupId>
            <artifactId>bcprov-jdk15on</artifactId>
            <version>1.56</version>
        </dependency>

解决方案 

HttpClient类 

package io.shentuzhigang.demo.http.okhttp3;

import io.shentuzhigang.demo.http.okhttp3.config.HttpClientConfig;
import okhttp3.*;

import javax.net.ssl.*;
import java.security.SecureRandom;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.concurrent.TimeUnit;

/**
 * @author ShenTuZhiGang
 * @version 1.0.0
 * @date 2020-08-25 15:32
 */
public class HttpClient {

    /**
     * 原始OkHttpClient,全局保持唯一一个,从而保证性能开销
     */
    private OkHttpClient mOkHttpClient = null;

    /**
     * httpClient的配置选项 {@link HttpClientConfig}
     */
    private HttpClientConfig config;

    /**
     * 构造方法
     */
    public HttpClient() {
        this(new HttpClientConfig());
    }

    /**
     * 构造方法
     *
     * @param config {@link HttpClientConfig}
     */
    public HttpClient(HttpClientConfig config) {
        if (config == null) {
            config = new HttpClientConfig();
        }
        this.setConfig(config);
    }

    public void setConfig(HttpClientConfig config) {
        if (config == null) {
            return;
        }
        this.config = config;
        resetHttpClient();
    }

    public HttpClientConfig getConfig() {
        return config;
    }

    /**
     * 重新配置HttpClient
     *
     */
    public synchronized void resetHttpClient() {
        OkHttpClient.Builder builder = new OkHttpClient.Builder()
                //设置超时连接时间
                .connectTimeout(config.getTimeoutConnect(), TimeUnit.MILLISECONDS)
                //设置写入超时时间
                .writeTimeout(config.getTimeoutWrite(), TimeUnit.MILLISECONDS)
                //设置读取超市时间
                .readTimeout(config.getTimeoutRead(), TimeUnit.MILLISECONDS)
                //连接池
                .connectionPool(new ConnectionPool(
                        config.getMaxIdleConnections(),
                        config.getKeepAliveDuration(),
                        config.getKeepAliveTimeUnit()));
        if (config.getInterceptors() != null) {
            for (Interceptor interceptor : config.getInterceptors()) {
                if (interceptor == null) {
                    continue;
                }
                builder.addInterceptor(interceptor);
            }
        }
        if (config.getNetworkInterceptors() != null) {
            for (Interceptor interceptor : config.getNetworkInterceptors()) {
                if (interceptor == null) {
                    continue;
                }
                builder.addNetworkInterceptor(interceptor);
            }
        }
        if (config.getExecutorService() != null) {
            builder.dispatcher(new Dispatcher(config.getExecutorService()));
        }


        TrustManager[] trustAllCerts = new TrustManager[]{
                new X509TrustManager() {
                    @Override
                    public void checkClientTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {

                    }

                    @Override
                    public void checkServerTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {

                    }

                    @Override
                    public X509Certificate[] getAcceptedIssuers() {
                        return new X509Certificate[0];
                    }
                }
        };
        //支持HTTPS请求,跳过证书验证
        builder.sslSocketFactory(createSSLSocketFactory(trustAllCerts), (X509TrustManager) trustAllCerts[0]);
        builder.hostnameVerifier(new HostnameVerifier() {
            @Override
            public boolean verify(String s, SSLSession sslSession) {
                return true;
            }
        });
        mOkHttpClient = builder.build();
    }

    /**
     * 生成安全套接字工厂,用于https请求的证书跳过
     *
     * @return SSLSocketFactory
     */
    private SSLSocketFactory createSSLSocketFactory(TrustManager[] trustManagers) {
        SSLSocketFactory ssfFactory = null;
        try {
            //"SSLv2Hello", "SSLv3", "TLSv1"
            SSLContext sslContext = SSLContext.getInstance("TLSv1.2");
            sslContext.init(null, trustManagers, new SecureRandom());
            ssfFactory = sslContext.getSocketFactory();
        } catch (Exception e) {
        }
        return ssfFactory;
    }


    public synchronized OkHttpClient getOkHttpClient() {
        return mOkHttpClient;
    }

    public synchronized Call newCall(Request request){
        return mOkHttpClient.newCall(request);
    }
}

HttpClient配置类 

package io.shentuzhigang.demo.http.okhttp3.config;


import io.shentuzhigang.demo.http.okhttp3.interceptor.LogInterceptor;
import okhttp3.Interceptor;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.TimeUnit;

/**
 * @author ShenTuZhiGang
 * @version 1.0.0
 * @date 2020-08-25 16:49
 */
public class HttpClientConfig {
    public static final long DEFAULT_CONNECT_TIMEOUT = 10 * 1000;
    public static final long DEFAULT_WRITE_TIMEOUT = 30 * 1000;
    public static final long DEFAULT_READ_TIMEOUT = 30 * 1000;
    /**
     * 默认okhttp最大空闲连接数(5)
     */
    public static final int DEFAULT_MAX_IDLE_CONNECTIONS = 5;
    /**
     * 默认okhttp活动链接存货时间(5分钟)
     */
    public static final long DEFAULT_KEEP_ALIVE_DURATION_MINUTES = 5;
    /**
     * 默认okhttp活动链接存货时间单位, (分钟)
     */
    public static final TimeUnit DEFAULT_KEEP_ALIVE_DURATION_TIME_UNIT = TimeUnit.MINUTES;

    private long timeoutConnect;
    private long timeoutRead;
    private long timeoutWrite;
    private int maxIdleConnections;
    private long keepAliveDuration;
    private TimeUnit keepAliveTimeUnit;
    private List<Interceptor> interceptors;
    private List<Interceptor> networkInterceptors;
    private ExecutorService executorService;

    public HttpClientConfig() {
        this(DEFAULT_MAX_IDLE_CONNECTIONS, DEFAULT_KEEP_ALIVE_DURATION_MINUTES, DEFAULT_KEEP_ALIVE_DURATION_TIME_UNIT);
    }

    public HttpClientConfig(int maxIdleConnections, long keepAliveDuration, TimeUnit keepAliveTimeUnit) {
        this.maxIdleConnections = maxIdleConnections;
        this.keepAliveDuration = keepAliveDuration;
        this.keepAliveTimeUnit = keepAliveTimeUnit;
        this.timeoutConnect = DEFAULT_CONNECT_TIMEOUT;
        this.timeoutRead = DEFAULT_READ_TIMEOUT;
        this.timeoutWrite = DEFAULT_WRITE_TIMEOUT;
        this.interceptors = new ArrayList<>();
        this.interceptors.add(new LogInterceptor());
    }

    public HttpClientConfig setInterceptors(List<Interceptor> interceptors) {
        this.interceptors = interceptors;
        return this;
    }

    public HttpClientConfig addInterceptor(Interceptor interceptor) {
        if (interceptor == null){
            return this;
        }

        if (this.interceptors == null){
            this.interceptors = new ArrayList<>();
        }

        this.interceptors.add(interceptor);
        return this;
    }

    public HttpClientConfig setNetworkInterceptors(List<Interceptor> networkInterceptors) {
        this.networkInterceptors = networkInterceptors;
        return this;
    }

    public HttpClientConfig addNetInterceptor(Interceptor interceptor) {
        if (interceptor == null){
            return this;
        }

        if (this.networkInterceptors == null) {
            this.networkInterceptors = new ArrayList<>();
        }
        this.networkInterceptors.add(interceptor);
        return this;
    }

    public HttpClientConfig setMaxIdleConnections(int maxIdleConnections) {
        this.maxIdleConnections = maxIdleConnections;
        return this;
    }

    public HttpClientConfig setKeepAliveDuration(long keepAliveDuration) {
        this.keepAliveDuration = keepAliveDuration;
        return this;
    }

    public HttpClientConfig setKeepAliveTimeUnit(TimeUnit keepAliveTimeUnit) {
        this.keepAliveTimeUnit = keepAliveTimeUnit;
        return this;
    }

    public HttpClientConfig setExecutorService(ExecutorService executorService) {
        this.executorService = executorService;
        return this;
    }

    public HttpClientConfig setTimeout(long timeoutConnect, long timeoutRead, long timeoutWrite) {
        this.timeoutConnect = timeoutConnect;
        this.timeoutRead = timeoutRead;
        this.timeoutWrite = timeoutWrite;
        return this;
    }

    public long getTimeoutConnect() {
        return timeoutConnect;
    }

    public long getTimeoutRead() {
        return timeoutRead;
    }

    public long getTimeoutWrite() {
        return timeoutWrite;
    }

    public ExecutorService getExecutorService() {
        return executorService;
    }

    public int getMaxIdleConnections() {
        return maxIdleConnections;
    }

    public long getKeepAliveDuration() {
        return keepAliveDuration;
    }

    public TimeUnit getKeepAliveTimeUnit() {
        return keepAliveTimeUnit;
    }

    public List<Interceptor> getInterceptors() {
        return interceptors;
    }

    public List<Interceptor> getNetworkInterceptors() {
        return networkInterceptors;
    }
}

日志拦截器 

package io.shentuzhigang.demo.http.okhttp3.interceptor;

import okhttp3.Interceptor;
import okhttp3.Request;
import okhttp3.Response;
import okio.Buffer;
import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.util.concurrent.TimeUnit;

/**
 * @author ShenTuZhiGang
 * @version 1.0.0
 * @date 2020-08-25 15:33
 */
public class LogInterceptor implements Interceptor {
    private static Logger log = LoggerFactory.getLogger(LogInterceptor.class);
    private String TAG = getClass().getSimpleName();


    @NotNull
    @Override
    public Response intercept(@NotNull Chain chain) throws IOException {
        //获得请求信息,此处如有需要可以添加headers信息
        Request request = chain.request();
        log.trace(TAG, "[request]:" + request.toString());
        log.trace(TAG, "[request-headers]:" + request.headers().toString());
        /* 记录请求耗时 */
        long startNs = System.nanoTime();
        /* 发送请求,获得响应 */
        Response response = chain.proceed(request);

        long tookMs = TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - startNs);
        /* 打印请求耗时 */
        log.debug(TAG, "[耗时]:" + tookMs + "ms");
        /* 使用response获得headers(),可以更新本地Cookie。*/
        log.trace(TAG, "[response-code]:" + response.code());
        log.trace(TAG, "[response-headers]:" + response.headers().toString());
        return response;
    }

    private String readRequestBody(Request oriReq) {
        if (oriReq.body() == null){
            return "";
        }
        Request request = oriReq.newBuilder().build();
        Buffer buffer = new Buffer();
        try {
            request.body().writeTo(buffer);
            return buffer.readUtf8();
        } catch (IOException e) {
            e.printStackTrace();
        }

        return "";
    }
}

OkHTTP封装工具类

package io.shentuzhigang.demo.http.okhttp3.util;

import com.alibaba.fastjson.JSON;
import io.shentuzhigang.demo.http.okhttp3.ContentType;
import io.shentuzhigang.demo.http.okhttp3.HttpClient;
import okhttp3.*;
import org.apache.commons.collections4.MapUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.nio.charset.Charset;
import java.util.Map;
import java.util.Set;

/**
 * @author ShenTuZhiGang
 * @version 1.0.0
 * @date 2020-09-25 20:02
 */
public class HttpRequestUtil {
    private static Logger logger = LoggerFactory.getLogger(HttpRequestUtil.class);

    private static String ENCODING = "UTF-8";

    private HttpClient httpClient = new HttpClient();

    public final static HttpRequestUtil INSTANCE;

    private static final String CONTENT_TYPE = "Content-Type";

    //单例模式
    static {
        INSTANCE = new HttpRequestUtil();
    }
    //构造器私有化,防止new对象
    private HttpRequestUtil()
    {

    }

    public static HttpRequestUtil getInstance()
    {
        return INSTANCE;
    }
    /**
     * Set URI
     * @param url
     * @param params
     */
    private HttpUrl getHttpUrl(String url,
                                  Map<String, String> params) {
        HttpUrl.Builder newBuilder = HttpUrl.parse(url).newBuilder();
        if (MapUtils.isNotEmpty(params)) {
            // Set params
            for (Map.Entry<String, String> stringStringEntry : params.entrySet()) {
                newBuilder.addQueryParameter(stringStringEntry.getKey(), stringStringEntry.getValue());
            }
        }
        return newBuilder.build();
    }
    /**
     * Set Header
     * @param headers 请求头数据
     */
    private Headers getHeaders(Map<String, String> headers){
        if(MapUtils.isNotEmpty(headers)){
            return Headers.of(headers);
        }
        return  new Headers.Builder().build();
    }


    /**
     * Content-Type: application/x-www-from-urlencoded
     *
     * Description: 封装请求参数
     * @param params 参数
     *
     */
    private FormBody getFormBody(Map<String, String> params) {
        FormBody.Builder formBodyBuilder = new FormBody.Builder(Charset.forName(ENCODING));
        // 封装请求参数
        if (MapUtils.isNotEmpty(params)) {
            Set<Map.Entry<String, String>> entrySet = params.entrySet();
            for (Map.Entry<String, String> entry : entrySet) {
                formBodyBuilder.add(entry.getKey(), entry.getValue());
            }
        }
        return  formBodyBuilder.build();
    }

    /**
     * Content-Type: multipart/form-data
     *
     * Description: 封装请求参数
     * @return
     */
    private MultipartBody getMultipartBody(Map<String, Object> params){
        MultipartBody.Builder multipartBodyBuilder = new MultipartBody.Builder();
        return multipartBodyBuilder.build();
    }

    /**
     *
     *
     * @param content
     * @param type
     * @return
     */
    private RequestBody getRawBody(String content,MediaType type){
        return RequestBody.create(content,type);
    }

    /**
     * Content-Type: application/json
     *
     * @param json
     * @return
     */
    private RequestBody getJSONBody(Object json){
        return getRawBody(JSON.toJSONString(json),MediaType.parse(ContentType.JSON.toString()));
    }


    //GET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS, TRACE

    /**
     *
     * @param url
     * @return
     * @throws IOException
     */
    public Response get(String url) throws IOException {
        return get(url,null,null);
    }

    /**
     *
     * @param url
     * @param params
     * @return
     * @throws IOException
     */
    public Response get(String url,Map<String, String> params) throws IOException {
        return get(url,null,params);
    }

    /**
     * get请求,同步方式,获取网络数据,是在主线程中执行的,需要新起线程,将其放到子线程中执行
     *
     * @param url
     * @param headers
     * @param params
     * @return
     * @throws IOException
     */
    public Response get(String url,
                        Map<String, String> headers,
                        Map<String, String> params) throws IOException {

        Request.Builder builder = new Request.Builder()
                .url(getHttpUrl(url,params))
                .headers(getHeaders(headers))
                .get();
        return httpClient
                .newCall(
                        builder
                        .build())
                .execute();
    }

    /**
     *
     *
     * @param url
     * @param headers
     * @param params
     * @param formData
     * @return
     * @throws IOException
     */
    public Response post(String url,
                        Map<String, String> headers,
                        Map<String, String> params,
                        Map<String, String> formData) throws IOException {
        headers.put(CONTENT_TYPE, ContentType.FORM.toString());
        return post(url,headers,params,getFormBody(formData));
    }

    /**
     *
     * @param url
     * @param headers
     * @param params
     * @param multipartData
     * @return
     * @throws IOException
     */
    public Response postMultipart(String url,
                         Map<String, String> headers,
                         Map<String, String> params,
                         Map<String, Object> multipartData) throws IOException {
        headers.put(CONTENT_TYPE, ContentType.MULTIPART.toString());
        return post(url,headers,params,getMultipartBody(multipartData));
    }

    /**
     *
     * @param url
     * @param headers
     * @param params
     * @param json
     * @return
     * @throws IOException
     */
    public Response postJSON(String url,
                         Map<String, String> headers,
                         Map<String, String> params,
                         Object json) throws IOException {
        headers.put(CONTENT_TYPE, ContentType.JSON.toString());
        return post(url,headers,params,getJSONBody(json));
    }

    /**
     * post form表单 请求,同步方式,提交数据,是在主线程中执行的,需要新起线程,将其放到子线程中执行
     *
     * @param url
     * @param headers
     * @param params
     * @param requestBody
     * @return
     * @throws IOException
     */
    private Response post(String url,
                         Map<String, String> headers,
                         Map<String, String> params,
                         RequestBody requestBody) throws IOException {
        Request.Builder builder = new Request.Builder()
                .url(getHttpUrl(url,params))
                .headers(getHeaders(headers))
                .post(requestBody);
        return httpClient.newCall(builder.get().build()).execute();
    }

    /**
     *
     * @param url
     * @param headers
     * @param params
     * @return
     * @throws IOException
     */
    public Response head(String url,
                         Map<String, String> headers,
                         Map<String, String> params) throws IOException {
        Request.Builder builder = new Request.Builder()
                .url(getHttpUrl(url,params))
                .headers(getHeaders(headers))
                .get();
        return httpClient.newCall(builder.build()).execute();
    }

    public Response put(String url,
                        Map<String, String> headers,
                        Map<String, String> params,
                        Map<String, String> formData) throws IOException {
        Request.Builder builder = new Request.Builder()
                .url(getHttpUrl(url,params))
                .headers(getHeaders(headers))
                .put(null);
        return httpClient.newCall(builder.build()).execute();
    }

    public Response patch(String url,
                          Map<String, String> headers,
                          Map<String, String> params,
                          Map<String, String> formData) throws IOException {
        Request.Builder builder = new Request.Builder()
                .url(getHttpUrl(url,params))
                .headers(getHeaders(headers))
                .patch(null);
        return httpClient.newCall(builder.build()).execute();
    }

    public Response delete(String url,
                           Map<String, String> headers,
                           Map<String, String> params,
                           Map<String, String> formData) throws IOException {
        Request.Builder builder = new Request.Builder()
                .url(getHttpUrl(url,params))
                .headers(getHeaders(headers))
                .delete();
        return httpClient.newCall(builder.build()).execute();
    }
}

ContentType类

package io.shentuzhigang.demo.http.okhttp3;

/**
 * @author ShenTuZhiGang
 * @version 1.0.0
 * @date 2020-09-27 22:16
 */
public enum ContentType {

    FORM("application/x-www-from-urlencoded"),
    MULTIPART("multipart/form-data"),
    JSON("application/json");

    private final String value;
    private final static String ENCODING = "utf-8";
    ContentType(String value){
        this.value = value + ";charset=" +ENCODING;
    }
    @Override
    public String toString(){
        return value;
    }
}

测试

package io.shentuzhigang.demo.http.okhttp3;

import io.shentuzhigang.demo.http.okhttp3.util.HttpRequestUtil;
import org.junit.jupiter.api.Test;

import java.io.IOException;

/**
 * @author ShenTuZhiGang
 * @version 1.0.0
 * @date 2020-09-25 22:44
 */
public class MainTest {
    @Test
    public void a() throws IOException {
        System.out.println(HttpRequestUtil.INSTANCE.get("http://www.baidu.com")
                .body().string());
    }
}

参考文章

OkHttp工具类

【记录】form-data与x-www-form-urlencoded的区别

HTTP content-type

 

©️2020 CSDN 皮肤主题: 1024 设计师:上身试试 返回首页