okhttp踩坑

ResponseBody.string()

   平常我们用的客户端http调用工具一般是RestTemplate,HttpClient,okhttp,以前使用过前两者,没咋接触过okhttp,我看公司项目中使用okhttp比较多,于是我这次也用了一下okhttp,果不其然,还是自己踩了一个坑:

   下面是一个okhttp请求的代码块:

...
okhttp3.Request okHttpRequest = new okhttp3.Request.Builder()
        .url(saveUrl)
        .post(requestBody)
        .build();
Call call = okHttpClient.newCall(okHttpRequest);
try {
    okhttp3.Response response = call.execute();
    if (Objects.nonNull(response)) {
        ResponseBody responseBody = response.body();
        if (Objects.nonNull(responseBody)) {
            log.info("responseBody:{}", responseBody.string());
            String responseBodyString = responseBody.string();
            Response resultTmp = JSON.parseObject(responseBodyString, Response.class);
            if (resultTmp.getCode() == ResponseCodeEnum.COMPANY_NOT_EXSIT.getCode()) {
                throw new GlobalException(ResponseCodeEnum.COMPANY_NOT_EXSIT);
            }
        }
    } else {
        log.info("erp-service saveQuesFeedback-请求没有返回数据");
    }
} catch (IOException e) {
    log.error("erp-service-forward saveQuesFeedback-Exception", e);
    throw new GlobalException(ResponseCodeEnum.FAIL);
}
...

   一般在请求http的时候,习惯先打印返回的数据,然后再取值。在调试的时候,每次请求都是返回的成功结果,但是走到后边的code判断逻辑就开始报异常,responseBody:{}都是打印的正常结果,那问题在哪呢,刚开始调试粒度太宽,后边一行一行的来进行调试,发现走到第13行,取到结果是空的,说明responseBody.string()没有获取到,但是日志里面明明打印的有,结果查看了一下源代码:

public abstract class ResponseBody implements Closeable {
    @Nullable
    private Reader reader;

    public ResponseBody() {
    }

    public final String string() throws IOException {
    BufferedSource source = this.source();
    Throwable var2 = null;

    String var4;
    try {
        Charset charset = Util.bomAwareCharset(source, this.charset());
        var4 = source.readString(charset);
    } catch (Throwable var8) {
        var2 = var8;
        throw var8;
    } finally {
        if (source != null) {
            $closeResource(var2, source);
        }

    }

    return var4;
    }
}

   ResponseBody实现了Closeable,然后获取body的内容,finally中closeResource,原来在获取string后会关闭数据流,
所以在第二次就获取不到数据了。
所以在使用response.string()的时候要先取出返回的数据,然后再打印结果:

// 此处responseBody.string 只能获取一次就会关闭,所以要先赋值
String responseBodyString = responseBody.string();
log.info("responseBody:{}", responseBodyString);
原文地址:https://www.cnblogs.com/xuanhaoo/p/14356305.html