原理: 在DataSource中事先建立多个数据库连接,保存在数据库连接池中。当程序访问数据库时,只用从连接池中取空闲状态的数据库连接即可,访问结束,销毁资源,数据库连接重新回到连接池,这与每次去直接访问数据库相比,会节省大量时间和资源。 JNDI( Java Naming and Directory Interface ),是Java平台的一个标准扩展,提供了一组接口、类和关于命名空间的概念。如同其它很多Java技术一样,JDNI是provider-based的技术,暴露了一个 API和一个服务供应接口(SPI)。这意味着任何基于名字的技术都能通过JNDI而提供服务,只要JNDI支持这项技术。JNDI目前所支持的技术包括 LDAP、CORBA Common Object Service(COS)名字服务、RMI、NDS、DNS、Windows注册表等等。很多J2EE技术,包括EJB都依靠JNDI来组织和定位实体。可以把它理解为一种将对象和名字捆绑的技术,对象工厂负责生产出对象,这些对象都和唯一的名字绑在一起,外部资源可以通过名字获得某对象的引用。
在javax.naming的包包中提供Context接口,提供了两个很好用的方法: <1> void bind( String name , Object object ) 将名称绑定到对象。所有中间上下文和目标上下文(由该名称最终原子组件以外的其他所有组件指定)都必须已经存在。
<2>Object lookup( String name )
检索指定的对象。如果 name为空,则返回此上下文的一个新实例(该实例表示与此上下文相同的命名上下文,但其环境可以独立地进行修改,而且可以并发访问)。
外部资源访问对象工厂中的工程图:
例: =================将以下代码段添加到server.xml中的<Host>中============
- <!-- configure DataSource. Add the following code into server.xml -->
<Context path="/bookstore" docBase="bookstore" debug="0" reloadable="true" >
<!-- 数据源名称 --> <Resource name="jdbc/BookDB" auth="Container" type="javax.sql.DataSource" />
<ResourceParams name="jdbc/BookDB"> <parameter> <name>factory</name> <value>org.apache.commons.dbcp.BasicDataSourceFactory</value> </parameter>
<!-- Maximum number of dB connections in pool. Make sure you configure your mysqld max_connections large enough to handle all of your db connections. Set to 0 for no limit. -->
- <!-- 活动状态最大连接数 -->
<parameter> <name>maxActive</name> <value>100</value> </parameter>
<!-- Maximum number of idle dB connections to retain in pool. Set to 0 for no limit. -->
- <!-- 空闲状态数据库连接最大数 -->
<parameter> <name>maxIdle</name> <value>30</value> </parameter>
<!-- Maximum time to wait for a dB connection to become available in ms, in this example 10 seconds. An Exception is thrown if this timeout is exceeded. Set to -1 to wait indefinitely. Maximum time to wait for a dB connection to become available in ms, in this example 10 seconds. An Exception is thrown if this timeout is exceeded. Set to -1 to wait indefinitely. -->
- <!-- 数据库处于空闲状态的最长时间 -->
<parameter> <name>maxWait</name> <value>10000</value> </parameter>
<!-- MySQL dB username and password for dB connections -->
- <!-- 指定连接数据库的用户名及密码 -->
<parameter> <name>username</name> <value>dbuser</value> </parameter> <parameter> <name>password</name> <value>1234</value> </parameter>
<!-- Class name for mm.mysql JDBC driver -->
- <!-- 指定JDBC驱动 -->
<parameter> <name>driverClassName</name> <value>com.mysql.jdbc.Driver</value> </parameter>
<!-- The JDBC connection url for connecting to your MySQL dB. The autoReconnect=true argument to the url makes sure that the mm.mysql JDBC Driver will automatically reconnect if mysqld closed the connection. mysqld by default closes idle connections after 8 hours. -->
- <!-- 指定连接数据库的URL -->
<parameter> <name>url</name> <value>jdbc:mysql://localhost:3306/BookDB?autoReconnect=true</value> </parameter> </ResourceParams>
</Context>
|
运行机制:
1、
首先程序代码获取初始化的
JNDI
环境并且调用
Context.lookup()
方法从
JNDI
服务提供者那里获一个
DataSource
对象
2、
中间层
JNDI
服务提供者返回一个
DataSource
对象给当前的
Java
应用程序这个
DataSource
对象代表了中间层服务上现存的缓冲数据源
3、
应用程序调用
DataSource
对象的
getConnection()
方法
4、
当
DataSource
对象的
getConnection()
方法被调用时,中间层服务器将查询数据库
连接缓冲池中有没有
PooledConnection
接口的实例对象。这个
PooledConnection
对象将被用于与数据库建立物理上的数据库连接
5、
如果在缓冲池中命中了一个
PooledCoonection
对象那么连接缓冲池将简单地更
新内部的缓冲连接队列并将该
PooledConnection
对象返回。如果在缓冲池内没
有找到现成的
PooledConnection
对象,那么
ConnectionPoolDataSource
接口将会被
用来产生一个新的
PooledConnection
对象并将它返回以便应用程序使用
6。
中间层服务器调用
PooledConnection
对象的
getConnection()
方法以便返还一个
java.sql.Connection
对象给当前的
Java
应用程序
7、
当中间层服务器调用
PooledConnection
对象的
getConnection()
方法时,
JDBC
数据
库驱动程序将会创建一个
Connection
对象并且把它返回中间层服务器
8、
中间层服务器将
Connection
对象返回给应用程序
Java
应用程序,可以认为这个
Connection
对象是一个普通的
JDBC Connection
对象使用它可以和数据库建立。事
实上的连接与数据库引擎产生交互操作 。
9、
当应用程序不需要使用
Connection
对象时,可以调用
Connection
接口的
close()
方
法。请注意这种情况下
close()
方法并没有关闭事实上的数据库连接,仅仅是释
放了被应用程序占用的数据库连接,并将它还给数据库连接缓冲池,数据库连接
缓冲池会自动将这个数据库连接交给请求队列中下一个的应用程序使用。