java使用OkHttp

在做网络编程时,很多程序猿都会使用Apache的HttpClient,也有很多大佬自己封装HttpURLConnection,但是笔者认为最强的,还是大名鼎鼎的OkHttp。

源码地址:https://github.com/square/okhttp

使用方法:参照这位老铁的博客,写的非常详细。

https://blog.csdn.net/tanga842428/article/details/78713089

客户端使用可以使用单例模式:
https://blog.csdn.net/weixin_40281743/article/details/85330193

注意一点:maven导入依赖时,建议排除安卓的依赖。

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

            <exclusions>
                <exclusion>
                    <groupId>com.google.android</groupId>
                    <artifactId>android</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

另外:设置超时与超时异常处理:
https://blog.csdn.net/do168/article/details/51848895

okhttp使用完后需要关闭流,释放资源吗?
https://juejin.im/post/5a524eef518825732c536025

OKHttp官方推荐使用单例模式创建client,简单的封装一个工具类


public class HttpUtil {

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

    private static OkHttpClient client;

    private static final String DEFAULT_MEDIA_TYPE = "application/json; charset=utf-8";

    private static final int CONNECT_TIMEOUT = 5;

    private static final int READ_TIMEOUT = 7;

    private static final String GET = "GET";

    private static final String POST = "POST";

    /**
     * 单例模式  获取类实例
     *
     * @return client
     */
    private static OkHttpClient getInstance() {
        if (client == null) {
            synchronized (OkHttpClient.class) {
                if (client == null) {
                    client = new OkHttpClient.Builder()
                            .connectTimeout(CONNECT_TIMEOUT, TimeUnit.SECONDS)
                            .readTimeout(READ_TIMEOUT, TimeUnit.SECONDS)
                            .build();
                }
            }
        }
        return client;
    }

    public static String doGet(String url, String callMethod) throws HttpStatusException {

        try {
            long startTime = System.currentTimeMillis();
            addRequestLog(GET, callMethod, url, null, null);

            Request request = new Request.Builder().url(url).build();
            // 创建一个请求
            Response response = getInstance().newCall(request).execute();
            int httpCode = response.code();
            String result;
            ResponseBody body = response.body();
            if (body != null) {
                result = body.string();
                addResponseLog(httpCode, result, startTime);
            } else {
                response.close();
                throw new RuntimeException("exception in OkHttpUtil,response body is null");
            }
            return handleHttpResponse(httpCode, result);
        } catch (Exception ex) {
            handleHttpThrowable(ex, url);
            return StringUtils.EMPTY;
        }
    }


    public static String doPost(String url, String postBody, String mediaType, String callMethod) throws HttpStatusException {
        try {
            long startTime = System.currentTimeMillis();
            addRequestLog(POST, callMethod, url, postBody, null);

            MediaType createMediaType = MediaType.parse(mediaType == null ? DEFAULT_MEDIA_TYPE : mediaType);
            Request request = new Request.Builder()
                    .url(url)
                    .post(RequestBody.create(createMediaType, postBody))
                    .build();

            Response response = getInstance().newCall(request).execute();
            int httpCode = response.code();
            String result;
            ResponseBody body = response.body();
            if (body != null) {
                result = body.string();
                addResponseLog(httpCode, result, startTime);
            } else {
                response.close();
                throw new IOException("exception in OkHttpUtil,response body is null");
            }
            return handleHttpResponse(httpCode, result);
        } catch (Exception ex) {
            handleHttpThrowable(ex, url);
            return StringUtils.EMPTY;
        }
    }

