时间:2021-07-01 10:21:17 帮助过:4人阅读
代理的总结:
使用代理,可以在不实现接口的情况,对接口的方法进行扩展,添加额外的用户需要的业务逻辑!
概述:
Sun公司约定: 如果是连接池技术,需要实现一个接口!
javax.sql.DataSource;
连接池:
DBCP
C3P0
DBCP连接池:
DBCP 是 Apache 软件基金组织下的开源连接池实现,使用DBCP数据源,应用程序应在系统中增加如下两个 jar 文件:
? Commons-dbcp.jar:连接池的实现
? Commons-pool.jar:连接池实现的依赖库
Tomcat 的连接池正是采用该连接池来实现的。该数据库连接池既可以与应用服务器整合使用,也可由应用程序独立使用。
核心类:
BasicDataSource
使用步骤
? 引入jar文件
commons-dbcp-1.4.jar
commons-pool-1.5.6.jar
配置方式实现DBCP连接池, 配置文件中的key与BaseDataSouce中的属性一样:
db.properties
url=jdbc:mysql:///jdbc_demo
driverClassName=com.mysql.jdbc.Driver
username=root
password=root
initialSize=3
maxActive=6
maxIdle=3000
使用:
public class App_DBCP {
// 1. 硬编码方式实现连接池
@Test
public void testDbcp() throws Exception {
// DBCP连接池核心类
BasicDataSource dataSouce = new BasicDataSource();
// 连接池参数配置:初始化连接数、最大连接数 / 连接字符串、驱动、用户、密码
dataSouce.setUrl("jdbc:mysql:///jdbc_demo"); //数据库连接字符串
dataSouce.setDriverClassName("com.mysql.jdbc.Driver"); //数据库驱动
dataSouce.setUsername("root"); //数据库连接用户
dataSouce.setPassword("root"); //数据库连接密码
dataSouce.setInitialSize(3); // 初始化连接
dataSouce.setMaxActive(6); // 最大连接
dataSouce.setMaxIdle(3000); // 最大空闲时间
// 获取连接
Connection con = dataSouce.getConnection();
con.prepareStatement("delete from admin where id=3").executeUpdate();
// 关闭
con.close();
}
@Test
// 2. 【推荐】配置方式实现连接池 , 便于维护
public void testProp() throws Exception {
// 加载prop配置文件
Properties prop = new Properties();
// 获取文件流
InputStream inStream = App_DBCP.class.getResourceAsStream("db.properties");
// 加载属性配置文件
prop.load(inStream);
// 根据prop配置,直接创建数据源对象
DataSource dataSouce = BasicDataSourceFactory.createDataSource(prop);
// 获取连接
Connection con = dataSouce.getConnection();
con.prepareStatement("delete from admin where id=4").executeUpdate();
// 关闭
con.close();
}
}
C3P0连接池:
最常用的连接池技术!Spring框架,默认支持C3P0连接池技术!
C3P0连接池,核心类:
CombopooledDataSource ds;
使用:
1. 下载,引入jar文件: c3p0-0.9.1.2.jar
2. 使用连接池,创建连接
a) 硬编码方式
b) 配置方式(xml)
案例:
public class App {
@Test
//1. 硬编码方式,使用C3P0连接池管理连接
public void testCode() throws Exception {
// 创建连接池核心工具类
ComboPooledDataSource dataSource = new ComboPooledDataSource();
// 设置连接参数:url、驱动、用户密码、初始连接数、最大连接数
dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/jdbc_demo");
dataSource.setDriverClass("com.mysql.jdbc.Driver");
dataSource.setUser("root");
dataSource.setPassword("root");
dataSource.setInitialPoolSize(3);
dataSource.setMaxPoolSize(6);
dataSource.setMaxIdleTime(1000);
// ---> 从连接池对象中,获取连接对象
Connection con = dataSource.getConnection();
// 执行更新
con.prepareStatement("delete from admin where id=7").executeUpdate();
// 关闭
con.close();
}
@Test
//2. XML配置方式,使用C3P0连接池管理连接
public void testXML() throws Exception {
// 创建c3p0连接池核心工具类
// 自动加载src下c3p0的配置文件【c3p0-config.xml】
ComboPooledDataSource dataSource = new ComboPooledDataSource();// 使用默认的配置
// 获取连接
Connection con = dataSource.getConnection();
// 执行更新
con.prepareStatement("delete from admin where id=5").executeUpdate();
// 关闭
con.close();
}
}
配置方式:
<c3p0-config>
<default-config>
<property name="jdbcUrl">jdbc:mysql://localhost:3306/jdbc_demo
</property>
<property name="driverClass">com.mysql.jdbc.Driver</property>
<property name="user">root</property>
<property name="password">root</property>
<property name="initialPoolSize">3</property>
<property name="maxPoolSize">6</property>
<property name="maxIdleTime">1000</property>
</default-config>
<named-config name="oracle_config">
<property name="jdbcUrl">jdbc:mysql://localhost:3306/jdbc_demo</property>
<property name="driverClass">com.mysql.jdbc.Driver</property>
<property name="user">root</property>
<property name="password">root</property>
<property name="initialPoolSize">3</property>
<property name="maxPoolSize">6</property>
<property name="maxIdleTime">1000</property>
</named-config>
</c3p0-config>
重写Utils
public class JdbcUtils {
/**
* 1. 初始化C3P0连接池
*/
private static DataSource dataSource;
static {
dataSource = new ComboPooledDataSource();
}
/**
* 2. 创建DbUtils核心工具类对象
*/
public static QueryRunner getQueryRuner(){
// 创建QueryRunner对象,传入连接池对象
// 在创建QueryRunner对象的时候,如果传入了数据源对象;
// 那么在使用QueryRunner对象方法的时候,就不需要传入连接对象;
// 会自动从数据源中获取连接(不用关闭连接)
return new QueryRunner(dataSource);
}
}
分页技术:
JSP页面,用来显示数据! 如果数据有1000条,分页显示,每页显示10条,共100页; 好处: 利于页面布局,且显示的效率高!
分页关键点:
实现步骤:
0. 环境准备
a) 引入jar文件及引入配置文件
i. 数据库驱动包
ii. C3P0连接池jar文件 及 配置文件
iii. DbUtis组件: QueryRunner qr = new QueryRuner(dataSouce);
qr.update(sql);
b) 公用类: JdbcUtils.java
1. 先设计:PageBean.java
2. Dao接口设计/实现: 2个方法
3. Service/servlet
4. JSP
entity:
public class Employee {
private int empId; // 员工id
private String empName; // 员工名称
private int dept_id; // 部门id
public int getEmpId() {
return empId;
}
public void setEmpId(int empId) {
this.empId = empId;
}
public String getEmpName() {
return empName;
}
public void setEmpName(String empName) {
this.empName = empName;
}
public int getDept_id() {
return dept_id;
}
public void setDept_id(int deptId) {
dept_id = deptId;
}
}
Dao:
public interface IEmployeeDao {
/**
* 分页查询数据
*/
public void getAll(PageBean<Employee> pb);
/**
* 查询总记录数
*/
public int getTotalCount();
}
DaoImpl:
public class EmployeeDao implements IEmployeeDao {
public void getAll(PageBean<Employee> pb) {
//2. 查询总记录数; 设置到pb对象中
int totalCount = this.getTotalCount();
pb.setTotalCount(totalCount);
/*
* 问题: jsp页面,如果当前页为首页,再点击上一页报错!
* 如果当前页为末页,再点下一页显示有问题!
* 解决:
* 1. 如果当前页 <= 0; 当前页设置当前页为1;
* 2. 如果当前页 > 最大页数; 当前页设置为最大页数
*/
// 判断
if (pb.getCurrentPage() <=0) {
pb.setCurrentPage(1); // 把当前页设置为1
} else if (pb.getCurrentPage() > pb.getTotalPage()){
pb.setCurrentPage(pb.getTotalPage()); // 把当前页设置为最大页数
}
//1. 获取当前页: 计算查询的起始行、返回的行数
int currentPage = pb.getCurrentPage();
int index = (currentPage -1 ) * pb.getPageCount(); // 查询的起始行
int count = pb.getPageCount(); // 查询返回的行数
//3. 分页查询数据; 把查询到的数据设置到pb对象中
String sql = "select * from employee limit ?,?";
try {
// 得到Queryrunner对象
QueryRunner qr = JdbcUtils.getQueryRuner();
// 根据当前页,查询当前页数据(一页数据)
List<Employee> pageData = qr.query(sql, new BeanListHandler<Employee>(Employee.class), index, count);
// 设置到pb对象中
pb.setPageData(pageData);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
service:
public interface IEmployeeService {
/**
* 分页查询数据
*/
public void getAll(PageBean<Employee> pb);
}
serviceimpl:
public class EmployeeService implements IEmployeeService {
// 创建Dao实例
private IEmployeeDao employeeDao = new EmployeeDao();
public void getAll(PageBean<Employee> pb) {
try {
employeeDao.getAll(pb);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
servlet:
public class IndexServlet extends HttpServlet {
// 创建Service实例
private IEmployeeService employeeService = new EmployeeService();
// 跳转资源
private String uri;
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
try {
//1. 获取“当前页”参数; (第一次访问当前页为null)
String currPage = request.getParameter("currentPage");
// 判断
if (currPage == null || "".equals(currPage.trim())){
currPage = "1"; // 第一次访问,设置当前页为1;
}
// 转换
int currentPage = Integer.parseInt(currPage);
//2. 创建PageBean对象,设置当前页参数; 传入service方法参数
PageBean<Employee> pageBean = new PageBean<Employee>();
pageBean.setCurrentPage(currentPage);
//3. 调用service
employeeService.getAll(pageBean); // 【pageBean已经被dao填充了数据】
//4. 保存pageBean对象,到request域中
request.setAttribute("pageBean", pageBean);
//5. 跳转
uri = "/WEB-INF/list.jsp";
} catch (Exception e) {
e.printStackTrace(); // 测试使用
// 出现错误,跳转到错误页面;给用户友好提示
uri = "/error/error.jsp";
}
request.getRequestDispatcher(uri).forward(request, response);
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
this.doGet(request, response);
}
}
PageBean:
public class PageBean<T> {
private int currentPage = 1; // 当前页, 默认显示第一页
private int pageCount = 4; // 每页显示的行数(查询返回的行数), 默认每页显示4行
private int totalCount; // 总记录数
private int totalPage; // 总页数 = 总记录数 / 每页显示的行数 (+ 1)
private List<T> pageData; // 分页查询到的数据
// 返回总页数
public int getTotalPage() {
if (totalCount % pageCount == 0) {
totalPage = totalCount / pageCount;
} else {
totalPage = totalCount / pageCount + 1;
}
return totalPage;
}
public void setTotalPage(int totalPage) {
this.totalPage = totalPage;
}
public int getCurrentPage() {
return currentPage;
}
public void setCurrentPage(int currentPage) {
this.currentPage = currentPage;
}
public int getPageCount() {
return pageCount;
}
public void setPageCount(int pageCount) {
this.pageCount = pageCount;
}
public int getTotalCount() {
return totalCount;
}
public void setTotalCount(int totalCount) {
this.totalCount = totalCount;
}
public List<T> getPageData() {
return pageData;
}
public void setPageData(List<T> pageData) {
this.pageData = pageData;
}
}
jsp:
<html>
<head>
<title>分页查询数据</title>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
</head>
<body>
<table border="1" width="80%" align="center" cellpadding="5" cellspacing="0">
<tr>
<td>序号</td>
<td>员工编号</td>
<td>员工姓名</td>
</tr>
<!-- 迭代数据 -->
<c:choose>
<c:when test="${not empty requestScope.pageBean.pageData}">
<c:forEach var="emp" items="${requestScope.pageBean.pageData}" varStatus="vs">
<tr>
<td>${vs.count }</td>
<td>${emp.empId }</td>
<td>${emp.empName }</td>
</tr>
</c:forEach>
</c:when>
<c:otherwise>
<tr>
<td colspan="3">对不起,没有你要找的数据</td>
</tr>
</c:otherwise>
</c:choose>
<tr>
<td colspan="3" align="center">
当前${requestScope.pageBean.currentPage }/${requestScope.pageBean.totalPage }页
<a href="${pageContext.request.contextPath }/index?currentPage=1">首页</a>
<a href="${pageContext.request.contextPath }/index?currentPage=${requestScope.pageBean.currentPage-1}">上一页 </a>
<a href="${pageContext.request.contextPath }/index?currentPage=${requestScope.pageBean.currentPage+1}">下一页 </a>
<a href="${pageContext.request.contextPath }/index?currentPage=${requestScope.pageBean.totalPage}">末页</a>
</td>
</tr>
</table>
</body>
</html>
25、连接池(DBCP、C3P0)、动态代理与分页技术
标签: