对于自己的服务器程序是自己编写的,现在还在测试阶段,还对于数据库的连接,考虑到服务器多并发,连接池的应用肯定是
必要的。现在很多连接池框架,可是总感觉挺别扭,与是还是决定自己写。
连接池的主要作用是为了减少重复连接数据库以及重复建立与销毁数据库连接所花费的代价与资源。还连接池可以建立一定量
的连接数,每次用完一个连接把连接返回给连接池,等有新的请求时再分配给另外的请求,这样从而达到重复利用的连接的效果。还
连接池只是一个管理连接的功能。
实现连接池的关键是每次只关闭时只是把连接返回到连接池中去,还不是关闭物理连接。还要达到这种功能,网上的资料一般有
两种解决方法,一种是通过动态代理的方式,接管connection 返回的对象,当connection掉用close方法时,InvocationHandler的
invoke方法会检测到,则把连接返回到池中即可。如果非close方式,则返回con对象。第二种是重写connection方式。我实现连接池
时用的第一种方式,第二种方式没实现,不知道是否可行。!
具体实现代码如下:(注意,我的数据是sqlserver2005,其连接数据库的方式跟2000有一些区别)
首先代码是一个InvocationHandler接口,接管connection返回对象的一个类。
import java.sql.Connection;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
import java.lang.reflect.Method;
public class ConnectionHandler implements InvocationHandler{
private final String close_Method_Name = "close";//方法名
//false为正闲
private boolean inuse = false;//是否可用
private Connection con = null;
public ConnectionHandler(Connection conn,boolean inuse){
this.con = conn;
this.inuse = inuse;
}
/**
*
*返回数据库连接con的接管类,以便截住close
*
**/
public Connection getConnection(){
Connection con1 = (Connection)Proxy.newProxyInstance(
con.getClass().getClassLoader(),
con.getClass().getInterfaces(),this);
return con1;
}
/**
*
*直接关闭连接,由于con没有被接管的属性,直接关闭
*
**/
public void close(){
try{
con.close();
}catch(Exception e){
e.printStackTrace();
}
}
/**
*
*当此代理类被创建对像被掉用时,首先会执行invoke方法
*
**/
public Object invoke(Object proxy,Method m,Object[] o){
Object obj = null;
try{
if(close_Method_Name.equals(m.getName())){
this.setInuse(false);//返回到连接池
}else{
obj = m.invoke(con,o);//直接返回没有接管的对象con
}
}catch(Exception e){
e.printStackTrace();
}
return obj;
}
/**
*
*设置inuse
*
**/
public void setInuse(boolean b){
this.inuse = b;
}
/**
*
*得到inuse
*
**/
public boolean isInuse(){
return this.inuse;
}
}
接着是实现连接池的类:DCSLinkPool.java:
import java.sql.Connection;
import java.sql.Driver;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Enumeration;
import java.util.Vector;
public class DCSLinkPool{
private String dbDriver = "com.microsoft.sqlserver.jdbc.SQLServerDriver";//数据库驱动
private String dbUrl = "jdbc:sqlserver://127.0.0.1:1433;DataBaseName = dcs";//数据库URL
private String dbUsername = "dcs";//数据库用户名
private String dbPassword = "roiland";//数据库用户密码
private int maxconnections = 5;//最大数据库连接数,
private int curconnections = 1;//当前数据库连接数,如果当等于最大时,再需要连接时,则抛出异常
private Vector connections = null;
/**
*
*创建一个数据库连接池
*
**/
public synchronized void createPool(){
//如果连接池已创建,不会为空
if(connections != null){
return;
}
try{
Driver driver = (Driver)(Class.forName(this.dbDriver).newInstance());
DriverManager.registerDriver(driver);
//创建保存连接的向量
connections = new Vector();
for(int i = 0; i < this.curconnections; i++){
connections.addElement(new ConnectionHandler(newConnection(),false));
}
//连接池建立
}catch(Exception e){
e.printStackTrace();
}
}
/**
*
*创建一个connection
*
*
*/
public Connection newConnection(){
Connection connection = null;
try{
System.out.println("创建一次");
connection = DriverManager.getConnection(dbUrl,dbUsername,dbPassword);
}catch(Exception e){
e.printStackTrace();
}
return connection;
}
/**
*
*返回一个连接,如果当前连接数小于最大的连接时,增加一个新的连接
*
**/
public Connection getConnection(){
Connection con = this.getFreeConnection();
if(con == null){//如果连接池已满
if(this.curconnections < this.maxconnections){
Connection con1 = this.newConnection();
ConnectionHandler cons1 = new ConnectionHandler(con1,true);
synchronized(connections){//实现同步
connections.addElement(cons1);//创建一个新的连接
this.curconnections++;//当前连接池中的连接数增加一个。
}
con = cons1.getConnection();
}else{
try{
throw new SQLException("连接数已经达到最大");
}catch(Exception e){
e.printStackTrace();
}
}
}//end if(con == null)
return con;
}
/**
*
*返回一个可用连接的连接
*
**/
public synchronized Connection getFreeConnection(){
Connection con = null;
ConnectionHandler pcon = null;
try{
//得确保连接池已经创建
if(connections == null){
return null;//连接池还没创建
}
Enumeration it = this.connections.elements();
while(it.hasMoreElements()){
pcon = (ConnectionHandler)it.nextElement();
if(!pcon.isInuse()){//如果可用
con = pcon.getConnection();//闲时返回其状态
System.out.println("con"+con);
pcon.setInuse(true);//设置其已经不可用
break;
}
}//end while
}catch(Exception e){
e.printStackTrace();
}
//如果没用,则返回一个null
return con;
}
/**
*
*返回当前连接数
*
**/
public int getCurlinks(){
return this.curconnections;
}
/*
public static void main(String[] args){
DCSLinkPool pool = new DCSLinkPool();
pool.createPool();
Connection c = pool.getConnection();
}*/
}
以上连接池的建立,我经过测试,当数据在十几个并发时,数据库中一个连接数就可以完全处理,至于更多我没有进行过测试,。本
人的服务器以后可能会有上千甚至上万,几十万的并发。此时连接池肯定是必要的。但是一个连接能处理多少个并发连接?我知道
sqlserver2005的连接并发数可以是无限制,但在程序中是否可以设置连接数到多大?这两问题我将会在接下来的日子解决。
总的来说,此连接池是在别人的基础上开发出来的。只能算是一个连接池模型,相信连接池框架在处理上会好的多。
比如说:当本连接池中连接数满时,但当前连接数还没达到最大时,本连接池是自动增加一个连接,如果在多并发中可能会一次增加
五个或者更多,这时跟据具体情况来定吧。