Connection.close()的实现解析

在写JDBC代码时,一般都会用如下的“八股文”的形式:
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
try {
   conn = getConnection();
   pstmt = conn.prepareStatement("select * from booktab");
   rs = pstmt.executeQuery();

   while (rs.next()) {
       // traverse the records
   }

} catch (SQLException e) {
  // handle exception
} finally {
   if (rs != null) { try { rs.close(); } catch (Exception e) { } }
   if (pstmt != null) { try { pstmt.close(); } catch (Exception e) { } }
   if (conn != null) { try { conn.close(); } catch (Exception e) { } }
}

两个注意点:1、将关闭连接代码写到finally块中,即不管是否抛异常都要执行;2、要进行非空判断(如pstmt != null),防止抛NullPointerException异常。

作者学JDBC的时候,也是照着上述范例代码,稍作修改用到自己的程序中,前阵子突发奇想,在关闭中能否只调用Connection.close()方法而不事先调用ResultSet和Statement的close()方法?通过实验(MySQL5.1.14+mysql-connector-java-5.0.5-bin.jar的驱动程序),验证了是可行的。

首先,去掉ResultSet和Statement的close()方法调用,在finally块中只调用Connection.close():
    if (conn != null) { try { conn.close(); } catch (Exception e) { } }
再在eclipse中进行单步跟踪,在上面代码上加一个断点,执行前查看rs和pstmt对象的属性isClosed值为false,执行完conn.close()方法后,rs和pstmt对象的属性isClosed值已经被修改为true,表明已经被关闭。

根据上面的分析,笔者虽然没有去读mysql的jdbc源代码,但猜测在Connection对象中会保存一个Statement对象的列表,并且每个Statement对象也会保存一个ResultSet对象,从而在调用Connection.close()方法时,会递归调用ResultSet.close()和Statement.close()方法,最后再关闭connection。

不知道其它数据库(如SQLServer/DB2/Sybase/PostgreSQL等)的jdbc驱动是否也是这样处理的,猜想应该是一样的。虽然可以省略两行程序,但从代码的可读性以及编程习惯上来说,加上会更好一些,省略了的话,代码的连贯性不好,因而是不推荐的。

### 关于 `HttpURLConnection` 中 `getErrorStream()` 的用法 当通过 `HttpURLConnection` 发送 HTTP 请求并接收到错误响应(HTTP 响应码大于等于 400),可以通过调用 `getErrorStream()` 来获取服务器返回的错误消息或数据。此方法适用于解析来自服务器的 JSON 或 XML 错误响应。 以下是有关如何正确使用 `getErrorStream()` 的说明以及示例代码: #### 使用场景 如果服务器返回了一个错误状态码(如 4xx 或 5xx),则 `getInputStream()` 将抛出异常,而此时应该改用 `getErrorStream()` 获取错误流中的内容[^1]。 #### 示例代码 下面是一个完整的例子展示如何捕获和读取错误流的内容: ```java import java.io.BufferedReader; import java.io.InputStreamReader; import java.net.HttpURLConnection; import java.net.URL; public class HttpExample { public static void main(String[] args) { try { String url = "https://example.com/api"; HttpURLConnection httpConnection = (HttpURLConnection) new URL(url).openConnection(); httpConnection.setRequestMethod("POST"); int responseCode = httpConnection.getResponseCode(); if (responseCode >= 400 && responseCode < 600) { // Error responses BufferedReader reader = new BufferedReader(new InputStreamReader(httpConnection.getErrorStream())); StringBuilder errorMessage = new StringBuilder(); String line; while ((line = reader.readLine()) != null) { errorMessage.append(line); } System.out.println("Error Response: " + errorMessage.toString()); reader.close(); } else { BufferedReader reader = new BufferedReader(new InputStreamReader(httpConnection.getInputStream())); StringBuilder content = new StringBuilder(); String line; while ((line = reader.readLine()) != null) { content.append(line); } System.out.println("Response Content: " + content.toString()); reader.close(); } httpConnection.disconnect(); } catch (Exception e) { e.printStackTrace(); } } } ``` 在此代码片段中,程序会先尝试获取正常输入流 (`getInputStream`);但如果遇到错误,则切换到错误流 (`getErrorStream`) 并打印其内容。 #### 处理注意事项 - **关闭资源**: 不管是从哪个流读取的数据,在完成操作之后都需要确保关闭该流以释放系统资源。 - **编码问题**: 默认情况下,`InputStreamReader` 可能不会自动检测字符集。因此建议显式指定预期使用的字符集,比如 UTF-8。 ```java BufferedReader reader = new BufferedReader( new InputStreamReader(httpConnection.getErrorStream(), StandardCharsets.UTF_8)); ``` 这样可以避免因不同平台默认编码差异而导致乱码现象发生。 #### 总结 对于任何可能失败的服务调用来说,合理利用 `getErrorStream()` 是非常重要的一步,因为它允许客户端理解为什么请求未能成功执行,并据此采取适当措施进行反馈或者重试逻辑设计。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值