在服务端返回 2XX 以外的 HTTP 响应码时,HttpURLConnection 该怎样拿到 response body?

和 webservice 供应商联调 saop 接口时遇到一个问题:服务商所有业务逻辑错误 (包括用户名密码、逻辑校验、请求数据为空等等) 都返回 HTTP 状态码 500 而不是状态码 200,同时错误码及详情在返回 body 中给出。

    conn.setDoInput(true);
    conn.setUseCaches(false);
    conn.setDoOutput(true);
    conn.setRequestMethod("POST");
    conn.setConnectTimeout(Integer.valueOf(wsConnectTimeout));
    conn.setReadTimeout(Integer.valueOf(wsRequestTimeout));
    conn.setRequestProperty("Content-Type", "text/xml;charset=utf-8");
    conn.setRequestProperty("Content-Length", String.valueOf(message.length()));
    conn.setRequestProperty("SOAPAction", wsURL);
    OutputStream os = conn.getOutputStream();
    OutputStreamWriter writer = new OutputStreamWriter(os, "utf-8");
    writer.write(message);
    writer.flush();
    writer.close();
    reader = new BufferedReader(new InputStreamReader(conn.getInputStream(), "utf-8"));

上述对接代码在执行到最后一行时会抛以下异常:

java.io.IOException: Server returned HTTP response code: 500 for URL: https://gpm-test.defonds.com/rrc/soap/v1 at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1626) at sun.net.www.protocol.https.HttpsURLConnectionImpl.getInputStream(HttpsURLConnectionImpl.java:254) at com.defonds.als.server.tools.interfaces.standard.gpm.WSClientGPMManagerImpl.gpmCostRateWebservice(WSClientGPMManagerImpl.java:1376)

异常当然容易捕捉,但是服务商返回的错误详细错误原因就丢失了。
那么怎么样才可以从 response body 中拿到错误详细信息呢?用 onn.getInputStream() 已经抛错了,再用还是 500。
当状态码不是 2XX 时,要用 getErrorStream() 来读取响应体里的内容,在捕捉到 500 IO 异常之后进行以下处理:

try {
    // Since webservice returns 500 for any logic error, we get their error message from the error stream
    if (500 == conn.getResponseCode()) {
        reader = new BufferedReader(new InputStreamReader(conn.getErrorStream(), "utf-8"));
        String line = null;
        while ((line = reader.readLine()) != null) {
            result += line;
        }
        reader.close();
        dealWith500LogicError(result, errorMsg);
    }
}catch (Exception e2) {
    logger.logError(e2.toString());
}   

dealWith500LogicError 是负责错误文本解析的方法。
参考资料
Class HttpURLConnection
How to get response body using HttpURLConnection, when code other than 2xx is returned?

posted @ 2018-09-03 17:41  Defonds  阅读(55)  评论(0编辑  收藏  举报