使用JERSEY的MySQL连接池

使用JERSEY的MySQL连接池,mysql,jdbc,jersey,connection-pooling,Mysql,Jdbc,Jersey,Connection Pooling,我正在用Jersey和MySQL开发一个RESTful API 实际上,我正在使用JDBC驱动程序连接数据库,每次我想访问它时,我都会创建一个新的连接。由于这显然是内存泄漏,我开始实现ServletContextClass类,但我不知道在需要获取SQL查询结果时如何调用该方法 以下是我是如何做错的: DbConnection.java 公共类数据库连接{ public Connection getConnection() throws Exception { try {

我正在用Jersey和MySQL开发一个RESTful API

实际上,我正在使用JDBC驱动程序连接数据库,每次我想访问它时,我都会创建一个新的连接。由于这显然是内存泄漏,我开始实现
ServletContextClass
类,但我不知道在需要获取SQL查询结果时如何调用该方法

以下是我是如何做错的:

DbConnection.java 公共类数据库连接{

    public Connection getConnection() throws Exception {
        try {
            String connectionURL = "jdbc:mysql://root:port/path";
            Connection connection = null;
            Class.forName("com.mysql.jdbc.Driver").newInstance();
            connection = DriverManager.getConnection(connectionURL, "root", "password");
            return connection;
        }

        catch (SQLException e) {
            throw e;
        }
    }
}
DbData.java

public ArrayList<Product> getAllProducts(Connection connection) throws Exception {
    ArrayList<Product> productList = new ArrayList<Product>();
    try {
        PreparedStatement ps = connection.prepareStatement("SELECT id, name FROM product");
        ResultSet rs = ps.executeQuery();
        while (rs.next()) {
            Product product = new Product();
            product.setId(rs.getInt("id"));
            product.setName(rs.getString("name"));
            productList.add(product);
        }
        return productList;
    } catch (Exception e) {
            throw e;
    }
}
@GET
@Path("task/{taskId}")
@Consumes(MediaType.APPLICATION_JSON)
public Response getInfos(@PathParam("taskId") int taskId) throws Exception {
    try {
        DbConnection database= new DbConnection();
        Connection connection = database.getConnection();
        Task task = new Task();
        DbData dbData = new DbData();
        task = dbData.getTask(connection, taskId);

        return Response.status(200).entity(task).build();
    } catch (Exception e) {
        throw e;
    }
}
public class ServletContextClass implements ServletContextListener {

    public Connection getConnection() throws Exception {
        try {
            String connectionURL = "jdbc:mysql://root:port/path";
            Connection connection = null;
            Class.forName("com.mysql.jdbc.Driver").newInstance();
            connection = DriverManager.getConnection(connectionURL, "root", "password");
            return connection;
        } catch (SQLException e) {
            throw e;
        }
    }

    public void contextInitialized(ServletContextEvent arg0) {
        System.out.println("ServletContextListener started");
        DbConnection database = new DbConnection();
        try {
            Connection connection = database.getConnection();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void contextDestroyed(ServletContextEvent arg0) {
        System.out.println("ServletContextListener destroyed");
        //con.close ();       
    }

}
下面是我尝试实现新类的地方:

ServletContextClass.java

public ArrayList<Product> getAllProducts(Connection connection) throws Exception {
    ArrayList<Product> productList = new ArrayList<Product>();
    try {
        PreparedStatement ps = connection.prepareStatement("SELECT id, name FROM product");
        ResultSet rs = ps.executeQuery();
        while (rs.next()) {
            Product product = new Product();
            product.setId(rs.getInt("id"));
            product.setName(rs.getString("name"));
            productList.add(product);
        }
        return productList;
    } catch (Exception e) {
            throw e;
    }
}
@GET
@Path("task/{taskId}")
@Consumes(MediaType.APPLICATION_JSON)
public Response getInfos(@PathParam("taskId") int taskId) throws Exception {
    try {
        DbConnection database= new DbConnection();
        Connection connection = database.getConnection();
        Task task = new Task();
        DbData dbData = new DbData();
        task = dbData.getTask(connection, taskId);

        return Response.status(200).entity(task).build();
    } catch (Exception e) {
        throw e;
    }
}
public class ServletContextClass implements ServletContextListener {

    public Connection getConnection() throws Exception {
        try {
            String connectionURL = "jdbc:mysql://root:port/path";
            Connection connection = null;
            Class.forName("com.mysql.jdbc.Driver").newInstance();
            connection = DriverManager.getConnection(connectionURL, "root", "password");
            return connection;
        } catch (SQLException e) {
            throw e;
        }
    }

    public void contextInitialized(ServletContextEvent arg0) {
        System.out.println("ServletContextListener started");
        DbConnection database = new DbConnection();
        try {
            Connection connection = database.getConnection();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void contextDestroyed(ServletContextEvent arg0) {
        System.out.println("ServletContextListener destroyed");
        //con.close ();       
    }

}

但问题是,我不知道下一步该怎么办。有什么帮助吗?谢谢你,你需要将连接变量设置为
ServletContext
属性。另外,我建议你使用
Connection
作为静态类变量,这样你就可以在
contextdestromed
方法中关闭它。 稍后,您可以在任何servlet中检索
connection
属性,以便执行DB操作

public class ServletContextClass implements ServletContextListener {

    public static Connection connection;

    public Connection getConnection(){
        try {
            String connectionURL = "jdbc:mysql://root:port/path";
            Class.forName("com.mysql.jdbc.Driver").newInstance();
            connection = DriverManager.getConnection(connectionURL, "root", "password");
        } catch (SQLException e) {
            // Do something
        }
    }

    public void contextInitialized(ServletContextEvent arg0) {
        System.out.println("ServletContextListener started");
        getConnection();
        arg0.getServletContext().setAttribute("connection", connection);
    }

    public void contextDestroyed(ServletContextEvent arg0) {
        System.out.println("ServletContextListener destroyed");
        try{
            if(connection != null){
                connection.close();
            }
        }catch(SQLException se){
            // Do something
        } 
    }

}
最后访问Servlet(资源)中的
连接
属性。确保将
@Context-ServletContext
传递给
响应
方法,以便访问上下文属性

@GET
@Path("task/{taskId}")
@Consumes(MediaType.APPLICATION_JSON)
public Response getInfos(@PathParam("taskId") int taskId, @Context ServletContext context) throws Exception {
    try {
        Connection connection = (Connection) context.getAttribute("connection");
        Task task = new Task();
        DbData dbData = new DbData();
        task = dbData.getTask(connection, taskId);

        return Response.status(200).entity(task).build();
    } catch (Exception e) {
        throw e;
    }
}
现在我们已经解决了您当前的问题,我们需要知道这种方法会出现什么问题

首先,您只创建一个
连接
对象,该对象将在任何地方使用。想象多个用户同时访问您的API,单个
连接
将在所有用户之间共享,这将降低您的响应时间

其次,您到DB的
连接将在闲置一段时间后终止(除非您将
MySql
服务器配置为不终止空闲连接,这不是一个好主意),当您尝试访问它时,会抛出
SQLException
s。这可以在servlet中解决,您可以检查连接是否已断开,重新创建连接,然后更新context属性


使用Mysql连接池的最佳方法是使用JNDI资源。您可以创建一个
连接池
,该连接池将由
servlet容器
管理。您可以配置该池,以便在连接闲置后失效时重新创建连接。如果您使用Tomcat作为servlet容器,您可以k了解JNDI连接池的简短教程。

谢谢@imranarshad,我刚刚在
getConnection()
函数中得到了一个返回值和一些
catch
,但它可以工作。我将查看您消息的第二部分。这是一个很好的建议