关于JSP的连接池的问题?

侯斌 2007-05-17 08:03:45
同一个连接使用次数过多,将会导致连接的不稳定,进而会导致WEB SERVER的频频重启。因此就需要用到连接池。
那里连接池怎么建立咯。连接池内部的管理怎么做咯!!

急急急急急急急急急急急急急!!!!!!!!!!!
...全文
555 12 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
12 条回复
切换为时间正序
请发表友善的回复…
发表回复
difeng 2007-08-31
  • 打赏
  • 举报
回复
http://www.ourjava.net/database/2007-07-04/1277.html
luowenwei 2007-05-23
  • 打赏
  • 举报
回复
同意
chinanb 2007-05-23
  • 打赏
  • 举报
回复
版本太多了 最好还是用hibernate最方便了
MrJober 2007-05-23
  • 打赏
  • 举报
回复
数据库连接池技术原理
2007年04月17日 星期二 11:28
浅析(一)

在执行数据库SQL语句时,我们先要进行数据连接;而每次创建新的数据库的连接要消耗大量的资源,这样,大家就想出了数据库连接池技术。它的原理是,在运行过程中,同时打开着一定数量的数据库连接,形成数据连接池,当需要用到数据连接时,就从中取出一个连接,完成某些SQL操作后,系统自动回收,以供其它用户(或进程)调用。


我们知道,java标准的java.sql.Connection表示一个数据连接。我们封装了这个类,形成自己的数据库连接池。为了说明方便,这里用实际的类来显示:

DBConnectionPool 真正的数据连接池

DBConnectionManager 对多个池进行管理



实际执行过程:

1) 新建一个DBConnectionManager类的实例。

2) 然后调用DBConnectionManager. CreatePool()创建一个连接池,并把这个连接池加入到pools的HasthTable中。(这种过程可执行多次,对应不同的数据连接,可能是sql2k的,也可能是oracle的,但生成的DBConnectionPool都要放到pools中进行统一管理,用并用一个名字与相应的DBConnectionPool对应起来)。

3) 当需要数据连接时,首先得到一个DBConnectionPool,然后从DBConnectionPool中看有没有空闲的连接,如果有,则使用。如果没有,显没过最大连接数,则创建一个Connection连接,并返回这上连接。

