OkHttp3系列(三)okhttp3-fast-spring-boot-starter

OkHttp3是由Square贡献的HTTP客户端框架,主要用在Andorid中,但是由于其易用的API、强大的功能、请求的快速等特点,也被大量采用在后端开发领域。本系列文章讲述OkHttp3的基本使用、OkHttp3的高级功能以及OkHttp3源码的解析等,请持续关注。


本篇文章是此系列的第三篇。

简介

okhttp3-fast-spring-boot-starter是笔者开发的一个HTTP网络调用库,封装了okhttp3,按照Spring Boot Starter标准开发,可以帮助我们快速的在Spring Boot项目中使用okhttp3。同时okhttp3-fast-spring-boot-starter提供了方便易用的API、好用的辅助功能,让开发人员效率倍增、心情舒畅。

项目已在Github公布,并在Maven中央仓库发布。项目的具体使用方法已在Github中详细介绍,对于想学习okhttp3框架的同学,本项目有很多使用okhttp3的示例,可作为案列参考,想要试用的同学快来吧。

详细介绍

日志拦截器

okhttp3-fast-spring-boot-starter使用okhttp3提供的拦截器功能开发了日志拦截器,用于打印请求过程的详细信息,方便使用人员诊断项目。

/**
 * 日志拦截器
 */
public class LoggingInterceptor implements Interceptor {

    private static final Logger LOGGER = LoggerFactory.getLogger(LoggingInterceptor.class);

    private final Charset UTF8 = Charset.forName("UTF-8");

    @Override
    public Response intercept(Chain chain) throws IOException {
        Request request = chain.request();
        RequestBody requestBody = request.body();
        String sendBody = "";
        if (requestBody != null) {
            Buffer buffer = new Buffer();
            requestBody.writeTo(buffer);
            Charset charset = UTF8;
            MediaType contentType = requestBody.contentType();
            if (contentType != null) {
                charset = contentType.charset(UTF8);
            }
            sendBody = buffer.readString(charset == null? UTF8 : charset);
        }
        LOGGER.debug("\n request method : {} \n request url: {} \n request headers: {} \n request body: {}",
                request.method(), URIUtils.urlDecode(request.url().toString()), request.headers(), sendBody);


        long requestStartNanoTime = System.nanoTime();
        Response response = chain.proceed(request);
        long requestEndNanoTime = System.nanoTime();
        double usedMillsTime = (requestEndNanoTime - requestStartNanoTime) / Math.pow(10, 6);


        ResponseBody responseBody = response.body();
        String receiveBody = "";
        if (responseBody != null) {
            BufferedSource source = responseBody.source();
            source.request(Long.MAX_VALUE);
            Buffer buffer = source.getBuffer();

            Charset charset = UTF8;
            MediaType contentType = responseBody.contentType();
            if (contentType != null) {
                charset = contentType.charset(UTF8);
            }
            receiveBody = buffer.clone().readString(charset == null? UTF8 : charset);
        }

        LOGGER.debug("\n response url: {} \n response time: {} millseconds \n response code: {} \n request headers: {} \n " +
                        "request body: {} \n response headers: {} \n response body: {}",
                URIUtils.urlDecode(response.request().url().toString()), String.format("%.2f", usedMillsTime),
                response.code(), request.headers(), sendBody, response.headers(), receiveBody);

        return response;
    }
}

自动认证机制

okhttp3-fast-spring-boot-starter使用okhttp3提供的认证功能开发了自动认证机制,目前支持对Baisc AuthDigest Auth的认证。

public class AuthAuthenticator implements Authenticator {

    private static final Logger LOGGER = LoggerFactory.getLogger(AuthAuthenticator.class);
    private final Charset UTF8 = Charset.forName("UTF-8");

    @Override
    public Request authenticate(Route route, Response response) throws IOException {
        if (AuthConfig.isStatus()) {
            String responseAuth = response.header("WWW-Authenticate");
            if (responseAuth == null || responseAuth.length() <= 0) {
                return null;
            }
            String authType = WWWAuthParse.authType(responseAuth);
            if ("Basic".equalsIgnoreCase(authType)) {
                if (!StringUtils.isEmpty(AuthConfig.getBasicUsername()) && !StringUtils.isEmpty(AuthConfig.getBasicPassword())) {
                    String basicAuth = Credentials.basic(AuthConfig.getBasicUsername(), AuthConfig.getBasicPassword());
                    return response.request().newBuilder().addHeader("Authorization", basicAuth).build();
                }
                return null;
            } else if ("Digest".equalsIgnoreCase(authType)) {
                if (!StringUtils.isEmpty(AuthConfig.getDigestUsername()) && !StringUtils.isEmpty(AuthConfig.getDigestPassword())) {
                    Map<String, String> digestAuthMap = new HashMap<>();
                    try {
                        digestAuthMap = WWWAuthParse.parseDigestAuthenticateHeader(responseAuth);
                    } catch (Exception e) {
                        LOGGER.error("处理Digest认证,解析Response Header WWW-Authenticate [{}] 出错", responseAuth);
                        return null;
                    }
                    digestAuthMap.put("username", AuthConfig.getDigestUsername());
                    digestAuthMap.put("password", AuthConfig.getDigestPassword());
                    digestAuthMap.put("uri", new URL(response.request().url().toString()).getPath());
                    digestAuthMap.put("method", response.request().method());
                    if (response.request().body() != null) {
                        Buffer buffer = new Buffer();
                        response.request().body().writeTo(buffer);
                        Charset charset = UTF8;
                        MediaType contentType = response.request().body().contentType();
                        if (contentType != null) {
                            charset = contentType.charset(UTF8);
                        }
                        String requestBody = buffer.readString(charset == null? UTF8 : charset);
                        digestAuthMap.put("body", requestBody);
                    } else {
                        digestAuthMap.put("body", "");
                    }

                    String authorization = WWWAuthParse.assembleDigestAuthorization(digestAuthMap);
                    if (!StringUtils.isEmpty(authorization)) {
                        return response.request().newBuilder().addHeader("Authorization", authorization).build();
                    }
                }
                return null;
            } else {
                return null;
            }
        }
        return null;
    }
}

小结

本篇文章介绍了笔者开发的okhttp3-fast-spring-boot-starter框架,介绍了该框架的基本功能。除了上述功能点外,okhttp3-fast-spring-boot-starter还提供了很多其它功能,喜欢该框架的同学可以在Github点击下star,对该框架有想法或者不同意见的同学,可以在本篇文章下评论留言、在Github上提出Issue或者通过笔者在Github首页留下的邮箱地址联系笔者。

posted @ 2020-07-31 15:40  weegee  阅读(1135)  评论(0编辑  收藏  举报