连接池最基本的目的:
1、重用连接,节省连接资源;
2、免去建立连接操作,提高效率
最近做的一个项目中运用到了连接池技术,在此简单的记录一下,我在项目中成功的配置和测试源码。
第一步:首先去http://proxool.sourceforge.net/下载一个proxool.jar文件
第二步:就是写一个单独的proxool.xml文件放到对应工程的WEB-INF文件夹下。我用的数据库是MySQL;proxool.xml的配置文件如下:
<?xml version="1.0"encoding="utf-8"?>
<something-else-entirely>
<proxool>
<alias>dbpool</alias>
<driver-url>jdbc:mysql://localhost/mar</driver-url>
<driver-class>com.mysql.jdbc.Driver</driver-class>
<driver-properties>
<propertyname="user" value="root" />
<propertyname="password" value="1" />
</driver-properties>
<house-keeping-sleep-time>90000</house-keeping-sleep-time>
<prototype-count>5</prototype-count>
<maximum-connection-lifetime>24000000</maximum-connection-lifetime>
<maximum-connection-count>100</maximum-connection-count>
<minimum-connection-count>10</minimum-connection-count>
<simultaneous-build-throttle>100</simultaneous-build-throttle>
<maximum-active-time>3000000</maximum-active-time>
<trace>true</trace>
</proxool>
</something-else-entirely>
对以上配置简单的解释:
1.<alias>:为该连接池起一个别名,在其他文件中引用。引用是:(proxool.dbpool);
2.<driver-class>com.mysql.jdbc.Driver</driver-class>
<driver-properties>
<property name="user" value="root"/>
<property name="password" value="root"/>
</driver-properties>
配置数据库的驱动和连接。
3.<house-keeping-sleep-time>:house keeper 保留线程处于睡眠状态的最长时间,house keeper的职责就是检查各个连接的状态,并判断是否需要销毁或者创建.
4.<maximum-new-connections>:指因未有空闲连接可以分配而在队列中等候的最大请求数,超过这个请求数的用户连接就不会被接受。
5.<prototype-count>:最少保持的空闲连接数。
6.<maximum-connection-count>:允许最大连接数,超过了这个连接,再有请求时,就排在队列中等候,最大的等待请求数由maximum-new-connections决定
7.<minimum-connection-count>:最小连接数
8.simultaneous-build-throttle :同时执行的最大连接数
9.maximum-active-time : 如果housekeeper检测到某个线程的活动时间大于这个数值.它将会杀掉这个线程.所以确认一下你的服务器的带宽.然后定一个合适的值.默认是5分钟.
第三步:加载并初始化proxool.xml文件。因为它是连接数据库的,其他很多模块都用到数据,所以你必须首先加载它,
<—>在Tomcat相对应的web.xml中进行如下配置
<servlet>
<servlet-name>proxoolServletConfigurator</servlet-name>
<servlet-class>org.logicalcobwebs.proxool.configuration.ServletConfigurator</servlet-class>
<init-param>
<param-name>xmlFile</param-name>
<param-value>WEB-INF/proxool.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet>
<servlet-name>Admin</servlet-name>
<servlet-class>org.logicalcobwebs.proxool.admin.servlet.AdminServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Admin</servlet-name>
<url-pattern>/admin</url-pattern>
</servlet-mapping>
此时可以在程序中直接调用:
public Connection getConn() {
try {
Class.forName("org.logicalcobwebs.proxool.ProxoolDriver");
return DriverManager.getConnection("proxool.Develop");
} catch (ClassNotFoundException ex){
Logger.getLogger(PoolManager.class).log(Level.INFO, null,ex);
} catch (SQLException ex) {
Logger.getLogger(PoolManager.class).log(Level.INFO, null,ex);
}
return null;
}
<二>,在自己写的java文件中直接调用,就是写了一个main方法,然后用"javaApplication"运行,
publicConnection getConnection(){
Connection conn = null;
try {
JAXPConfigurator.configure("src/proxool.xml", false);
conn = DriverManager.getConnection("proxool.dbpool");
return conn;
} catch(SQLException e){
Logger.getLogger(PoolManager.class).log(Level.INFO, null,e);
}
returnnull;
}
如果不这样而按<一>的程序来调用,则就会报Attempt to referto a unregistered pool by its alias ‘dbpool’,但是在JSP页面里并不会报错,其实问题的关键就是在这里,连接池的应用本来就是要通过服务器调用的,如果你在java文件中调用,就没有涉及到服务器,这样就会报错了!所以我们要用
JAXPConfigurator.configure("src/proxool.xml", false) 来加载配置文件!
web.xml 中的Admin 是配置proxool的管理界面:
proxool连接池的管理页面有可能不能正常显示,出现类似以下错误:
java.io.CharConversionException: Not an ISO 8859-1 character:十
javax.servlet.ServletOutputStream.print(ServletOutputStream.java:89)
org.logicalcobwebs.proxool.admin.servlet.AdminServlet.printDefinitionEntry(AdminServlet.java:515)
org.logicalcobwebs.proxool.admin.servlet.AdminServlet.doSnapshot(AdminServlet.java:273)
org.logicalcobwebs.proxool.admin.servlet.AdminServlet.doStats(AdminServlet.java:145)
org.logicalcobwebs.proxool.admin.servlet.AdminServlet.doGet(AdminServlet.java:129)
javax.servlet.http.HttpServlet.service(HttpServlet.java:690)
javax.servlet.http.HttpServlet.service(HttpServlet.java:803)
这是个编码问题,因我们一般用的是utf-8,gbk2312.
解决办法有两种:
1.把 web.xml 的编码换为 ISO 8859-1
2. 重写源码中的AdminServlet.java。重写这个源码,只需简单的该一个方法就可以了。
private voidprintDefinitionEntry(ServletOutputStream out, String name, Stringvalue) throws IOException {
out.println(" <tr>");
out.print(" <td width="200" valign="top" style="" +STYLE_CAPTION + "">");
out.print(name);
out.println("</td>");
if (value != null) {
out.print(" <td style="" + STYLE_DATA +"">");
out.print(new String(value.getBytes("ISO-8859-1"),"utf-8"));
} else {
out.print(" <td style="" + STYLE_NO_DATA +"">off");
}
out.print("</td>");
out.println(" </tr>");
}
然后把web.xml中的
<servlet-class>
org.logicalcobwebs.proxool.admin.servlet.AdminServlet </servlet-class>
中<servlet-class>换成你改写的那个类。
测试源码:
public Connection getConnection(){
Connection conn = null;
try {
JAXPConfigurator.configure("src/proxool.xml", false);
conn = DriverManager.getConnection("proxool.dbpool");
return conn;
} catch(SQLException e){
Logger.getLogger(PoolManager.class).log(Level.INFO, null,e);
}
returnnull;
}
public void getQuery(){
try{
Connection conn =getConnection();
if(conn !=null){
Statement statement =conn.createStatement();
ResultSet rs = statement.executeQuery("select * frommarketing");
int c =rs.getMetaData().getColumnCount();
while(rs.next()){
System.out.println();
for(inti=1;i<=c;i++){
System.out.print(rs.getObject(i));
}
}
rs.close();
}
} catch (SQLException e){
e.printStackTrace();
} finally{
if(conn!=null){
try{
conn.close();
} catch (SQLException e){
Logger.getLogger(PoolManager.class).log(Level.ERROR,null,e);
}
}
}
}
注:conn.close不会关闭实际连接,只是归还连接池!(但我们每次最好还是显式调用它!!)