Java中遇HTTP 400错误时如何读取响应体?
问题:如何读取HTTP 4xx状态码对应的响应体?
我用Java代码调用HTTP POST接口时,响应码200能正常获取InputStream读取响应,但响应码400时,在标记/// error !!!的代码行会抛出异常:
Exception in thread "main" java.io.IOException: Server returned HTTP response code: 400 for URL: ...
at java.base/sun.net.www.protocol.http.HttpURLConnection.getInputStream0(HttpURLConnection.java:1924)
at java.base/sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1520)
at com.test123.Main009.main(Main009.java:41)
请问有没有办法读取4xx状态码对应的响应体?
对应的原代码:
package com.test123; import java.io.InputStream; import java.io.OutputStream; import java.net.HttpURLConnection; import java.net.URL; import java.net.URLConnection; import java.nio.charset.StandardCharsets; import java.util.Base64; public class Main009 { public static void main(String[] args) throws Exception { String username = "xxx"; String password = "yyy"; URL url = new URL("http://host/path"); URLConnection uc = url.openConnection(); HttpURLConnection http = (HttpURLConnection)uc; http.setRequestMethod("POST"); // PUT is another valid option http.setDoOutput(true); http.setDoInput(true); byte[] request = "{ id: \"test2\" }".getBytes(StandardCharsets.UTF_8); int length = request.length; http.setFixedLengthStreamingMode(length); String userpass = username + ":" + password; String basicAuth = "Basic " + new String(Base64.getEncoder().encode(userpass.getBytes())); http.setRequestProperty ("Authorization", basicAuth); http.setRequestProperty("Content-Type", "application/json; charset=UTF-8"); // http.connect(); try(OutputStream os = http.getOutputStream()) { os.write(request); os.flush(); InputStream in = http.getInputStream(); /// error !!! System.out.println(in); } } }
解决方案
当HTTP响应码为4xx或5xx时,HttpURLConnection.getInputStream()会直接抛出异常,此时需要调用HttpURLConnection.getErrorStream()来读取错误响应体。核心处理逻辑如下:
- 先获取响应码,根据响应码区间判断使用正常输入流还是错误流
- 统一读取流内容,完成资源释放
修改后的代码示例:
package com.test123; import java.io.BufferedReader; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.net.HttpURLConnection; import java.net.URL; import java.nio.charset.StandardCharsets; import java.util.Base64; public class Main009 { public static void main(String[] args) throws Exception { String username = "xxx"; String password = "yyy"; URL url = new URL("http://host/path"); HttpURLConnection http = (HttpURLConnection) url.openConnection(); http.setRequestMethod("POST"); http.setDoOutput(true); http.setDoInput(true); byte[] request = "{ id: \"test2\" }".getBytes(StandardCharsets.UTF_8); int length = request.length; http.setFixedLengthStreamingMode(length); String userpass = username + ":" + password; String basicAuth = "Basic " + new String(Base64.getEncoder().encode(userpass.getBytes())); http.setRequestProperty("Authorization", basicAuth); http.setRequestProperty("Content-Type", "application/json; charset=UTF-8"); // 发送请求 try(OutputStream os = http.getOutputStream()) { os.write(request); os.flush(); } // 根据响应码选择对应输入流 int responseCode = http.getResponseCode(); InputStream inputStream = (responseCode >= 200 && responseCode < 300) ? http.getInputStream() : http.getErrorStream(); // 读取并打印响应内容 try(BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8))) { StringBuilder response = new StringBuilder(); String line; while ((line = reader.readLine()) != null) { response.append(line); } System.out.println("响应码: " + responseCode); System.out.println("响应内容: " + response.toString()); } finally { http.disconnect(); } } }
关键说明
- 流的选择时机:必须先完成请求发送(写入输出流并关闭/flush),再获取响应码和对应流,否则会出现连接状态异常。
- 错误流的有效性:
getErrorStream()仅在响应码为错误状态(4xx/5xx)时返回有效流,成功状态下调用会返回null。 - 资源释放:务必通过
try-with-resources或手动关闭流,最后调用disconnect()释放HTTP连接资源。
内容的提问来源于stack exchange,提问作者peter.petrov
相关产品推荐
相关产品推荐