    public static String doPost(String url, Map<String, String> parameterMap, String callMethod) throws HttpStatusException {
        try {
            long startTime = System.currentTimeMillis();
            List<String> parameterList = new ArrayList<>();
            FormBody.Builder builder = new FormBody.Builder();
            if (parameterMap.size() > 0) {
                for (Map.Entry<String, String> entry : parameterMap.entrySet()) {
                    String parameterName = entry.getKey();
                    String value = entry.getValue();
                    builder.add(parameterName, value);
                    parameterList.add(parameterName + ":" + value);
                }
            }

            addRequestLog(POST, callMethod, url, null, Arrays.toString(parameterList.toArray()));

            FormBody formBody = builder.build();
            Request request = new Request.Builder()
                    .url(url)
                    .post(formBody)
                    .build();

            Response response = getInstance().newCall(request).execute();
            String result;
            int httpCode = response.code();
            ResponseBody body = response.body();
            if (body != null) {
                result = body.string();
                addResponseLog(httpCode, result, startTime);
            } else {
                response.close();
                throw new IOException("exception in OkHttpUtil,response body is null");
            }
            return handleHttpResponse(httpCode, result);

        } catch (Exception ex) {
            handleHttpThrowable(ex, url);
            return StringUtils.EMPTY;
        }
    }


    private static void addRequestLog(String method, String callMethod, String url, String body, String formParam) {
        logger.info("===========================request begin================================================");
        logger.info("URI          : {}", url);
        logger.info("Method       : {}", method);
        if (StringUtils.isNotBlank(body)) {
            logger.info("Request body : {}", body);
        }
        if (StringUtils.isNotBlank(formParam)) {
            logger.info("Request param: {}", formParam);
        }
        logger.info("---------------------------request end--------------------------------------------------");
    }

    private static void addResponseLog(int httpCode, String result, long startTime) {
        long endTime = System.currentTimeMillis();
        logger.info("Status       : {}", httpCode);
        logger.info("Response     : {}", result);
        logger.info("Time         : {} ms", endTime - startTime);
        logger.info("===========================response end================================================");
    }

    private static String handleHttpResponse(int httpCode, String result) throws HttpStatusException {
        if (httpCode == HttpStatus.OK.value()) {
            return result;
        }
        HttpStatus httpStatus = HttpStatus.valueOf(httpCode);
        throw new HttpStatusException(httpStatus);
    }

    private static void handleHttpThrowable(Exception ex, String url) throws HttpStatusException {
        if (ex instanceof HttpStatusException) {
            throw (HttpStatusException) ex;
        }
        logger.error("OkHttp error url: " + url, ex);
        if (ex instanceof SocketTimeoutException) {
            throw new RuntimeException("request time out of OkHttp when do url:" + url);
        }
        throw new RuntimeException(ex);
    }

}






public class HttpStatusException extends Exception {

    private HttpStatus httpStatus;


    private String result;

    public HttpStatusException(HttpStatus httpStatus) {
        this.httpStatus = httpStatus;
    }

    public HttpStatusException(HttpStatus httpStatus, String result) {
        this.httpStatus = httpStatus;

    }

    public HttpStatus getHttpStatus() {
        return httpStatus;
    }

    public String getResult() {
        return result;
    }
}

public class JsonUtil {

    private JsonUtil() {
    }

    /**
     * 避免指令重排序导致拿到半初始化的对象,保证线程可见性
     */
    private static volatile Gson gson;

    private static Gson getGson() {
        if (gson == null) {
            synchronized (JsonUtil.class) {
                if (gson == null) {
                    gson = new GsonBuilder().setDateFormat("yyyy-MM-dd HH:mm:ss").create();
                }
            }
        }
        return gson;
    }

    public static <T> String toJson(T object) {
        return getGson().toJson(object);
    }


    public static <T> T fromJson(String json, Type type) {
        return getGson().fromJson(json, type);
    }

    public static <T> T fromJson(String json, Class<T> clazz) {
        return getGson().fromJson(json, clazz);
    }


访问https

如果遇到:

java.lang.Exception: sun.security.validator.ValidatorException: PKIX path building failed: 
sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

这个异常是由于您在使用OkHttp库时遇到了证书验证问题导致的。

在HTTPS通信中,服务器会使用SSL证书来验证其身份。客户端(okhttputil)需要验证服务器的证书是否有效,以确保您正在与合法的服务器进行通信,而不是中间人攻击者。

验证失败,可能有以下几个原因:

