代理实现连接池第三方连接池Dbutilsc3p0.docx
- 文档编号:7319902
- 上传时间:2023-01-22
- 格式:DOCX
- 页数:23
- 大小:337.66KB
代理实现连接池第三方连接池Dbutilsc3p0.docx
《代理实现连接池第三方连接池Dbutilsc3p0.docx》由会员分享,可在线阅读,更多相关《代理实现连接池第三方连接池Dbutilsc3p0.docx(23页珍藏版)》请在冰豆网上搜索。
代理实现连接池第三方连接池Dbutilsc3p0
代理实现连接池,第三方连接池,Dbutils
GenericServlet继承增强了HttpServlet(包装)
IO都是包装
BufferedReaderrd=newBufferedReader(newFileReader(“a.txt”));
BufferedReader增强了FileReader,从而可以由一个字符一个字符的读增强到可以到一行一行的读。
包装缺点:
1.需要实现的方法太多。
2.一个包装类,只可以包装一个被包装类。
如一个包装盒只可以包装一个蛋糕。
3.包装类也是被包装类(被包装的蛋糕,还是蛋糕)
对一个类增强的三种方式:
1.继承某个类extends
2.对某个类进行包装
3.动态代理
代理
代理的特点:
1.可以代理多个被代理类。
2.代理类不是被代理类,即经济人不是华仔。
3.代理可以在不污染任何类的情况下,对某个类进行代理。
代理的要求:
1.被代理的类必须要拥有一个接口。
2.代理的核心类:
●java.lang.reflect.Proxy–代理生成类
●java.lang.invokeHandler–执行句柄,可以在运行时获取正在调用某个方法,还有传递的参数
第一步:
如果要实现代理,某类必须要拥有一个接口。
Proxy(代理)在运行时根据给定的接口,在内存中创建一个与被代理类相同的类。
第二步:
示例代码
publicclassProxyDemo{
publicstaticvoidmain(String[]args){
System.err.println("1:
声明被代理类的实例");
finalCatcat=newCat();
System.err.println("2:
通过Proxy在内存中创建ICat的子类");
ObjectproxyedObj=Proxy.newProxyInstance(
ProxyDemo.class.getClassLoader(),newClass[]{Animal.class},
//拦截句柄,在执行时,只要执行代理类(经济人,中介-proxyedObj)任何方法,
//都会被这个句柄给拦截到
newInvocationHandler(){
//1:
参数:
proxy即proxyedObj,即这个一个代理,经济人,中介
//2:
Method即反射出来的代理对象的方法proxyedObj.getClass().getMethod(xx)
//3:
参数列表
publicObjectinvoke(Objectproxy,Methodmethod,
Object[]args)throwsThrowable{
System.err.println("5:
正在执行的方法为:
"+method.getName());
//如果没有返回则为null,调用cat对象的eat方法
ObjectreturnValue=method.invoke(cat,args);
System.err.println("7:
返回的值是:
"+returnValue);
returnreturnValue;
}
});
System.err.println("3:
将proxyedObj代理类,即经济人转成被代理对象");
Animala1=(Animal)proxyedObj;
System.err.println("4:
调用代理对象的(经济人的)eat方法");
a1.eat();
System.err.println("8:
执行完成");
}
}
//声明被代理类的class
interfaceAnimal{
publicvoideat();
}
classCatimplementsAnimal{
publicvoideat(){
System.err.println("6:
fishing...");
}
}
案例:
要求拦截List接口的添加元素方法。
分析:
即拦截List.add方法
/**
*拦截List添加方法
*/
publicclassInterListDemo{
publicstaticvoidmain(String[]args){
//1:
声明被代理的list
finalList
newArrayList
list.add("World");
//2:
在内存中创建List接口的子类
ObjectproxyedObj=
Proxy.newProxyInstance(InterListDemo.class.getClassLoader(),
newClass[]{List.class},
newInvocationHandler(){
publicObjectinvoke(Objectproxy,Methodmethod,Object[]args)
throwsThrowable{
System.err.println("正在执行某个方法:
"+method.getName());
//判断是否是正在执行size方法
if(method.getName().equals("size")){
return100;
}else{//否则,即调用的不是size方法,直接去执行原对象的某个方法
ObjectreturnValue=method.invoke(list,args);
returnreturnValue;
}
}
});
//3:
转换
List
//list2.add("Hello");
//要求当调用size时不管原list中的size是多少,都返回100
System.err.println("list.size:
"+list2.size());
for(Objecto:
list2){
System.err.println(o);
}
}
}
代理实现连接池
用代理实现对Connection的close方法修改,目的要求不能关闭连接,应该是归还连接。
1.必须要有一个池,即List,LinkedList
2.创建多个连接入到List中去,在放之前,必须要对Connection进行代理
3.在代理的Connection方法中对所有其它方法都直接去调用原类即被代理类的方法,但对于close方法不能调用,应是修改为归还连接。
实现代码:
publicclassConnPool{
privatestaticLinkedList
newLinkedList
static{
try{
Propertiesp=
newProperties();
InputStreamin=
ConnPool.class.getClassLoader().getResourceAsStream("jdbc.properties");
p.load(in);
Stringdriver=p.getProperty("d");
Stringurl=p.getProperty("u");
Stringnm=p.getProperty("n");
Stringpwd=p.getProperty("p");
Integersize=Integer.valueOf(p.getProperty("s"));
//创建多个连接
for(inti=0;i finalConnectioncon=//原生对象,即没有被代理的,但准备被代理的-华仔 DriverManager.getConnection(url,nm,pwd); //声明代理类 ObjectconnProxy= Proxy.newProxyInstance( ConnPool.class.getClassLoader(), newClass[]{Connection.class}, newInvocationHandler(){ publicObjectinvoke(Objectproxy,Methodmethod,Object[]args) throwsThrowable{ if(method.getName().equals("close")){ System.err.println("有人还连接了"); synchronized(pool){ //由于proxy就是connProxy,所以直接就将proxy添加回去就可以 pool.addLast((Connection)proxy); pool.notify(); } returnnull; }else{ //如果调用的不是close方法则直接调用原生对象的方法即放行 returnmethod.invoke(con,args); } } }); //将代理类,即经济人放到List中 pool.add((Connection)connProxy); } }catch(Exceptione){ e.printStackTrace(); } } publicstaticConnectiongetCon(){ synchronized(pool){ //计算时间的开始 longstart=System.currentTimeMillis(); while(pool.size()==0){ //进入等待池 System.err.println("取一次: "+Thread.currentThread().getName()); try{ pool.wait(1000); }catch(InterruptedExceptione){ e.printStackTrace(); } //计算时间是否超过了三秒 longpro=System.currentTimeMillis()-start; if(pro>3000){ System.err.println("已经超过3秒超时,放弃"); thrownewRuntimeException("时间超时了"); } } System.err.println(pool.size()); Connectioncon=pool.removeFirst(); returncon; } } } 标准连接池 标准的连接池,就是实现DataSource接口,且实现DataSource接口的类,必须是具体类,没有静态方法。 ConnectiongetConnection() AttemptstoestablishaconnectionwiththedatasourcethatthisDataSourceobjectrepresents. 尝试建立与此DataSource对象所表示的数据源的连接。 ConnectiongetConnection(Stringusername,Stringpassword) AttemptstoestablishaconnectionwiththedatasourcethatthisDataSourceobjectrepresents. 尝试建立与此DataSource对象所表示的数据源的连接。 实现以上的两个方法: 1.基本实现–生成标准的Connection对象。 2.连接池实现–生成自动参与连接池的Connection对象。 此实现与中间层连接池管理器一起使用。 实现代码: publicclassMyDataSourceimplementsDataSource{ //1: 声明池对象 privateLinkedList newLinkedList //2: 为了向pool中放connection必须要只,能通过构造初始化多个连接 publicMyDataSource(){ try{ Propertiesp= newProperties(); InputStreamin= MyDataSource.class.getClassLoader() .getResourceAsStream("jdbc.properties"); p.load(in); Stringdriver=p.getProperty("d"); Stringurl=p.getProperty("u"); Stringnm=p.getProperty("n"); Stringpwd=p.getProperty("p"); Integersize=Integer.valueOf(p.getProperty("s")); //创建多个连接 for(inti=0;i finalConnectioncon=//原生对象,即没有被代理的,但准备被代理的-华仔 DriverManager.getConnection(url,nm,pwd); //声明代理类 ObjectconnProxy= Proxy.newProxyInstance( ConnPool.class.getClassLoader(), newClass[]{Connection.class}, newInvocationHandler(){ publicObjectinvoke(Objectproxy,Methodmethod,Object[]args) throwsThrowable{ if(method.getName().equals("close")){ System.err.println("有人还连接了"); synchronized(pool){ //由于proxy就是connProxy,所以直接就将proxy添加回去就可以 pool.addLast((Connection)proxy); pool.notify(); } returnnull; }else{ //如果调用的不是close方法则直接调用原生对象的方法即放行 returnmethod.invoke(con,args); } } }); //将代理类,即经济人放到List中 pool.add((Connection)connProxy); } }catch(Exceptione){ e.printStackTrace(); } } publicConnectiongetConnection()throwsSQLException{ synchronized(pool){ //计算时间的开始 longstart=System.currentTimeMillis(); while(pool.size()==0){ //进入等待池 System.err.println("取一次: "+Thread.currentThread().getName()); try{ pool.wait(1000); }catch(InterruptedExceptione){ e.printStackTrace(); } //计算时间是否超过了三秒 longpro=System.currentTimeMillis()-start; if(pro>3000){ System.err.println("已经超过3秒超时,放弃"); thrownewRuntimeException("时间超时了"); } } System.err.println(pool.size()); Connectioncon=pool.removeFirst(); returncon; } } 如何使用: 通过第三方框架连接数据库 由于操作数据库,管理连接池,回收连接是JDBC必须要做的事,所以就有了第三方框架。 目前比较流行的连接池框架: ●dbcp-apache公司的dbcp=DataBaseConnectionPool版本1.2 ●c3p0–0.9.1.2 ●proxool–1.1 dbcp数据源 第一步: 导包 第二步: dbcp核心类–声明一个类,用核心类连接数据库 BasicDataSource–它是javax.sql.DataSource子类。 对DataSource来说,它只是一个池,至于里面有没有连接,能不能连接到数据库,必须要通过dataSource.getConnection()测试。 如果只判断dataSource是否为null是不能确定是否连接数据库成功与否的。 c3p0数据源 c3p0的核心类: ComboPooledDataSource–通过读取一个配置文件–配置文件必须是classpath: c3p0-config.xml 第一步: 导包 第二步: 准备c3p0配置文件 第三步: 配置连接数据库的数据 xmlversion="1.0"encoding="UTF-8"? > --必须以c3p0-config开始--> --在c3p0的配置文件中没有dtd定义--> --必须要包含默认的配置项目--> --配置驱动器--> [CDATA[jdbc: mysql: //127.0.0.1: 3306/day14? useUnicode=true&characterEncoding=UTF-8]]> --初始化个数--> --最少有多少个连接--> --最多有多少个--> --如果池中数据连接不够时一次增长多少个--> --一个连接每一次最多执行多少个sql语句--> 第四步: 书写一个类,创建ComboPooledDataSource实例 publicclassDataSouceUtils{ //1: 声明ds的成员,一个项目中只要有一个ds就可以了 privatestaticDataSourceds; //2: 在静态代码块中 static{ //如果直接实例化cpds则默认读取c3p0-config.xml中的默认配置 //如果带有参数,就会读取命名的配置 ds=newComboPooledDataSource(); } //3: 提供一个静态方法返回ds实例 publicstaticDataSourcegetDataSource(){ returnds; } } dbutils 定义 dbutils就是一个小型的hibenate。 就是将用户的CRUD工作都全部给封装了,用户通过简单的调用,就可以实现原来所有JDBC的一些功能。 (将statement.Query,execute,executeUpdate给封装了) dbutils核心类 ●QueryRunner,核心查询的类(select,update,delete,insert),相
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 代理 实现 连接 第三 Dbutilsc3p0
![提示](https://static.bdocx.com/images/bang_tan.gif)