返回介绍

00-07、使用数据库连接池

发布于 2025-03-09 23:21:23 字数 10404 浏览 0 评论 0 收藏 0

目前比较常见的连接池实现有 DBCP、C3P0,Tomcat_JDBC 等。

本文使用的连接池是 DBCP。

进入 http://commons.apache.org/proper/commons-dbcp/download_dbcp.cgi 下载 Apache Commons DBCP for JDBChttp://commons.apache.org/proper/commons-pool/download_pool.cgi 中下载 Apache Commons Poolhttp://dev.mysql.com/downloads/connector/j/ 下载 MySQL 的 JDBC 驱动。

若下载出现问题,可以到一些 Maven 仓库中下载。例如 http://mvnrepository.com/http://maven.oschina.net

数据库准备

MySQL 5.6。

--创建数据库
CREATE DATABASE IF NOT EXISTS `test` DEFAULT CHARSET utf8 COLLATE utf8_general_ci;
USE `test`;
--创建 table
CREATE TABLE IF NOT EXISTS user
(
  `id` int AUTO_INCREMENT,
  `name` varchar(255),
  `email` varchar(255),
  `age` varchar(255),
  `passwd` varchar(255),
  PRIMARY KEY (`id`),
  UNIQUE KEY (`name`),
  UNIQUE KEY (`email`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
---插入若干数据
INSERT INTO user (`name`, `email`, `age`, `passwd`)
VALUES ('user01', 'user01@163.com', 20, password('123'));

INSERT INTO user (`name`, `email`, `age`, `passwd`)
VALUES ('user02', 'user02@163.com', 20, password('456'));

示例 1

目录结构如下:

web.xml 源码:

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.1" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd">

  <servlet-mapping>  
    <servlet-name>default</servlet-name>
    <url-pattern>*.jpg</url-pattern>
  </servlet-mapping>

  <servlet-mapping>  
    <servlet-name>default</servlet-name>
    <url-pattern>*.png</url-pattern>   
  </servlet-mapping>  

  <servlet-mapping>  
    <servlet-name>default</servlet-name>  
    <url-pattern>*.js</url-pattern>  
  </servlet-mapping>  

  <servlet-mapping>  
    <servlet-name>default</servlet-name>  
    <url-pattern>*.css</url-pattern>   
  </servlet-mapping>

  <session-config>
    <session-timeout>
      30
    </session-timeout>
  </session-config>

</web-app>

dbcp.properties 源码:

driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/test
username=root
password=123456
initialSize=2
maxActive=15
maxIdle=2
minIdle=1
maxWait=30000

这些配置的解释请见 BasicDataSource Configuration Parameters

HelloServlet.java 源码:

package me.letiantian.servlet;

import java.io.IOException;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.Properties;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.sql.DataSource;

import org.apache.commons.dbcp.BasicDataSourceFactory;

@WebServlet(name = "HelloServlet", urlPatterns = {"/hello"})
public class HelloServlet extends HttpServlet {

  protected void processRequest(HttpServletRequest request, HttpServletResponse response) throws IOException {
    response.setContentType("text/html;charset=UTF-8");
    PrintWriter out = response.getWriter();
    try{
      Properties properties=new Properties();
      properties.load(getServletContext().getResourceAsStream("/WEB-INF/dbcp.properties"));
      DataSource dataSource = BasicDataSourceFactory.createDataSource(properties);
      Connection conn = dataSource.getConnection();
      String sql = "select 1+1 as result;";
      PreparedStatement pstmt = conn.prepareStatement(sql);
      ResultSet rs = pstmt.executeQuery();

      if (rs.next()) {
        int result = rs.getInt("result");
        out.println("result: " + result);
      }

      rs.close();
      pstmt.close();
      conn.close();

    } catch (Exception ex) {
      out.println(ex.getMessage());
    }
  }

  @Override
  protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
    processRequest(request, response);
  }

  @Override
  protected void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException {
    processRequest(request, response);
  }

}

运行项目,浏览器访问 http://localhost:8084/Project_0007_DBCP/hello

改进:将初始化的连接池放到 Servlet 上下文中

上面代码中是再 servlet 中初始化连接池,更好的方法是再 Listener 中初始化,并将连接池作为属性放入 servlet 上下文中。

源文件以及代码有所变化,项目结构如下:

DBCPListener.java 内容如下:

package me.letiantian.listener;

import java.util.Properties;
import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;
import javax.sql.DataSource;
import org.apache.commons.dbcp.BasicDataSourceFactory;

@WebListener
public class DBCPListener implements ServletContextListener{

  // 应用启动时,该方法被调用
  @Override
  public void contextInitialized(ServletContextEvent sce) {
    try {
      System.out.println("设置数据库连接池");
      ServletContext application = sce.getServletContext();
      Properties properties=new Properties();
      properties.load(application.getResourceAsStream("/WEB-INF/dbcp.properties"));
      DataSource dataSource = BasicDataSourceFactory.createDataSource(properties);
      application.setAttribute("dataSource", dataSource);
    }
    catch(Exception ex) {
      System.err.println("数据库连接池设置出现异常:" + ex.getMessage());
    }
  }

  // 应用关闭时,该方法被调用
  @Override
  public void contextDestroyed(ServletContextEvent sce) {

  }

}

HelloServlet.java 内容如下:

package me.letiantian.servlet;

import java.io.IOException;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.sql.DataSource;

@WebServlet(name = "HelloServlet", urlPatterns = {"/hello"})
public class HelloServlet extends HttpServlet {

  protected void processRequest(HttpServletRequest request, HttpServletResponse response) throws IOException {
    response.setContentType("text/html;charset=UTF-8");
    PrintWriter out = response.getWriter();
    try {
      DataSource dataSource = (DataSource) getServletContext().getAttribute("dataSource");
      Connection conn = dataSource.getConnection();
      String sql = "select name from user;";
      PreparedStatement pstmt = conn.prepareStatement(sql);
      ResultSet rs = pstmt.executeQuery();

      while (rs.next()) {
        String name = rs.getString("name");
        out.println("result: " + name + "</br>");
      }

      rs.close();
      pstmt.close();
      conn.close();

    } catch (Exception ex) {
      out.println(ex.getMessage());
    }
  }

  @Override
  protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
    processRequest(request, response);
  }

  @Override
  protected void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException {
    processRequest(request, response);
  }

}

