【毕业设计】JSP数据库连接池的研究与实现(源代码+论文)

29 篇文章 1 订阅
17 篇文章 3 订阅


目录

在这里插入图片描述

系统设计

数据库连接池技术的设计思想非常简单,先将数据库连接作为对象存储在一个Vector对象中,Vector 类可以实现可增长的对象“数组”。Vector 的大小可以根据需要增大或缩小,以适应创建 Vector 后进行添加或移除项的操作。这里主要包含使用的连接(nowConnections)和未使用的连接(freeConnections)两个Vector类创建的对象,创建Vector对象的方法如下:

public DBConnectionPool(Vectorconnections)
{
freeConnections = new Vector();
nowConnections = new Vector();
}

当外部程序向数据库申请建立连接后,系统会调用nowConnections.add( )方法,此时已用连接计数器加1,相应的,调用freeConnections.remove( )方法,此时空闲连接计数器减1,对于这样的引用计数法将会在后面的章节中具体描述。这样,不同的数据库访问请求就可以共享这些连接,并通过复用这些已经建立的数据库连接,克服传统开发模式对数据库操作的缺点。另外,采用超时判断(timeout)机制,等待应用程序对连接的释放或者调用Connection.close()方法主动释放连接,能极大地节省系统资源和用户等待时间。而实现连接池时,当应用程序调用Connection.close( )试图去关闭数据库连接时,这时需要有一个通告给连接池实现模块,通告对当前的数据库物理连接(DBConnectionPool 对象)进行重用。为了使连接池实现模块能得到这种“通告”,连接池实现模块必须实现ConnectionEventListener接口,而且同时需要注册成为DBConnectionPool对象的监听者。连接池实现模块接受到此通告后,不是真正意义上的物理关闭,而是将DBConnectionPool对象返回到池中进行重用。从上面的介绍,可以看出连接池技术的关键就是其自身的管理机制,结合连接池工作的基本原理,通过下图展现出一个连接池系统的总体设计框架。
在这里插入图片描述
1.1 连接池中的关键类设计
一个连接池应用的设计,需要几个关键部分作为支撑,其中最为重要的是DBConnectionPool类和DBConnectionManager类,他们对连接的建立、管理、释放起决定性作用。大体作用列举如下:

1、一个DBConnectionPool类,该类负责从连接池获取(或创建)连接、将连接返回给连接池、空闲连接的超时等待、系统关闭时释放所有资源并关闭所有连接。

2、一个DataSourceProviderServlet类,该类负责通过上下文环境读取配置文件后装载和注册JDBC驱动、数据库名等。

3、一个DBConnectionManager类,该类负责按预先指定的最大连接池数连初始化连接池、创建DBConnectionPool对象provider、当所有的连接客户退出后,关闭全部连接。

4、DBconfig.properties属性文件,该文件中包含了数据库驱动(DriverName)、数据库URL、数据库表空间名(User)、表空间密码(Password)、连接池最大连接数(maxConnections)。

5、即为应用程序对连接池中的连接的调用和释放,应用程序退出后连接池的关闭。

将以上5个部分串连起来,即是本连接池的简单设计流程。首先应用程序向连接池申请连接,就需要通过DBConnectionPool类、DBConnectionManager类对连接池初始化,并且还需要DataSourceProviderServlet类的帮助读取DBconfig.properties文件中的属性,加载和注册JDBC驱动、数据库名等,连接池才能初始化成功。之后通过DBConnectionPool类监视、管理应用程序调用、释放的数据库连接,并通过该类的cp对象将连接使用情况反映在页面上。连接池管理程序得到某个连接,而其他线程就不会得到这个数据库连接了,此线程使用结束后,该线程将连接交还给连接池管理程序,以分配给其他等待连接的请求线程。这里连接池充分利用Java的线程同步机理,使当前服务线程处于等待状态,直至有空闲的连接出现。最后当应用程序退出时,通过DBConnectionManager类负责连接池的关闭。

1.2 连接池中的管理机制
应用程序开发中“三分技术、七分管理”的思想在连接池的配置中同样得以体现,如何从连接池中取得连接,何时释放连接、如何释放连接等问题还需要为连接池配置更为复杂的管理机制,连接池流程的管理如下图所示,这些属性定义了连接池与其中每个连接的有效状态值。连接池的自我管理,实际上就是通过定时的对每个连接的状态、连接的数量进行判断而进行相应操作。
在这里插入图片描述

系统实现

1.1 连接池的建立
应用程序中建立的连接池其实是一个静态的。所谓静态连接池是指连接池中的连接在系统初始化时就已分配好,且不能随意关闭连接。Java中提供了很多容器类可以方便的构建连接池,如:Vector、Stack、Servlet、Bean等,通过读取连接属性文件DBconfig.properties与数据库实例建立连接。(该属性文件中包含了连接数据库的URL、数据库驱动、数据库表空间、数据库表空间密码、连接池最大连接数)在系统初始化时,根据相应的配置创建连接并放置在连接池中,这些对象作为系统可分配的自由连接,以后所使用的连接都是从连接池中获得,这样就避免了随意建立连接,关闭连接所带来的资源浪费。

