与JERSEY的MySQL连接池

时间:2016-05-25 15:18:14

标签: mysql jdbc jersey connection-pooling

我正在使用Jersey和MySQL开发RESTful API。

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

以下是我做错的方法:

DbConnection.java     公共类DbConnection {

    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;
    }
}

Resource.java

@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;
    }
}

这是我最终尝试实现新类的地方:

ServletContextClass.java

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 ();       
    }

}

但问题是,我不知道接下来该做什么。有帮助吗?感谢

1 个答案:

答案 0 :(得分:2)

您需要将Connection变量设置为attribute的{​​{1}}。另外,我建议使用ServletContext作为静态类变量,以便您可以在connection方法中关闭它。 您可以稍后检索任何servlet中的contextDestroyed属性以进行数据库操作。

connection

最后访问Servlet(资源)中的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 } } } 属性。请务必将connection传递给@Context ServletContext方法,以便访问上下文属性。

Response

现在我们已经解决了您当前的问题,我们需要知道这种方法会出现什么问题。

首先,您只创建一个将在任何地方使用的@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,单个connection将在所有用户之间共享,这将减慢您的响应时间。

其次,你的connection到DB会在闲置一段时间后死掉(除非你配置connection服务器不要杀死空闲连接,这不是一个好主意),当你试图访问它,你会被MySql全部抛出。这可以在servlet中解决,你可以检查你的连接是否已经死,再次创建它,然后更新上下文属性。

关于Mysql连接池的最佳方法是使用JNDI资源。您可以创建一个由SQLException管理的pool of connections。您可以将池配置为在闲置后死亡时重新建立连接。如果您使用Tomcat作为Servlet容器,则可以查看this简短教程以开始了解JNDI连接池。