DBCP是tomcat中的一个工具类。

DBCP(DataBase Connection Pool)数据库连接池,是java数据库连接池的一种,由Apache开发,通过数据库连接池,可以让程序自动管理数据库连接的释放和断开。

DBCP(DataBase connection pool),数据库连接池。是 apache 上的一个 java 连接池项目,也是 tomcat 使用的连接池组件。单独使用dbcp需要2个包:commons-dbcp.jar,commons-pool.jar由于建立数据库连接是一个非常耗时耗资源的行为,所以通过连接池预先同数据库建立一些连接,放在内存中,应用程序需要建立数据库连接时直接到连接池中申请一个就行,用完后再放回去。

DBCP数据库连接池操作如下:

1、导入驱动jar包(dbcp连接池jar包通常依赖于pool包一起使用)

原理:dbcp包会产生许多个连接对象,这些对象供pool包进行统一管理。

2、创建数据库工具类:DBUtils.java

工具类优点:

  • 1、提高性能

告别传统方式每次连接数据库都要进行创建并关闭,严重影响性能,使用数据库连接池DBCP技术实现连接池中存放多个连接对象供使用。当不需要连接时,将连接对象存放到池中即可,提高性能!

  • 2、避免多线程访问连接对象混乱问题

将连接保存在ThreadLocal类中,相当于map结构,它是将当前线程对象作为key,保存连接conn对象,避免多线程访问业务层和dao层导致使用的conn连接对象不一致问题。先从threadLocal中获取连接,如果连接为null,从连接池获取连接,设置到threadLocal中。

  • 3、将提交和回滚事务统一处理

先从ThreadLocal类中获取连接,如果连接不为null,提交或者回滚事务,然后关闭连接,清理当前线程所绑定的连接。

  • 4、方便关闭连接

关闭除过conn连接对象的其他对象statement、resultset等。

DBCP核心设置代码如下:

// 创建数据库连接池ds = new BasicDataSource();// 设置连接信息ds.setDriverClassName("com.mysql.cj.jdbc.Driver");ds.setUrl(URL);ds.setUsername(USERNAME);ds.setPassword(PASSWORD);// 设置连接池信息// 最大空闲连接数ds.setMaxIdle(30);// 最小空闲连接数ds.setMinIdle(2);// 设置初始连接数ds.setInitialSize(2);// 创建连接时最大等待时间ds.setMaxWaitMillis(4000);// 毫秒// 从数据源中拿到的连接,关闭其自动提交的事务ds.setDefaultAutoCommit(false);

完整代码如下:

