用HttpURLConnection进行Post请求应答结果为null的原因分析

当使用HttpURLConnection进行Post请求时,发现应答结果为null。问题源于BufferedReader的readLine方法被错误地执行了两次,导致应答内容丢失。通过排除法和调试,发现循环中sb.append(bf.readLine())的错误写法,应改为while ((line = bf.readLine()) != null) { sb.append(line); },修正后请求能正常获取到响应内容。

笔者最近在项目中遇到了用HttpURLConnection请求第三方接口,但返回值始终为空的问题。项目中几个大拿费了好长时间,才找到了问题的原因,原来是BufferedReader的readline方法被错误执行了两次导致的。结果虽然很简单,但找原因颇费了一番功夫。现在分享一下。

(1)问题的现象

HttpURLConnection请求第三方接口,但返回值始终为空

(2)问题可能原因

第一,第三方接口有问题。不能正确处理请求。

第二,项目用的框架存在问题,请求对第三方接口或者第三方接口返回的内容被屏蔽了。

第三,项目本身代码的问题。

(3)排除方法

第一,首先排除接口的问题,因为通过chrome的一些插件如Advanced rest client调用第三方接口,能正常返回结果。

第二,排除了项目框架的问题。因为不用项目框架,单独写个main方法,将项目中的代码粘过来,进行调用还是得不到结果。

第三,项目本身代码的问题。前两者都不是,那么一定就是代码的原因了。但是开发环境无法连接第三方接口,只有客户的运行环境中才能连接。那如何定位呢?最后灵光一闪,还是直接访问一个web页面吧。于是将url修改了一下,进行了debug。发现HttpURLConnection请求有应答。奇了怪了。可是再细心一看,应答内容和web页面内容又有所不同,应答内容明显变少了。这样问题就很快能定位了,一定是解析请求结果出了问题。原来在循环中br.readLine被执行了多次。

while (bf.readLine() != null) {
    sb.append(bf.readLine());//错误写法,因为while中已经readLine了,之后游标跳到了下一行,此时读取的是下一行
}

//正确写法

while ((line = bf.readLine()) != null) {
    sb.append(line);
}

使用HttpURLConnection进行post请求的步骤如下: 1. 创建一个URL对象,指定请求的URL地址。 2. 调用URL对象的openConnection方法获HttpURLConnection对象。 3. 设置请求的方法为POST,设置请求头信息,设置超时时间等。 4. 构建请求参数,将请求参数写入输出流中。 5. 调用HttpURLConnection对象的getInputStream方法获服务器返回的输入流。 6. 读输入流中的数据,将数据转换成字符串格式。 7. 关闭输入流和输出流,断开与服务器的连接。 下面是使用HttpURLConnection进行post请求的示例代码: ``` public static String doPost(String urlStr, Map<String, String> params) throws Exception { // 1. 创建一个URL对象 URL url = new URL(urlStr); // 2. 获HttpURLConnection对象 HttpURLConnection conn = (HttpURLConnection) url.openConnection(); // 3. 设置请求的方法为POST conn.setRequestMethod("POST"); // 4. 设置请求头信息 conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); conn.setRequestProperty("Connection", "Keep-Alive"); conn.setRequestProperty("Charset", "UTF-8"); // 5. 设置超时时间 conn.setConnectTimeout(5000); conn.setReadTimeout(5000); // 6. 构建请求参数 StringBuilder sb = new StringBuilder(); for (Map.Entry<String, String> entry : params.entrySet()) { sb.append(entry.getKey()).append("=").append(URLEncoder.encode(entry.getValue(), "UTF-8")).append("&"); } sb.deleteCharAt(sb.length() - 1); String postData = sb.toString(); // 7. 将请求参数写入输出流中 conn.setDoOutput(true); OutputStream outputStream = conn.getOutputStream(); outputStream.write(postData.getBytes()); outputStream.flush(); outputStream.close(); // 8. 获服务器返回的输入流 InputStream inputStream = conn.getInputStream(); BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, "UTF-8")); // 9. 读输入流中的数据,将数据转换成字符串格式 StringBuilder response = new StringBuilder(); String line; while ((line = reader.readLine()) != null) { response.append(line); } reader.close(); inputStream.close(); // 10. 关闭输入流和输出流,断开与服务器的连接 conn.disconnect(); // 11. 返回服务器返回的数据 return response.toString(); } ``` 在调用该方法时,需要传入请求的URL地址和请求参数,请求参数以Map的形式传入。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值