  • 证书链问题:服务器证书可能没有正确设置整个证书链,或者中间证书(Intermediate Certificate)缺失。客户端需要完整的证书链才能验证服务器的证书。

  • 证书过期:服务器证书的有效期已过,客户端不再信任过期的证书。

  • 自签名证书:如果服务器使用自签名证书而不是受信任的公共CA(证书颁发机构)签署的证书,客户端可能会拒绝验证。

为了解决这个问题,有几种方法可以尝试:

  • 信任所有证书(不推荐):这不是一个安全的解决方案,但可以在测试或临时情况下使用。通过OkHttp配置一个信任所有证书的TrustManager,但请不要在生产环境中使用该方法,因为它会绕过证书验证,存在安全风险。
  private static final class ClientHolder {
        static final OkHttpClient client = new OkHttpClient.Builder()
                .sslSocketFactory(getUnsafeSSLSocketFactory(), getUnsafeTrustManager())
                .connectTimeout(CONNECT_TIMEOUT, TimeUnit.SECONDS)
                .readTimeout(READ_TIMEOUT, TimeUnit.SECONDS)
                .build();
    }

    private static SSLSocketFactory getUnsafeSSLSocketFactory() {
        try {
            SSLContext sslContext = SSLContext.getInstance("TLS");
            sslContext.init(null, new X509TrustManager[]{getUnsafeTrustManager()}, new SecureRandom());
            return sslContext.getSocketFactory();
        } catch (Exception e) {
            throw new RuntimeException("Failed to create unsafe SSLSocketFactory", e);
        }
    }

    private static X509TrustManager getUnsafeTrustManager() {
        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];
            }
        };
    }
  • 添加缺失的中间证书:如果服务器证书缺少中间证书,将缺失的中间证书添加到服务器配置中,以便客户端能够正确验证证书链。

  • 使用受信任的证书:确保服务器证书来自受信任的CA,如果是公共网站,一般情况下应该是这样。

  • 自定义信任策略:实现自己的TrustManager来验证服务器证书,可以在其中定义您自己的验证逻辑,但请谨慎使用,确保安全性。

好的,以下是使用 OkHttp3 发起 HTTP/2.0 POST 请求的 Java 代码: ```java import okhttp3.*; import java.io.IOException; public class Http2PostRequestExample { public static void main(String[] args) throws IOException { OkHttpClient client = new OkHttpClient(); // 构建 HTTP/2.0 的请求 Request request = new Request.Builder() .url("https://example.com/api") .post(RequestBody.create(MediaType.parse("application/json"), "{\"key\":\"value\"}")) .build(); // 发送请求 Response response = client.newCall(request).execute(); // 处理响应 if (response.isSuccessful()) { System.out.println(response.body().string()); } else { System.err.println("Unexpected response code: " + response); } } } ``` 这个例子中,我们使用 OkHttp3 的 `OkHttpClient` 类来创建 HTTP 客户端,然后构建一个 HTTP/2.0 的 POST 请求。在 `post()` 方法中,我们使用 `RequestBody.create()` 方法来创建一个请求体,并指定它的 MIME 类型为 `application/json`。最后,我们使用 `client.newCall(request).execute()` 方法来发送请求,并使用 `response.body().string()` 方法来获取响应内容。 需要注意的是,如果你要使用 HTTP/2.0 协议,你需要确保你的服务器端已经支持 HTTP/2.0。另外,OkHttp3 默认情况下会自动选择最佳的协议版本,如果你想强制使用 HTTP/2.0,可以在创建 `OkHttpClient` 对象时指定 `protocols()` 方法,如下所示: ```java OkHttpClient client = new OkHttpClient.Builder() .protocols(Arrays.asList(Protocol.HTTP_2, Protocol.HTTP_1_1)) .build(); ```
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值