连接池初始化如下:

publicDBConnectionPool(Vector connections)
{
FreeConnections = new Vector();
nowConnections = new Vector();
freeConnections = connections;
maxConnections =freeConnections.size();
}
本连接池的建立使用输入流,通过上下文环境,读取配置文件(Dbconfig.Prooperties)里预先设置的参数,部分代码如下:
public voidcontextInitialized(ServletContextEvent event)
{
Properties ps = new Properties();
Vector connections = new Vector();
ServletContext context =event.getServletContext();
try
{
//使用输入流,读取配置文件里的各种参数
InputStreaminput = getClass().getResourceAsStream("/DBconfig.properties");
ps.load(input);
input.close();
url = (String)ps.get(“url”);
user = (String)ps.get(“user”);
passWord = (String)ps.get(“passWord”);
DriverName = (String)ps.get(“DriverName”);
maxConnections=Integer.parseInt(((String)ps.get(“maxConnections”)).trim(), 10);
System.out.println(user);
//循环加入取得的连接到Vector中
for (int i = 0; i <maxConnections; i++)
{
//调用下面的方法,取得数据库连接,并放入到Vector中
connections.add(getConnection(url,user,passWord,DriverName));
}
}
catch (Exception e)
{
e.printStackTrace();
}
//放到服务器的上下文环境中
context.setAttribute(“CONNECTOR”,new DBConnectionPool(connections));
}

连接池初始化参数通过页面设置写入DBconfig.properties文件中,如下图所示:在这里插入图片描述
1.1 连接池的管理
连接池管理策略是连接池机制的核心。当连接池建立后,如何对连接池中的连接进行管理,解决好连接池内连接的分配和释放,对系统的性能有很大的影响。连接的合理分配、释放可提高连接的复用,降低了系统建立新连接的开销,同时也加速了用户的访问速度。下面介绍连接池中连接的分配、释放策略。

连接池的分配、释放策略对于有效复用连接非常重要。就一般情况而言,当客户释放数据库连接时,先判断该连接的引用次数是否超过了规定值,如果超过就删除该连接,并判断当前连接池内总的连接数是否小于minConn(最小连接数),若小于就将连接池充满;如果没超过就将该连接标记为开放状态,可供再次复用。可以看出正是这套策略保证了数据库连接的有效复用,避免频繁地建立、释放连接所带来的系统资源开销。我们采用的方法是一个很有名的设计模式:Reference Counting(引用记数)。该模式在复用资源方面应用的非常广泛,把该方法运用到对于连接的分配释放上,为每一个数据库连接,保留一个引用记数,用来记录该连接的使用者的个数。具体的实现方法是:

publicsynchronized Connection getConnection(int TimeOut)
{
Connection con = null;
if (freeConnections.size() <= 0)
{
System.out.println(“连接失败,由于数据库连接池中无可用连接!请等待!”);
try {
newDBConnectionManager().closeAll();
}
catch (Exception ex)
{
ex.printStackTrace();
}
return con;
}
else
{
Connection temp = (Connection)freeConnections.firstElement();
freeConnections.remove(temp);
nowConnections.add(temp);
return temp;
}
}

当应用程序向数据库发起连接请求时,会检查连接池中是否存在空闲的连接。如果存在空闲的连接,连接池则把空闲连接分配给客户,并将该连接做相应处理,即标记为正在使用的连接,并将引用计数加1。如果不存在空闲连接,则检查连接池里的连接数是否已经达到了最大连接数(maxConn),若没有达到就为应用程序创建一个新的连接;若达到了最大连接数,那么就需要等待连接的释放,等待连接的释放时间是由系统中预先定义好的一个超时参数(Timeout)来做判断。如果在超时等待(TimeOut)后仍没有可用的空间连接,程序上便会返回一个null值,同时抛出无空闲连接的异常给用户。

publicvoid TimeOut(int TimeOut, Connection con)
{
try {
Thread t = new Thread();
t.start();
t.run();
t.wait(TimeOut);
closeConnection(con);
t.destroy();
}
catch (Exception ex)
{
ex.printStackTrace();
}
}
已用连接计数器的问题交由JSP页面中的循环来处理,每当应用程序申请一个连接时,计数器便会循环一次,部分实现代码如下:
for(int i = 0; i < cp.getNowConnections().size(); i++)
{
out.println("<fontcolor=blue>连接名称" + (i + 1) + “:”+ cp.getNowConnections().get(i) + “
”);
con =(Connection)cp.getNowConnections().get(0);
}
对于未用连接的处理与已用连接类似,部分实现代码如下:
for(int j = 0; j < cp.getFreeConnections().size(); j++)
{
out.println("<fontcolor=blue>未用连接名称" + (j + 1) + “:”+ cp.getFreeConnections().get(j) + “
”);
}

连接池的调用如下图所示,若连接已分配完毕,系统提示等待连接释放
在这里插入图片描述

源文件

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值