我有下面的代码,它使用BasicDataSource,Sql Connection,Statement和ResultSet的静态对象。下面的代码工作正常,但我只想知道使用这些编码实践的安全性。或者我如何优化以下代码,使其变得更稳定,更可靠。
public class Testing {
static BasicDataSource bds = DBConnection.getInstance().getBds();
static Connection con = null;
static PreparedStatement stmt = null;
static ResultSet rs = null;
private void show() {
try {
con = bds.getConnection();
stmt = con.prepareStatement("SELECT * FROM users");
rs = stmt.executeQuery();
if(rs.next()) {
System.out.println(rs.getString("firstname") + " " + rs.getString("lastname"));
}
} catch (SQLException e) {
e.printStackTrace();
}finally {
try {
con.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
private void display() {
try {
con = bds.getConnection();
stmt = con.prepareStatement("SELECT * FROM agent_cities");
rs = stmt.executeQuery();
while(rs.next()) {
System.out.println(rs.getString("city_name"));
}
} catch (SQLException e) {
e.printStackTrace();
}finally {
try {
con.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
private void add() {
try {
con = bds.getConnection();
stmt = con.prepareStatement("UPDATE users SET firstname = 'shsh' WHERE id = 2");
stmt.executeUpdate();
System.out.println("updated successfully");
} catch (SQLException e) {
e.printStackTrace();
}finally {
try {
con.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
Testing t = new Testing();
t.show();
t.display();
t.add();
}
}
提前致谢。分享您的案例,您可以在这些案件中打破代码并质疑其安全性。
更新:仅更新以确保没有人应该使用我在上面的程序中使用的静态字段,因为上面的程序包含在开发服务器上部署时的错误。
在大型系统上使用上面的代码后,我发现了这个bug。一个月前,我对上面的代码没有任何问题,它工作正常,但今天我发现了这个错误。
错误:
点击我的API 6-7次后,它停止在第8次点击时给出响应。我真的不知道为什么,也不知道程序中存在的循环漏洞。但是现在我已经接受了答案,我改变了我的源代码并开始在我的代码中使用try-with资源并删除了静态字段。
但我仍然很想知道我在上面的代码中发现的错误。在7-8 API点击后,它不会给出响应并挂起。请分享您对此的看法。我正在使用apache tomcat 8.5.32服务器。提前致谢。
更好地使用try-with-resources。即使引发了异常,也会在内部返回时自动关闭Connection,Statement和ResultSet。
String sql = "UPDATE users SET firstname = ? WHERE id = ?";
try (Connection con = bds.getConnection();
PreparedStatement stmt = con.prepareStatement()) {
stmt.setString(1, "shsh");
stmt.setLong(2, 2);
stmt.executeUpdate();
System.out.println("updated successfully");
}
String sql = "SELECT city_name FROM agent_cities";
try (Connection con = bds.getConnection();
PreparedStatement stmt = con.prepareStatement()) {
try (ResultSet rs = stmt.executeQuery()) {
while(rs.next()) {
System.out.println(rs.getString("city_name"));
}
}
}
这对垃圾收集更好。防止unnice rs2,rs3。允许多用户并发,就像在服务器应用程序中一样。调用自己查询。 static
更像是全球变量的风格。
如果我们谈论这么小的节目,或多或少都可以。但是没有必要将con,stmt和rs保持为静态变量,它们可以在方法中声明。此外,您需要重写try catch finally块并正确关闭资源:
Connection con = null;
PreparedStatement stmt = null;
ResultSet rs = null;
try {
// your code
} catch (SQLException e) {
e.printStackTrace();
} finally {
try { if (rs != null) rs.close(); } catch (Exception e) {e.printStackTrace();}
try { if (stmt != null) stmt.close(); } catch (Exception e) {e.printStackTrace();}
try { if (conn != null) conn.close(); } catch (Exception e) {e.printStackTrace();}
}
下一步,您可以检查try-with-resources构造以清理此代码。
您应该使用try-with-resources来避免任何类型的连接泄漏。
以下示例从文件中读取第一行。它使用BufferedReader实例从文件中读取数据。 BufferedReader是一个在程序完成后必须关闭的资源:
static String readFirstLineFromFile(String path) throws IOException {
try (BufferedReader br =
new BufferedReader(new FileReader(path))) {
return br.readLine();
}
}