4) 如果某个连接使用完毕,则调用DBConnectionManager.freeConnection(String name, Connection con),它又调用DBConnectionPool. freeConnection(Connection con),此时,连接并不真正释放,而是把这个暂时不用的Connection放到DBConnectionPool的freeConnections数组中(同时,通知其它正在等待连接的线程。这样,以后要用时,就不用再新建Connection。



浅析(二)
一般情况下,在使用开发基于数据库的WEB程序时,传统的模式基本是按以下步骤:
   1. 在主程序(如Servlet、Beans)中建立数据库连接。
   2. 进行SQL操作,取出数据。
   3. 断开数据库连接。
   使用这种模式开发,存在很多问题。首先,我们要为每一次WEB请求(例如察看某一篇文章的内容)建立一次数据库连接,对于一次或几次操作来讲,或许你觉察不到系统的开销,但是,对于WEB程序来讲,即使在某一较短的时间段内,其操作请求数也远远不是一两次,而是数十上百次(想想全世界的网友都有可能在您的网页上查找资料),在这种情况下,系统开销是相当大的。事实上,在一个基于数据库的WEB系统中,建立数据库连接的操作将是系统中代价最大的操作之一。很多时候,可能您的网站速度瓶颈就在于此。
   其次,使用传统的模式,你必须去管理每一个连接,确保他们能被正确关闭,如果出现程序异常而导致某些连接未能关闭,将导致数据库系统中的内存泄露,最终我们将不得不重启数据库。
   针对以上问题,我们首先想到可以采用一个全局的Connection对象,创建后就不关闭,以后程序一直使用它,这样就不存在每次创建、关闭连接的问题了。但是,同一个连接使用次数过多,将会导致连接的不稳定,进而会导致WEB SERVER的频频重启。故而,这种方法也不可取。实际上,我们可以使用连接池技术来解决上述问题。首先,介绍一下连接池技术的基本原理。顾名思义,连接池最基本的思想就是预先建立一些连接放置于内存对象中以备使用:

   如图所示,当程序中需要建立数据库连接时,只须从内存中取一个来用而不用新建。同样,使用完毕后,只需放回内存即可。而连接的建立、断开都有连接池自身来管理。同时,我们还可以通过设置连接池的参数来控制连接池中的连接数、每个连接的最大使用次数等等。通过使用连接池,将大大提高程序效率,同时,我们可以通过其自身的管理机制来监视数据库连接的数量、使用情况等。下面我们以一个名为ConnectionPool的连接池为例来看看连接池的实现。先看看ConnectionPool的基本属性:
   m_ConnectionPoolSize:连接池中连接数量下限
   m_ConnectionPoolMax:连接池中连接数量上限
   m_ConnectionUseCount:一个连接的最大使用次数
   m_ConnectionTimeout:一个连接的最长空闲时间
   m_MaxConnections = -1:同一时间的最大连接数
   m_timer:定时器
   这些属性定义了连接池与其中的每个连接的有效状态值。连接池的自我管理,实际上就是通过定时的对每个连接的状态、连接的数量进行判断而进行相应操作。其管理流程如下:

通过上图,我们可以定义出ConnectionPool要完成管理所需要的基本接口:
public class ConnectionPool implements TimerListener{
   public boolean initialize() //连接池初始化
   public void destroy() //连接池的销毁
   public synchronized java.sql.Connection getConnection() //取一个连接
   public synchronized void close() //关闭一个连接
   private synchronized void removeFromPool() //把一个连接从连接池中删除
   private synchronized void fillPool() //维护连接池大小
   public synchronized void TimerEvent() //定时器事件处理函数
}
   通过这几个接口,已经可以完成连接池的基本管理。在TimeEvent()函数中完成连接池的状态检验工作,fillPool()时连接池至少保持最小连接数。因为我们要保存每一个连接的状态,所以还需要一个数据库连接对象:
class ConnectionObject{
   public java.sql.Connection con; public boolean inUse; //是否被使用标志
   public long lastAccess; //最近一次开始使用时间
   public int useCount; //被使用次数
}
加入了ConnectionObject对象后,在ConnectionPool中操作的应该只是ConnectionObject,而其他进程需要的只是ConnectionObject的con属性,因此我们再加入一个类,作为其他进程获得与返回连接的接口: CLASS Conn{
   GetConnection(); //从连接池中取出一个有效连接
   CloseConnection(); //返回连接,此时并没有关闭连接,只是放回了连接池
   DestroyPool(); //销毁连接池
}
   最后我们的整个系统总的架构如下:

   通过上面的介绍,我们可以看出,连接池技术的关键就是其自身的管理机制,以上的管理流程只是本人一点见解,关键是想向大家介绍一种思路,在此基础上,您可以进一步完善连接池技术为您所用。

侯斌 2007-05-20
  • 打赏
  • 举报
回复
不是有一种方法是这样的吗?
InitialContext ctx=new InitialContext();
ConnectionPoolDataSource ds=(ConnectionPoolDataSource)ctx.lookup("jdbc/WroxDB");
Connection con=ds.getPooledConnection("User","Password");
它是以ConnectionPoolDataSource作为连接池是吗?
而javaboy2006(喝着coffee学java)说的哪个是我们自己写的连接池,是吗?
shantang1984 2007-05-17
  • 打赏
  • 举报
回复
大多数服务器都可以配置连接池的,在网上一般都能搜到!
javaboy2006 2007-05-17
  • 打赏
  • 举报
回复
以前用过的一个简单连接池实现:

***************** DBConnPool.java *********************
import java.sql.*;
import java.util.*;

/*连接池类.能够根据要求创建新连接,直到最大连接数为止.*/
public class DBConnPool {
//实际使用中的连接数
public int inUse = 0;
//空闲连接
private Vector connections = new Vector();
//连接池名
private String poolname;
//数据库标识
private String dbid;
//驱动程序名
private String drivername;
//数据库账号
private String username;
//数据库密码
private String passwd;
//最大连接数
private int maxconn;

public DBConnPool(String poolname, String drivername, String dbid,
String username, String passwd, int maxconn) {
this.poolname = poolname;
this.dbid = dbid;
this.drivername = drivername;
this.username = username;
this.passwd = passwd;
this.maxconn = maxconn;
}

/*将连接返回给连接池*/
public synchronized void releaseConnection(Connection con) {
// 将指定连接加入到向量末尾
connections.addElement(con);
//连接数减一
inUse--;
}

/*从连接池得到一个连接*/
public synchronized Connection getConnection() {
Connection con = null;
if (connections.size() > 0) {
// 获取连接列表中获得第一个连接
con = (Connection) connections.elementAt(0);
connections.removeElementAt(0);
//如果此连接已关闭,则继续获取
try {
if (con.isClosed()) {
con = getConnection();
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
//如果实际使用的连接小于最大连接数,就新创建一个连接
else if (maxconn == 0 || inUse < maxconn) {
con = newConnection();
}
if (con != null) {
//连接数增一
inUse++;
}
//返回一个连接
return con;
}

/*创建新的连接*/
private Connection newConnection() {
Connection con = null;
try {
//加载驱动程序
Class.forName(drivername);
//建立连接
con = DriverManager.getConnection(dbid, username, passwd);
System.out.println("连接池成功创建新连接!");
} catch (Exception e) {
e.printStackTrace();
return null;
}
//返回该连接
return con;
}

/*关闭所有连接*/
public synchronized void closeConn() {
Enumeration allConnections = connections.elements();
while (allConnections.hasMoreElements()) {
Connection con = (Connection) allConnections.nextElement();
try {
con.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
connections.removeAllElements();
System.out.println("连接池已关闭所有连接!");
}
}

***************** PoolManager.java *********************
import java.sql.*;
import java.util.*;

/*** 连接池管理类 ***/
public class PoolManager {

private static PoolManager instance;
//存放所有连接池的集合
private Hashtable pools = new Hashtable();

private PoolManager() {
//连接池名
String poolname = "mydbconpool";
//驱动程序名
String drivername = "sun.jdbc.odbc.JdbcOdbcDriver";
//数据库标识
String dbid = "jdbc:odbc:ds";
//数据库账号
String username = "";
//数据库密码
String passwd = "";
//最大连接数
int maxconn = 10;

//创建一个连接池
createPool(poolname, drivername, dbid, username, passwd, maxconn);
}

/*** 获得连接池管理类实例 ***/
public static synchronized PoolManager getInstance() {
if (instance == null) {
instance = new PoolManager();
}
return instance;
}

/*** 创建连接池 ***/
private void createPool(String poolname, String drivername, String dbid,
String username, String passwd, int maxconn) {
DBConnPool pool = new DBConnPool(poolname, drivername, dbid, username, passwd, maxconn);
pools.put(poolname, pool);
}

/*** 返回指定连接池中实际使用的连接数 ***/
public int getPoolinUse(String poolname) {
DBConnPool pool = (DBConnPool) pools.get(poolname);
return pool.inUse;
}

/*** 根据连接池名称返回其中一个连接对象 ***/
public Connection getConnection(String poolname) {
Connection con = null;
DBConnPool pool = (DBConnPool) pools.get(poolname);
if (pool != null) {
con = pool.getConnection();
}
return con;
}

/*** 释放一个连接对象到指定连接池中 ***/
public void releaseConnection(String poolname, Connection con) {
DBConnPool pool = (DBConnPool) pools.get(poolname);
if (pool != null) {
pool.releaseConnection(con);
}
}

/*** 关闭指定连接池中所有连接 ***/
public void closeConn(String poolname) {
DBConnPool pool = (DBConnPool) pools.get(poolname);
if (pool != null) {
pool.closeConn();
}
}
}

聪头 2007-05-17
  • 打赏
  • 举报
回复
像tomcat、resin等都有连接池的配置选项,比较方便。

如果用hibernate,支持很多连接池的配置。

连接池就是对与数据库的连接管理。控制最大同时连接个数,优化空闲连接个数,对请求与连接进行配对和排队处理等。可以自己写连接池管理程序。
yksky 2007-05-17
  • 打赏
  • 举报
回复
呵呵,原来我也用过这种方式,但是感觉很不方便,比如说:现在要将tomcat下的程序移植到其他的web容器下,如WebLogic,Resin等等,就又要重新配置了,感觉很麻烦,而且,又容易出错;现在,我一般都是利用连接池来对数据库进行操作,这样,就与具体的web容器无关了
shantang1984 2007-05-17
  • 打赏
  • 举报
回复
tomcat容器下:
可以在server.xml配置数据源,在程序中就可以去取,不用自己去管理了!...
server.xml
在<host>里面加入:
<Context docBase="DaxWebMonitor" path="/path"
reloadable="true"
source="org.eclipse.jst.j2ee.server:path">
<Resource name="jdbc/myoracle" auth="Container"
type="javax.sql.DataSource" />

<ResourceParams name="jdbc/myoracle">
<parameter>
<name>factory</name>
<value>
org.apache.commons.dbcp.BasicDataSourceFactory
</value>
</parameter>
<parameter>
<name>driverClassName</name>
<value>
oracle.jdbc.driver.OracleDriver
</value>
</parameter>
<parameter>
<name>url</name>
<value>
jdbc:oracle:thin:@ip:1521:db
</value>
</parameter>
<parameter>
<name>username</name>
<value>username</value>
</parameter>
<parameter>
<name>password</name>
<value>password</value>
</parameter>
<parameter>
<name>maxActive</name>
<value>20</value>
</parameter>
<parameter>
<name>maxIdle</name>
<value>10</value>
</parameter>
<parameter>
<name>maxWait</name>
<value>-1</value>
</parameter>
</ResourceParams>
</Context>


web.xml加入引用:
<resource-ref>
<description>Oracle Datasource</description>
<res-ref-name>jdbc/myoracle</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
</resource-ref>

在你的代码里如下去取:
initContext = new InitialContext();
Context envContext = (Context) initContext.lookup("java:/comp/env");
DataSource ds = (DataSource) envContext.lookup("jdbc/myoracle");
conn= ds.getConnection();

用完就用conn.close释放连接!
完毕!
当然你也可以自己去实现一个自己的连接池......
佳岳 2007-05-17
  • 打赏
  • 举报
回复
在什么容器下呢
yksky 2007-05-17
  • 打赏
  • 举报
回复
1:利用DBCP,c3p0等开源连接池直接进行工作
2:利用google搜一下,自己些个连接池

81,122

社区成员

发帖
与我相关
我的任务
社区描述
Java Web 开发
社区管理员
  • Web 开发社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