启动项目,可以看到 Tomcat 输出:

设置数据库连接池

浏览器输出:

查看一下 mysql 的连接:

mysql> show processlist;
+----+------+-----------------+------+---------+------+-------+------------------+
| Id | User | Host      | db   | Command | Time | State | Info       |
+----+------+-----------------+------+---------+------+-------+------------------+
| 45 | root | localhost     | test | Query   |  0 | init  | show processlist |
| 77 | root | localhost:41770 | test | Sleep   |  300 |     | NULL       |
| 78 | root | localhost:41771 | test | Sleep   |  300 |     | NULL       |
| 83 | root | localhost:41790 | test | Sleep   |  274 |     | NULL       |
| 84 | root | localhost:41791 | test | Sleep   |   69 |     | NULL       |
+----+------+-----------------+------+---------+------+-------+------------------+
5 rows in set (0.00 sec)

关闭 Tomcat,查看数据库连接:

mysql> show processlist;
+----+------+-----------+------+---------+------+-------+------------------+
| Id | User | Host    | db   | Command | Time | State | Info       |
+----+------+-----------+------+---------+------+-------+------------------+
| 45 | root | localhost | test | Query   |  0 | init  | show processlist |
+----+------+-----------+------+---------+------+-------+------------------+
1 row in set (0.00 sec)

DBUtils

使用 DBUtils 可以更加方便的操作数据库,可以参考 DBUtils 简明教程

资料

官网
DBCP,C3P0,Tomcat_JDBC 性能及稳定性测试
数据连接池 DBCP 参数介绍
DBCP 数据库连接池的使用

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文