Java 创建&;正在关闭ServletContextListener vs筛选器中的数据库连接
我正在用Java在一个web项目中创建一个数据库连接。然而,有一件事我感到困惑Java 创建&;正在关闭ServletContextListener vs筛选器中的数据库连接,java,tomcat,servlets,jdbc,connection-pooling,Java,Tomcat,Servlets,Jdbc,Connection Pooling,我正在用Java在一个web项目中创建一个数据库连接。然而,有一件事我感到困惑 创建数据库连接并关闭连接的最佳方法是什么?使用过滤器或ServletContextListener 在servlet中执行数据库操作后,JDBC连接将如何关闭?我需要手动关闭连接吗?我应该在哪里关闭连接?我确实添加了contextdestromed方法来关闭连接,但我认为它只有在Tomcat服务器停止时才能工作 或者,是否需要在过滤器中打开和关闭连接 以下是我工作的步骤 使用标记在Tomcat服务器的Context.
过滤器
或ServletContextListener
contextdestromed
方法来关闭连接,但我认为它只有在Tomcat服务器停止时才能工作过滤器中打开和关闭连接
标记在Tomcat服务器的Context.xml
文件中创建数据源
标记引用web.xml
中的资源ServletContextListener的contextInitialized
中创建连接
doPost
或doGet
方法中执行数据库操作contextInitialized
方法:
@Override
public void contextInitialized(ServletContextEvent event) {
System.out.println("START CONNECTION");
try {
Context contextEnvironment = (Context) new InitialContext().lookup("java:comp/env/");
DataSource ds = (DataSource) contextEnvironment.lookup("jdbc/lunaruniversity");
try {
Connection con = ds.getConnection();
ServletContext context = event.getServletContext();
context.setAttribute("dbConnection", con);
} catch (SQLException e) {
e.printStackTrace();
}
} catch (NamingException e) {
e.printStackTrace();
}
}
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
Connection con = (Connection) getServletContext().getAttribute("dbConnection");
String saveStudent = request.getParameter("saveStudent");
String insertSQL = "INSERT INTO STUDENT (FNAME, LNAME, EMAIL, PHONE, STATE, ZIPCODE) VALUES(?,?,?,?,?,?)";
String fName = request.getParameter("fName");
String lName = request.getParameter("lName");
String email = request.getParameter("email");
String phone = request.getParameter("phone");
String state = request.getParameter("state");
String zipCode = request.getParameter("zipCode");
try {
java.sql.PreparedStatement ps = con.prepareStatement(insertSQL);
ps.setString(1, fName);
ps.setString(2, lName);
ps.setString(3, email);
ps.setString(4, phone);
ps.setString(5, state);
ps.setString(6, zipCode);
ps.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
}
}
@Override
public void contextDestroyed(ServletContextEvent event) {
System.out.println("CLOSE CONNECTION");
DataSource ds = (DataSource) event.getServletContext().getAttribute("dbConnection");
try {
if (!ds.getConnection().isClosed()) {
System.out.println("CONNECTION IS CLOSED");
ds.getConnection().close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
servlet的doGet
方法:
@Override
public void contextInitialized(ServletContextEvent event) {
System.out.println("START CONNECTION");
try {
Context contextEnvironment = (Context) new InitialContext().lookup("java:comp/env/");
DataSource ds = (DataSource) contextEnvironment.lookup("jdbc/lunaruniversity");
try {
Connection con = ds.getConnection();
ServletContext context = event.getServletContext();
context.setAttribute("dbConnection", con);
} catch (SQLException e) {
e.printStackTrace();
}
} catch (NamingException e) {
e.printStackTrace();
}
}
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
Connection con = (Connection) getServletContext().getAttribute("dbConnection");
String saveStudent = request.getParameter("saveStudent");
String insertSQL = "INSERT INTO STUDENT (FNAME, LNAME, EMAIL, PHONE, STATE, ZIPCODE) VALUES(?,?,?,?,?,?)";
String fName = request.getParameter("fName");
String lName = request.getParameter("lName");
String email = request.getParameter("email");
String phone = request.getParameter("phone");
String state = request.getParameter("state");
String zipCode = request.getParameter("zipCode");
try {
java.sql.PreparedStatement ps = con.prepareStatement(insertSQL);
ps.setString(1, fName);
ps.setString(2, lName);
ps.setString(3, email);
ps.setString(4, phone);
ps.setString(5, state);
ps.setString(6, zipCode);
ps.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
}
}
@Override
public void contextDestroyed(ServletContextEvent event) {
System.out.println("CLOSE CONNECTION");
DataSource ds = (DataSource) event.getServletContext().getAttribute("dbConnection");
try {
if (!ds.getConnection().isClosed()) {
System.out.println("CONNECTION IS CLOSED");
ds.getConnection().close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
contextdestromed
方法:
@Override
public void contextInitialized(ServletContextEvent event) {
System.out.println("START CONNECTION");
try {
Context contextEnvironment = (Context) new InitialContext().lookup("java:comp/env/");
DataSource ds = (DataSource) contextEnvironment.lookup("jdbc/lunaruniversity");
try {
Connection con = ds.getConnection();
ServletContext context = event.getServletContext();
context.setAttribute("dbConnection", con);
} catch (SQLException e) {
e.printStackTrace();
}
} catch (NamingException e) {
e.printStackTrace();
}
}
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
Connection con = (Connection) getServletContext().getAttribute("dbConnection");
String saveStudent = request.getParameter("saveStudent");
String insertSQL = "INSERT INTO STUDENT (FNAME, LNAME, EMAIL, PHONE, STATE, ZIPCODE) VALUES(?,?,?,?,?,?)";
String fName = request.getParameter("fName");
String lName = request.getParameter("lName");
String email = request.getParameter("email");
String phone = request.getParameter("phone");
String state = request.getParameter("state");
String zipCode = request.getParameter("zipCode");
try {
java.sql.PreparedStatement ps = con.prepareStatement(insertSQL);
ps.setString(1, fName);
ps.setString(2, lName);
ps.setString(3, email);
ps.setString(4, phone);
ps.setString(5, state);
ps.setString(6, zipCode);
ps.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
}
}
@Override
public void contextDestroyed(ServletContextEvent event) {
System.out.println("CLOSE CONNECTION");
DataSource ds = (DataSource) event.getServletContext().getAttribute("dbConnection");
try {
if (!ds.getConnection().isClosed()) {
System.out.println("CONNECTION IS CLOSED");
ds.getConnection().close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
1、2和3:以上均无 当需要启动事务时,可以从数据源获得连接。在参与该事务的所有方法调用中传递该连接。然后提交并关闭连接。使用try with resources确保它始终处于关闭状态,即使出现异常:
protected void doGet(HttpServletRequest request, HttpServletResponse response) {
try (Connection connnection = dataSource.getConnection()) {
// use the connection
connection.commit();
}
}
1、2和3:以上均无 当需要启动事务时,可以从数据源获得连接。在参与该事务的所有方法调用中传递该连接。然后提交并关闭连接。使用try with resources确保它始终处于关闭状态,即使出现异常:
protected void doGet(HttpServletRequest request, HttpServletResponse response) {
try (Connection connnection = dataSource.getConnection()) {
// use the connection
connection.commit();
}
}
在使用池时,不应创建连接。池负责实际创建连接
您不应将打开的连接
放入全局内存中,例如ServletContext
。连接决不能由多个线程同时使用。见“”
因此,对于您尝试执行的操作,请使用,并将连接
存储为请求属性
更好的方法是,在servlet方法中使用try-with-resources块,如中所示,这样您就不会从池中获取连接,除非您的servlet确实需要它。在使用池时,您不应该创建连接。池负责实际创建连接
您不应将打开的连接
放入全局内存中,例如ServletContext
。连接决不能由多个线程同时使用。见“”
因此,对于您尝试执行的操作,请使用,并将连接
存储为请求属性
更好的方法是,在servlet方法中使用try-with-resources块,如中所示,这样您就不会从池中获取连接,除非您的servlet确实需要它。在Web应用中,来自用户的每个http请求都在其自己的线程(或通过线程池)中运行。让所有请求共享一个全局连接对象不是一个好主意,因为一次只有一个线程能够使用它,这将成为应用程序的瓶颈
建议的设置是使用在服务器启动时初始化的连接池(例如C3P0)(通过配置自动或在ServletContextListener中手动)。连接池将根据需要创建和关闭连接。当您收到http请求(servlet的doPost或doGet)时,您只需从池中获取一个连接,并在处理完该请求后将其返回到池中即可
您可以使用ServletFilter自动化该部分。在过滤器中,在调用chain.doFilter()
之前,从池中获取连接并将其存储在请求属性中。调用doFilter()
后,将其返回到池中。在Web应用程序中,来自用户的每个http请求都在其自己的线程(或通过线程池)中运行。让所有请求共享一个全局连接对象不是一个好主意,因为一次只有一个线程能够使用它,这将成为应用程序的瓶颈
建议的设置是使用在服务器启动时初始化的连接池(例如C3P0)(通过配置自动或在ServletContextListener中手动)。连接池将根据需要创建和关闭连接。当您收到http请求(servlet的doPost或doGet)时,您只需从池中获取一个连接,并在处理完该请求后将其返回到池中即可
您可以使用ServletFilter自动化该部分。在过滤器中,在调用chain.doFilter()
之前,从池中获取连接并将其存储在请求属性中。调用doFilter()
后,将其返回到池中。您可以将资源试用放入过滤器中(#3)。这样,如果发生异常,您可以将异常处理代码添加到自动rollback()
,也可以在那里执行标准连接设置逻辑,例如setAutoCommit(false)
。唯一的缺点是连接是从池中获取的,即使对于不需要它的servlet调用也是如此。不过,+1来自我。你有更好的链接,我可以参考吗?谢谢@绿色奶酪与什么有联系?如何使用try-with资源?你试过了吗?我正在寻找一个参考,在那里我可以获得连接池并通过过滤器使用,而我找到的只是从ServletContextListener使用。无论如何谢谢你@greencheese我找不到任何使用ServletContextListener的例子