一、数据库连接池
为了避免每次访问数据库的时候都需要重新建立新的连接而影响运行速度,如果网站访问量比较大,极容易造成内存溢出,在实际的项目中必须使用数据库连接池来提高数据库的访问效率。
当用户在使用连接池获取链接后,一般都会调用Connection.close()方法,关闭链接。而我们需要的是把链接还回池中
装饰设计模式编码步骤
1、编写一个类,实现与被包装类相同的接口(包装类和原有类有着相同的行为)
2、定义一个变量,引用原有类的实例
3、定义构造方法,把原有类的实例注入进来
4、对于要改变的方法,编写自己的代码
5、对于不需要改变的方法,调用原有类的对应方法。
1. 连接池代码实现 装饰模式+适配器 实现
1.适配器类
//实现适配器包装类不做任何改变
//适配器 类步骤
/*1、编写一个类,实现与被包装类相同的接口(包装类和原有类有着相同的行为)
* 2、定义一个变量
* 3、定义构造方法,把原有类的实例注入进来
* 4、全部调用原有类的对应方法
*/<span style="color:#ff0000;">
</span>public class ConnectionAdapter implements Connection{
private Connection conn;
public ConnectionAdapter(Connection conn){
this.conn=conn;
}
@Override
public <T> T unwrap(Class<T> iface) throws SQLException {
// TODO Auto-generated method stub
return conn.unwrap(iface);
} <span style="color:#ff0000;"> 略......</span>
2.装饰
public class MyConnection extends ConnectionAdapter {
//通过继承一个适配器类
/* 装饰模式的编写的另外一种形式:(类即是包装类,又是子类)
* 编码步骤
1、编写一个类,继承已经实现了接口的包装类
2、定义一个变量,引用原有类的实例
3、定义构造方法,把原有类的实例注入进来
4、对于要改变的方法,编写自己的代码
*/
public MyConnection(Connection conn) {
super(conn);
}
private Connection conn<span style="color:#3333ff;">;//引用原有类的实例</span>
private List<Connection>pool;<span style="color:#3333ff;">//连接池</span>
public void Myconnection (Connection conn,List<Connection>pool){
this.conn=conn;
this.pool=pool;
}
@Override
public void close() throws SQLException {
pool.add(conn); //<span style="color: rgb(51, 51, 255); font-family: 宋体; font-size: 14px;">关闭链接。而我们需要的是把链接还回池中</span>
super.close();
}
}
二 、 动态代理
代理是一种常用的设计模式,其目的就是为其他对象提供一个代理以控制对某个对象的访问。代理类负责为委托类预处理消息,过滤消息并转发消息,以及进行消息被委托类执行后的后续处理。
主要用来做方法的增强,让你可以在不修改源码的情况下,增强一些方法,
基于接口的动态代理:Proxy
被代理对象一定要实现了某个接口。
动态代理代码体现
1.接口
public interface Person {
void sing(float money);
void playgame(float money);
void sleep();
}
2.实现接口
public class SpringBrother implements Person {
public void sing(float money) {
System.out.println("拿到钱:"+money+"唱歌");
}
public void playgame(float money) {
System.out.println("拿到钱:"+money+"玩游戏");
}
public void sleep() {
System.out.println("睡觉");
}
}
3.代理
<span style="color:#3333ff;">public class ProxyTest {
public static void main(String[] args) {
final Person p =new SpringBrother();//原有对象
<span style="color:#3366ff;"> </span><span style="color:#ff0000;">//动态代理 </span><span style="color:#3333ff;">基于接口的动态代理</span><span style="color:#ff0000;">
/*创建动态代理方法
* newProxyInstance(ClassLoader loader Class<?> interface,InvocationHandler h);
* classLoader loader:代理类需要用到的类加载器。和被代理对象使用相同加载器就可以了
* class<?> [] interface:代理类需要实现的接口.固定写法
* InvocationHandler h :策略设计模式.</span><span style="color:#3333ff;">
*/</span>
Person proxyPerson=(Person)Proxy.newProxyInstance(p.getClass().getClassLoader(),p.getClass().getInterfaces(), new InvocationHandler() {
</span><span style="color:#ff0000;">/<span style="color:#3366ff;">*调用代理类的方法都会调用这个方法</span>
Object invoke(Object proxy, Method method, Object[] args)
<span style="color:#3366ff;"> Object proxy:对代理对象的引用
method:当前执行的方法对象。
args:当前方法用到的参数
返回值:当前方法执行的返回值
*/</span><span style="color:#3333ff;"></span>
</span>if("sing".equals(method.getName())){
<span style="white-space:pre"> </span>float money=(Float)args[0]; <span style="color:#ff0000;">//sing的值必须是大于100才只执行</span>
<span style="white-space:pre"> </span> if(money>100){
<span style="white-space:pre"> </span> return method.invoke(p, money/2);
<span style="white-space:pre"> </span> }<span style="white-space:pre"> </span>
<span style="white-space:pre"> </span> return null;
<span style="white-space:pre"> </span> }<span style="white-space:pre"> </span>
<span style="white-space:pre"> </span> else{
<span style="white-space:pre"> </span> return method.invoke(p, args); <span style="color:#ff0000;">//其他方法照常运行</span>
<span style="white-space:pre"> </span> }<span style="white-space:pre"> </span>
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>});
<span style="white-space:pre"> </span>proxyPerson.sing(101);
<span style="white-space:pre"> </span>proxyPerson.sleep();
<span style="white-space:pre"> </span>}<span style="color:#3333ff;">
</span>
基于子类的动态代理:需要借助第三方开发包CGLIB
代码体现
1.
public class SpringBrother {
public void sing(float money) {
System.out.println("拿到钱:"+money+"唱歌");
}
public void playgame(float money) {
System.out.println("拿到钱:"+money+"玩游戏");
}
public void sleep() {
System.out.println("睡觉");
}
}
2代理
public class ProxyTest {
public static void main( String[] args) {<span style="color:#ff0000;">
final SpringBrother p = new SpringBrother();// 原有对象
// 基于子类代理的动态代理 :代理类是被代理类的子类
/*
* 使用Enhancer.create(Class type,Cllback callback); Class
* type:代理类的父类型(被代理类的类型)
*
* Callback callback:如何处理
*/
</span> SpringBrother proxyPerson = (SpringBrother) Enhancer.create(
SpringBrother.class, new MethodInterceptor() {
public Object intercept(Object proxy, Method method,
Object[] args, MethodProxy arg3) throws Throwable {
if ("sing".equals(method.getName())) {
float money = (Float) args[0];
if (money > 1000) {
//money大于1000才执行
return method.invoke(p, money/2);
}
return null;
} else {
return method.invoke(p, args);
}
}
});
proxyPerson.sing(1010);
proxyPerson.sleep();
}
}
三、开源数据包的使用
DBCP database conncetion poll
编码步骤
1.需要的jar:commons-dbcp.jar commons-pool.jar
2.设置配置文件
3.编写一个工具类
DBCP实现代码
public class DbcpUtil {
private static DataSource dataSource;
static {
try {
InputStream in = DbcpUtil.class.getClassLoader()
.getResourceAsStream("dbcpconfig.properties");
Properties props = new Properties();
props.load(in);
dataSource = BasicDataSourceFactory.createDataSource(props);
} catch (Exception e) {
e.printStackTrace();
}
}
public static Connection getConnection() {
try {
return dataSource.getConnection();
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
public static DataSource getDataSource() {
return dataSource;
}
public static void release(ResultSet rs, Statement stmt, Connection conn) {
if (rs != null) {
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
rs = null;
}
if (stmt != null) {
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
stmt = null;
}
if (conn != null) {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
conn = null;
}
}
C3P0
需要jar包 cp30
配置文件 可以是xml properties
实现代码
public class C3P0Util {
private static ComboPooledDataSource dataSource = new ComboPooledDataSource();<span style="color:#ff0000;">//构造方法可以传入配置文件名称进行加载 没有就默认 配置文件的名称规范的 </span>
public static Connection getConnection() {
try {
return dataSource.getConnection();
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
public static DataSource getDataSource(){
return dataSource;
}
public static void release(ResultSet rs,Statement stmt,Connection conn){
if(rs!=null){
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
rs=null;
}
if(stmt!=null){
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
stmt=null;
}
if(conn!=null){
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
conn=null;
}
}
C3P0属性文件 XML xml名称c3p0-config.xml
<?xml version="1.0" encoding="UTF-8"?>
<c3p0-config>
<default-config> <span style="color:#ff0000;">C3P0<a target=_blank href="http://www.open-open.com/lib/view/open1403403349127.html">配置文件属性详细</a>信息</span>
<property name="driverClass">com.mysql.jdbc.Driver</property>
<property name="jdbcUrl">jdbc:mysql://localhost:3306/test</property> <span style="color:#ff0000;"> </span>
<property name="user">root</property>
<property name="password">sorry</property>
<property name="initialPoolSize">10</property>
<property name="maxIdleTime">30</property>
<property name="maxPoolSize">100</property>
<property name="minPoolSize">10</property>
<property name="maxStatements">200</property>
</default-config>
<named-config name="abc">
<property name="acquireIncrement">50</property>
<property name="initialPoolSize">100</property>
<property name="minPoolSize">50</property>
<property name="maxPoolSize">1000</property>
<property name="maxStatements">0</property>
</named-config>
</c3p0-config>
(Java Naming and Directory Interface),Java命名和目录接口,它对应于J2SE中的javax.naming包,
这套API的主要作用在于:它可以把Java对象放在一个容器中(JNDI容器),并为容器中的java对象取一个名称,以后程序想获得Java对象,只需通过名称检索即可。
一般服务器通过JDNI存储数据源
编码步骤
a 首先把数据库驱动复制到Tomcat/lib目录中
b 在应用META-INF目录下,建立一个固定context.xml配置文件内容如下
<span style="color:#3333ff;"><?xml version="1.0" encoding="UTF-8"?>
<Context>
<Resource name="jdbc/day17" auth="Container" type="javax.sql.DataSource"
maxActive="100" maxIdle="30" maxWait="10000"
username="root" password="sorry" driverClassName="com.mysql.jdbc.Driver"
url="jdbc:mysql://localhost:3306/day17"/>
</Context></span>
c、部署应用、启动tomcat,服务器就会按照配置在JNDI容器中注册数据源的实例。
d、获取数据源 不能在java中运行因为会在jvm中运行 要在jsp或者servlet 因为在tomcat中运行才能拿到数据源 代码如下
利用JNDI的API(JDK:javax.naming.*)把数据源根据path+name查询出来
<%
Context initContext= new InitialContext();
Context envContext=(Context)initContext.lookup("java://comp/env");<span style="color:#3333ff;">//这里是tomcat绑定的path</span>
DataSource ds =(DataSource)envContext.lookup("jdbc/day17");
Connection conn=ds.getConnection();
System.out.println(conn);
%>
五、数据库元信息的获取
数据库元信息是指 数据库、表的定义信息
用于编写框架
方法
Connection.getMetaData()
DataBaseMetaData对象
getURL():返回一个String类对象,代表数据库的URL。
getUserName():返回连接当前数据库管理系统的用户名。
getDatabaseProductName():返回数据库的产品名称。
getDatabaseProductVersion():返回数据库的版本号。
getDriverName():返回驱动驱动程序的名称。
getDriverVersion():返回驱动程序的版本号。
isReadOnly():返回一个boolean值,指示数据库是否只允许读操作。