Java 创建&;正在关闭ServletContextListener vs筛选器中的数据库连接

Java 创建&;正在关闭ServletContextListener vs筛选器中的数据库连接,java,tomcat,servlets,jdbc,connection-pooling,Java,Tomcat,Servlets,Jdbc,Connection Pooling,我正在用Java在一个web项目中创建一个数据库连接。然而,有一件事我感到困惑 创建数据库连接并关闭连接的最佳方法是什么?使用过滤器或ServletContextListener 在servlet中执行数据库操作后,JDBC连接将如何关闭?我需要手动关闭连接吗?我应该在哪里关闭连接?我确实添加了contextdestromed方法来关闭连接,但我认为它只有在Tomcat服务器停止时才能工作 或者,是否需要在过滤器中打开和关闭连接 以下是我工作的步骤 使用标记在Tomcat服务器的Context.

我正在用Java在一个web项目中创建一个数据库连接。然而,有一件事我感到困惑

  • 创建数据库连接并关闭连接的最佳方法是什么?使用
    过滤器
    ServletContextListener
  • 在servlet中执行数据库操作后,JDBC连接将如何关闭?我需要手动关闭连接吗?我应该在哪里关闭连接?我确实添加了
    contextdestromed
    方法来关闭连接,但我认为它只有在Tomcat服务器停止时才能工作
  • 或者,是否需要在
    过滤器中打开和关闭连接
  • 以下是我工作的步骤

  • 使用
    标记在Tomcat服务器的
    Context.xml
    文件中创建
    数据源
  • 使用
    标记引用
    web.xml
    中的资源
  • ServletContextListener的
    contextInitialized
    中创建连接
  • 在servlet的
    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的例子