直入主题,工具类来!
public class IOUtil {
private static final ATSLogger logger = ATSLoggerFactory.getLogger(IOUtil.class);
/**
* close Closeable
* @param closeables the closeables
*/
public static void close(AutoCloseable... closeables) {
if (CollectionUtils.isNotEmpty(closeables)) {
for (AutoCloseable closeable : closeables) {
close(closeable);
}
}
}
/**
* close Closeable
* @param closeable the closeable
*/
public static void close(AutoCloseable closeable) {
if (closeable != null) {
try {
closeable.close();
} catch (Exception e) {
logger.error(e.getMessage(), e);
}
}
}
}
使用案例:
protected TableRecords buildBeforeImage(TableMeta tableMeta, List<List<Object>> paramAppenderList, String selectSQL) throws SQLException {
TableRecords beforeImage;
PreparedStatement pstmt = null;
Statement stmt = null;
ResultSet rs = null;
try {
if (paramAppenderList.isEmpty()) {
stmt = getStatementProxy().getConnection().createStatement();
rs = stmt.executeQuery(selectSQL);
} else {
pstmt = getStatementProxy().getConnection().prepareStatement(selectSQL);
fillPreparedStatement(paramAppenderList, pstmt);
rs = pstmt.executeQuery();
}
beforeImage = TableRecords.buildTableRecordsFromResultSet(tableMeta, rs);
} finally {
IOUtil.close(rs, stmt, pstmt);
}
return beforeImage;
}
Java 类 —— AutoCloseable
AutoCloseable 接口
概述:
AutoCloseable 是从 jdk7 开始存在的接口,位于 java.lang 包中,用于自动执行资源关闭操作。AutoCloseable 接口定义了一个名为 close() 的方法,用于关闭资源。通常在实现 AutoCloseable 接口的类中重写 close() 方法来实现自定义关闭资源的逻辑,例如关闭文件、释放网络连接等。
AutoCloseable 接口是为了配合 Java 7 引入的 try-with-resources(try-catch-finally) 语句而设计的。使用 try-with-resources 语句可以自动关闭实现了 AutoCloseable 接口的资源,无需显式调用 close() 方法,确保资源在使用完毕后被正确关闭,提高代码的可靠性和安全性。
示例
1、在 try-catch-finally 中使用 AutoCloseable 来自动关闭资源:
自定义类实现 AutoCloseable 并重写 close() 方法:
public class StreamExample implements AutoCloseable {
private BufferedReader reader;
public StreamExample(String filePath) throws IOException {
reader = new BufferedReader(new FileReader(filePath));
}
public String readLine() throws IOException {
return reader.readLine();
}
/**
* 重写 close() 方法,自定义关闭资源逻辑
* @throws IOException
*/
@Override
public void close() throws IOException {
reader.close();
}
}
在 try-catch-finally 中的使用:
public class BaseTest {
public static void main(String[] args) {
// 在 try() 中使用自定义对象,在执行完 try 逻辑后会自动调用 close() 方法关闭资源。
// 这样无需在 catch 或 finally 中编写关闭资源的逻辑了。
try (StreamExample example = new StreamExample("file.txt")) {
String line = example.readLine();
while (line != null) {
System.out.println(line);
line = example.readLine();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
2、不一定用来关闭资源,可以扩展为其它使用场景:
比如在 for 循环语句中,遍历每一个元素时,为每一个元素处理日志设置不同的 traceId,方便日志定位跟踪。
@Slf4j
public class TraceExample implements AutoCloseable {
/**
* 进入循环之前的traceId
*/
private String beforeTraceId;
public TraceExample(String beforeTraceId) {
try {
this.beforeTraceId = beforeTraceId;
// 处理不同集合元素使用不同的 traceId,方便定位日志
String newTraceId = UUID.randomUUID().toString().replaceAll("-", "");
MDC.put("traceId", newTraceId);
} catch (Exception e) {
log.error("TraceExample init error", e);
}
}
@Override
public void close() {
try {
// 集合处理完后恢复遍历集合之前的 traceId
MDC.put("traceId", this.beforeTraceId);
} catch (Exception e) {
log.error("TraceExample init error", e);
}
}
}
结合 try-catch-finally 在循环语句中使用:
public class BaseTest {
public static void main(String[] args) {
List<String> listData = Arrays.asList("1","2", "3");
for (int i = 0; i < listData.size(); i++) {
// 在处理元素之前设置新的 traceId,元素处理完后再恢复原 traceId。
try (TraceExample ignored = new TraceExample("beforeTraceId")) {
System.out.println("处理元素:" + listData.get(i));
System.out.println("每个元素处理过程中,新的traceId:" + MDC.get("traceId"));
} catch (Exception e) {
throw e;
}
System.out.println("原来的 traceId:" + MDC.get("traceId"));
}
}
}