package com.yueqian.store.common;import java.sql.Connection;import java.sql.DriverManager;import java.sql.ResultSet;import java.sql.SQLException;import java.sql.Statement;import java.util.HashMap;import java.util.Map;import org.apache.tomcat.dbcp.dbcp2.BasicDataSource;public class DBUtils {private static final String URL = "jdbc:mysql://127.0.0.1:3306/store?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2B8&useSSL=false";private static final String USERNAME = "root";private static final String PASSWORD = "root";private static final BasicDataSource ds;static {// 加载驱动try {// 方式一DriverManager.registerDriver(new com.mysql.cj.jdbc.Driver());// 方式二 根据传入字符串形式的类名加载该类 (加载类时调用静态代码块加载驱动)// Class.forName("com.mysql.cj.jdbc.Driver()");} catch (Exception e) {// TODO Auto-generated catch blocke.printStackTrace();}// 创建数据库连接池ds = new BasicDataSource();// 设置连接信息ds.setDriverClassName("com.mysql.cj.jdbc.Driver");ds.setUrl(URL);ds.setUsername(USERNAME);ds.setPassword(PASSWORD);// 设置连接池信息// 最大空闲连接数ds.setMaxIdle(30);// 最小空闲连接数ds.setMinIdle(2);// 设置初始连接数ds.setInitialSize(2);// 创建连接时最大等待时间ds.setMaxWaitMillis(4000);// 毫秒// 从数据源中拿到的连接,关闭其自动提交的事务ds.setDefaultAutoCommit(false);}// 定义连接保存在ThreadLocal类中,将当前线程对象作为key,保存连接conn对象,避免多线程访问业务层和dao层导致使用的conn连接不一致问题// service里绑定每个线程对象的连接,调用的dao层获取该处理线程对象的连接private static ThreadLocal threadLocal = new ThreadLocal();/** * 连接数据库 *  * @return */public static Connection getConnection() {//先从threadLocal中获得连接,threadLocal类似map存放,ThreadLocal中是以键为当前线程对象,值为conn连接存放的。Connection conn = threadLocal.get();//如果连接为null,从连接池中获取连接if (conn == null) {try {conn = ds.getConnection();} catch (SQLException e) {// TODO Auto-generated catch blocke.printStackTrace();}//将得到的连接设置到threadLocal中threadLocal.set(conn);}return conn;}/** * 关闭连接 *  * @param rs * @param stmt * @param conn */public static void close(ResultSet rs, Statement stmt) {if (rs != null) {try {rs.close();} catch (SQLException e) {// TODO Auto-generated catch blocke.printStackTrace();} finally {if (stmt != null) {try {stmt.close();} catch (SQLException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}}}// 提交事务public static void commit() {Connection conn = threadLocal.get();if(conn != null){try {conn.commit();} catch (SQLException e) {// TODO Auto-generated catch blocke.printStackTrace();}finally {//关闭连接try {conn.close();} catch (SQLException e) {// TODO Auto-generated catch blocke.printStackTrace();}//清理当前线程所绑定的连接threadLocal.remove();}}}// 回滚事务public static void rollback() {Connection conn = threadLocal.get();if(conn != null){try {conn.rollback();} catch (SQLException e) {// TODO Auto-generated catch blocke.printStackTrace();}finally {//关闭连接try {conn.close();} catch (SQLException e) {// TODO Auto-generated catch blocke.printStackTrace();}//清理当前线程所绑定的连接threadLocal.remove();}}}}

3、业务层

使用同一个连接对象,调用多个Dao层处理。所有事务处理完成之后,统一操作成功,调用DBUtils.commit()方法提交事务,一个失败,全部回滚。

package com.yueqian.store.service;import java.util.List;import com.yueqian.store.common.DBUtils;import com.yueqian.store.dao.ProductTypeDao;import com.yueqian.store.domain.ProductType;/** * 商品类别业务层 *  * @author LinChi * */public class ProductTypeService {private ProductTypeDao typeDao = new ProductTypeDao();/** * 查询所有商品类目 *  * @return */public List findAllProType() {List list = null;try {//调用多个Dao对象处理,最后统一事务提交list = typeDao.findAllProType();//使用同一个连接对象,执行后续的DAO方法//提交事务DBUtils.commit();} catch (Exception e) {//执行失败回滚事务DBUtils.rollback();}return list;}}

4、dao层

dao层直接调用DBUtils.getConnection()方法获得连接,将dao层所有出现的异常向上抛到业务层,业务层统一处理,最后统一提交并回滚事务,dao层不处理异常,一直声明抛出即可,

package com.yueqian.store.dao;import java.sql.Connection;import java.sql.PreparedStatement;import java.sql.ResultSet;import java.sql.SQLException;import java.util.ArrayList;import java.util.List;import com.yueqian.store.common.DBUtils;import com.yueqian.store.domain.ProductType;public class ProductTypeDao {/** * 查询所有商品类目表 * @return * @throws SQLException  将dao层所有出现的异常向上抛到业务层,业务层统一处理,最后统一提交并回滚事务 */public List findAllProType()throws SQLException{Connection conn = null;PreparedStatement pstm = null;List list = new ArrayList();ResultSet rs = null;ProductType proType = null;conn = DBUtils.getConnection();String sql = "SELECT p.product_type_id,p.name FROM product_types p";try {pstm = conn.prepareStatement(sql);rs = pstm.executeQuery();while(rs.next()) {proType = new ProductType();proType.setTypeId(rs.getInt(1));proType.setTypeName(rs.getString(2));list.add(proType);}} finally {DBUtils.close(rs, pstm);}return list;}}

5、controller层

调用业务层,处理相应的逻辑

  • BaseServlet.java

这是个通过反射机制,将前端传入String的参数类型转换为对应的类型。其他servlet集成该类即可方便转换类型。参数如下(前端name名称,请求对象req,要转化类型的字节码Integer.class)

package com.yueqian.store.controller;import java.sql.Date;import java.text.SimpleDateFormat;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;public class BaseServlet extends HttpServlet {private static final long serialVersionUID = 1L;private static SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");// 获取请求的参数,根据请求的参数转化为特定的类型public  T paseParamter(String parseName, HttpServletRequest req, Class clz) {// 获取请求参数String parmValue = req.getParameter(parseName);// 定义返回类型的对象T result = null;// clz类型 Integer.class String.class Double.class,Float.class,Date.classtry {if (parmValue != null || parmValue.length() > 0) {// 因为Float类型没有String参数的构造方法,所以只能传入long参数的构造方法if (clz == Date.class) {// 将paramValue转换成long类型的值long longValue = sdf.parse(parmValue).getTime();// 创建指定类型的String参数构造方法result = clz.getDeclaredConstructor(long.class).newInstance(longValue);} else {// 将paramValue作为指定类型构造方法的参数result = clz.getDeclaredConstructor(String.class).newInstance(parmValue);}}} catch (Exception e) {e.printStackTrace();}return result;}}

ProductServlet

具体使用如下:

package com.yueqian.store.controller;import java.io.IOException;import java.util.List;import javax.servlet.ServletException;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import com.yueqian.store.dao.ProductDAO;import com.yueqian.store.dao.ProductTypeDao;import com.yueqian.store.domain.ProductInfo;import com.yueqian.store.domain.ProductType;import com.yueqian.store.service.ProductService;import com.yueqian.store.service.ProductTypeService;public class ProductServlet extends BaseServlet {/** *  */private static final long serialVersionUID = 1L;private ProductService productService = new ProductService();private ProductTypeService typeService = new ProductTypeService();@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {String uri = req.getRequestURI();if (uri.indexOf("/prd/list") >= 0) {// 商品列表List findAllProduct = productService.findAllProduct();// 设置列表到请求页面req.setAttribute("findAllProduct", findAllProduct);// 请求转发到目标页面req.getRequestDispatcher("/product/product_list.jsp").forward(req, resp);} else if (uri.indexOf("/prd/add") >= 0) {// 查看所有类目List findAllProType = typeService.findAllProType();// 存放到请求域中转发到其他页面req.setAttribute("findAllProType", findAllProType);req.getRequestDispatcher("/product/product_add.jsp").forward(req, resp);}}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {req.setCharacterEncoding("utf-8");String uri = req.getRequestURI();if (uri.indexOf("/prd/add") > 0) {// 获取请求的参数Integer typeId = super.paseParamter("typeId", req, Integer.class);String productName = super.paseParamter("productName", req, String.class);String desc = super.paseParamter("desc", req, String.class);Float price = super.paseParamter("price", req, Float.class);System.out.println("productName:"+productName+"-------------------------");System.out.println("price:"+price+"-------------------------");//输入校验//数据库中商品名称不能为null,如果为null,将返回消息和用户填写的其他数据if(productName == null || productName.equals("")) {req.setAttribute("msg", "商品名称不能为空!");req.setAttribute("typeId", typeId);req.setAttribute("desc", desc);req.setAttribute("price", price);req.setAttribute("findAllProType", this.typeService.findAllProType());//请求转发到添加页面req.getRequestDispatcher("/product/product_add.jsp").forward(req, resp);return;}// 添加新商品ProductInfo info = new ProductInfo();if (typeId != null && typeId > 0) {info.setProductTypeId(typeId);}info.setProductName(productName);info.setDesc(desc);info.setPrice(price);int count = productService.saveInfo(info);System.out.println(info.getProductName()+"========================");// 重定向到添加请求url (此处不能使用请求转发,因为表单刷新会发送第二次请求,导致添加两次商品)resp.sendRedirect(req.getContextPath() + "/prd/add?count=" + count + "&from=add&proId=" + info.getProductId());}}}

6、view层

将servlet传入的数据,通过jsp展示到页面给用户

商品添加页面 typeList = (List) request.getAttribute("findAllProType");//获取传递的url参数String count = request.getParameter("count");String from = request.getParameter("from");String proId = request.getParameter("proId");%>返回主页商品类别:请选择商品类别 0) {for (ProductType types : typeList) {%>> 商品名称:商品描述: 商品价格:/> 0) {out.print(f + "了" + count + "件商品,刚刚录入的商品编号为:" + proId);}else{out.print(f+"失败!");}}Object msg = request.getAttribute("msg");if(msg!=null){out.print(msg);}%>

好了,该项目的部分代码如上所示,这节你将学到如何优化数据库连接、mvc分层创建web项目流程 、反射机制转换前端传递的类型。

这就是DBCP连接池的使用,可以大大提供系统的性能,可能现在我们的项目比较小,还没有真正体会到效率提高的到底有多少,相信在今后接触到更大的项目,我们会经常使用连接池的,继续前行……

dao层如何调用对象_如何实现DBCP数据库连接池工具类&mvc分层开发web流程操作?...相关推荐

  1. dao层如何调用对象_你的项目应该如何正确分层?

    你好,欢迎收听极客视点. 说起应用分层,大部分人都会认为这不是很简单嘛,就Controller.Service.Mapper三层.但在"简单"背后,很多人并没有将各层级的职责划分清 ...

  2. dao层如何调用对象_以k8s集群管理为例,大牛教你如何设计优秀项目架构

    架构设计一直是技术人的关注热点,如何设计一个更优的架构对于实际的业务来说至关重要.本文腾讯云专家将从自身从事的一个k8s集群管理项目为例,重点剖析在项目开发过程中的三次架构演进历程,即针对项目最早版本 ...

  3. java xml最火的的工具_几种高效的Java工具类推荐

    本文将介绍了十二种常用的.高效的Java工具类 在Java中,工具类定义了一组公共方法,这篇文章将介绍Java中使用最频繁及最通用的Java工具类. 在开发中,使用这些工具类,不仅可以提高编码效率,还 ...

  4. Java Web性能优化之一:减少DAO层的调用次数

    前言 很简单的一个问题,一个业务方法,需要先查询一次得到结果(select),然后再根据查询的结果进行一次更新(update),通常情况下我们会在DAO层定义两个接口,一个接口实现查询,一个接口实现更 ...

  5. mysql连接池_数据库技术:数据库连接池,Commons DbUtils,批处理,元数据

    Database Connection Pool Introduction to Database Connection Pool 实际开发中"获得连接"或"释放资源&q ...

  6. webbrowser实现input tab事件_如何合理构造一个Uploader工具类(设计到实现)

    作者:Chaser (本文来自作者投稿) 原文地址:https://juejin.im/post/5e5badce51882549652d55c2 源码地址:https://github.com/im ...

  7. java递归生成树结构_突破CRUD | 万能树Java工具类封装(源码)

    0.学完本文你或许可以收获 感受一个树工具从初始逐步优化完善的过程 树工具封装的设计思考与实现思路 最后收获一款拿来即用的树工具源代码 对于前端树组件有一定了解和使用过的同学可直接跳跃到第3章节开始. ...

  8. java 工具类命名_排名前16的Java工具类

    在Java中,工具类定义了一组公共方法,这篇文章将介绍Java中使用最频繁及最通用的Java工具类.以下工具类.方法按使用流行度排名,参考数据来源于Github上随机选取的5万个开源项目源码. 一. ...

  9. java 在线rsa解密_通用的Java RSA加密工具类,可在线验证通过

    /** * RSA加密工具类 * 使用PKCS1_PADDING填充,密钥长度1024 * 加解密结果在这里测试通过:http://tool.chacuo.net/cryptrsaprikey * 注 ...

  10. C#中调用Windows系统服务exe程序的工具类与重启服务的流程

    场景 使用C#编写的Windows服务程序,在Winform中进行调用. 常用工具类方法检测服务是否存在或者安装,获取服务状态,启动服务,停止服务的方法. 以在Winform中重启服务为例. 注: 博 ...

最新文章

  1. Squid下Http头信息优先级
  2. Python 集合的定义以及常用运算及函数
  3. Python 技术篇-PIL库安装及截图功能演示
  4. vim 格式化json
  5. 机器学习系列(一)感知器分类算法
  6. WPF Application 类介绍以及怎样修改启动方式
  7. 支持后悔药的etcdui
  8. C# WinForm关闭窗体确认
  9. word参考文献后面空格太大
  10. 面试的准备——公子禹
  11. 1883:北京旅行日记1276695923新浪博客
  12. 傅福:我可能是杭州接受BCH付款的第一个数码商家
  13. c语言lzma算法,在C中使用C-LZMA-SDK解压缩LZMA返回SZ_ERROR_DATA,因为输入流的第一个字节是!= 0...
  14. 电商战决胜在物流 聚美优品破瓶颈发展
  15. 基于多传感器数据融合的全自动泊车系统研究与应用(文献综述)
  16. ssd硬盘 速度慢 linux,Linux 对SSD硬盘优化的方法
  17. 时间流逝,岁月里所有的狼狈
  18. 内外网同时使用之添加路由
  19. sql面试重点之minus 2021-11-05
  20. java游戏三国神兽,三国神兽攻略游戏下载_三国神兽攻略手游安卓版下载-我的世界中文网...

热门文章

  1. Mininet实验 自定义拓扑结构
  2. MyBatis Review——多对多映射
  3. 二分搜索(Binary Search)
  4. Java集合(十三)Iterator和Enumeration的区别和对比
  5. yourphp添加KindEditor编辑器
  6. 使用Inno Setup 打包.NET程序,并自动安装.Net Framework
  7. Microsoft Dynamic CRM 自定义重复检测功能
  8. 物联网培训总结(C#)
  9. 3 超链接_excel函数应用技巧:超链接函数HYPERLINK
  10. linux命令行改变时区,Linux命令行操作修改系统时区