最近有个项目使用了proxool连接池,感觉它的配置很简单。
把相关的JAR包放入项目中,然后自己建一个xml<?xml version="1.0" encoding="UTF-8"?>
<something-else-entirely>
<proxool>
<alias>test</alias>
<driver-url>jdbc:sqlserver://localhost:1433;DatabaseName=wz</driver-url>
<driver-class>com.microsoft.sqlserver.jdbc.SQLServerDriver</driver-class>
<driver-properties>
<property name="user" value="aa"/>
<property name="password" value="aa"/>
</driver-properties>
<house-keeping-sleep-time>30000</house-keeping-sleep-time>
<maximum-new-connections>10000</maximum-new-connections>
<prototype-count>200</prototype-count>
<maximum-connection-count>5000</maximum-connection-count>
<minimum-connection-count>100</minimum-connection-count>
<maximum-active-time>60000</maximum-active-time>
<house-keeping-test-sql>select CURRENT_DATE</house-keeping-test-sql>
</proxool>
</something-else-entirely>然后在web.xml里加入 <servlet>
<servlet-name>ServletConfigurator</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/proxool/</url-pattern>
</servlet-mapping>
把相关的JAR包放入项目中,然后自己建一个xml<?xml version="1.0" encoding="UTF-8"?>
<something-else-entirely>
<proxool>
<alias>test</alias>
<driver-url>jdbc:sqlserver://localhost:1433;DatabaseName=wz</driver-url>
<driver-class>com.microsoft.sqlserver.jdbc.SQLServerDriver</driver-class>
<driver-properties>
<property name="user" value="aa"/>
<property name="password" value="aa"/>
</driver-properties>
<house-keeping-sleep-time>30000</house-keeping-sleep-time>
<maximum-new-connections>10000</maximum-new-connections>
<prototype-count>200</prototype-count>
<maximum-connection-count>5000</maximum-connection-count>
<minimum-connection-count>100</minimum-connection-count>
<maximum-active-time>60000</maximum-active-time>
<house-keeping-test-sql>select CURRENT_DATE</house-keeping-test-sql>
</proxool>
</something-else-entirely>然后在web.xml里加入 <servlet>
<servlet-name>ServletConfigurator</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/proxool/</url-pattern>
</servlet-mapping>
解决方案 »
- 【求助】JDBC 控制台输入数据 直接插入到数据库
- 用keytool配置tomcat ssl双向认证问题
- 用JSP实现文件(excel和text)的下载的代码?
- 求助:用Eclipse里用Glassfish插件连接Mysql
- struts框架下下载EXCEL文件,不能正常返回
- javaSrcipt
- Could not find a getter for subjectId in class com.mon.po.Subject
- 怎样在页面打开时,将光标定位在表单的第一个文本框里?谢谢
- dwz怎么返回json?struts2
- 在struts2.5.17下搭建struts2-junit-plugin-2.5.17时出现NullPointerException
- 怎么查询一个局域网内各个机器的ip
- 怎样把左边的下拉框内容添加到右边的下拉框,而且是选多个,还有怎样从右边的下拉框移除对象,最好用div 方法
public class DBConnection { private static Connection conn = null;
public DBConnection(){
}
/**
* 取得连接池中的连接
* @return
*/
public static Connection getConnection() {
try {
conn = DriverManager.getConnection("proxool.test");
System.out.println(conn+"*****************************");
return conn;
} catch (SQLException e) {
System.out.println("getConn:"+e.getMessage());
return null;
}
}
/**
* 释放连接
* freeConnection
* @param conn
*/
public static void freeConnection(Connection conn){
if(conn != null){
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
这是连接类。
连接是好的。但是我在用到JSP页面,按F5连续刷的时候,会报错误java.sql.SQLException: Couldn't perform the operation prepareStatement: You can't perform a prepareStatement operation after the connection has been closed但页面还是能用的。为什么会报这个错误呢
在日志中还会报这个错2008-11-28 10:38:42 StandardWrapperValve[jsp]: Servlet.service() for servlet jsp threw exception
java.lang.OutOfMemoryError: Java heap space2008-11-28 10:38:42 StandardWrapperValve[jsp]: Servlet.service() for servlet jsp threw exception
java.lang.OutOfMemoryError: Java heap space2008-11-28 10:38:42 StandardWrapperValve[jsp]: Servlet.service() for servlet jsp threw exception
java.lang.OutOfMemoryError: Java heap space另外网上说可以查看连接情况,但是我怎么就打不开那个页面呢
http://localhost:8080/admin/proxool/
报404错误
2.You can't perform a prepareStatement operation after the connection has been closed
连接关了
/**
* 根据ID得到投票选项名称
* @param id
* @return 投票选项名称
* @throws Exception
*/
public String getVoteClassNameById(String id) throws Exception {
conn = DBConnection.getConnection();
String className = "";
sql = "select CLASS_NAME from VOTE_CLASS_NAME where DELETE_FLAG=1 and ID=?";
try{
ps = conn.prepareStatement(sql);
ps.setString(1, id);
rs = ps.executeQuery();
while(rs.next()){
className = rs.getString("CLASS_NAME");
}
}catch(Exception e){
e.printStackTrace();
}finally{
if(rs!=null){
rs.close();
}
if(ps!=null){
ps.close();
}
DBConnection.freeConnection(conn);
}
return className;
}这是其中一个方法,所有的方法都是以这种形式关闭连接的。
if(rs!=null){
rs.close();
}
if(ps!=null){
ps.close();
}
DBConnection.freeConnection(conn);
}
return className;
老大,你都关闭连接了还能返回去吗?
将return className提前到finally前试试
<maximum-connection-count>5000</maximum-connection-count>
<minimum-connection-count>100</minimum-connection-count>
改成
<maximum-connection-count>50</maximum-connection-count>
<minimum-connection-count>10</minimum-connection-count>
再试
conn = DriverManager.getConnection("proxool.property-test");
pstmt = conn.prepareStatement();
rs = pstmt.executeQuery();
//处理代码
}
catch( SQLException sqle ) {
sqle.printStackTrace();
}
finally {
try { pstmt.close(); }
catch (Exception e) { e.printStackTrace(); }
try { conn.close(); }
catch (Exception e) { e.printStackTrace(); }
}
毕竟出现OOM问题了
严重: Caught exception (java.lang.OutOfMemoryError: Java heap space) executing org.apache.tomcat.util.net.TcpWorkerThread@439d3b, terminating thread
* 根据SQL语句得到总的记录
* @param sql
* @return 得到总的记录
* @throws Exception
*/
public List findAllVoteNameInfoList(String sql) throws Exception {
conn = DBConnection.getConnection();
dataList = new ArrayList();
try{
ps = conn.prepareStatement(sql);
rs = ps.executeQuery();
while(rs.next()){
model = new VoteNameModel();
model.setClassId(rs.getString("CLASS_ID"));
model.setCreateUserNo(rs.getString("CREATE_USER_NO"));
model.setDeleteFlag(rs.getInt("DELETE_FLAG"));
model.setId(rs.getInt("ID"));
model.setUpdateDateTime(rs.getString("UPDATE_DATE_TIME"));
model.setUpdateUserNo(rs.getString("UPDATE_USER_NO"));
model.setVoteName(rs.getString("VOTE_NAME"));
model.setVoteFlag(rs.getInt("VOTE_FLAG"));
dataList.add(model);
}
}catch(Exception e){
e.printStackTrace();
}finally{
if(rs!=null){
rs.close();
}
if(ps!=null){
ps.close();
}
DBConnection.freeConnection(conn);
}
return dataList;
}
<servlet>
<servlet-name>ServletConfigurator</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/proxool/</url-pattern>
</servlet-mapping>
-------------------------------------------------------------------------------------------
我是瞎蒙的,不要相信我!!
就是DBConnection类
它用了一个静态的值保存conn,这种做法是严重错误的!
第一个请求者来调用它,它从连接池里面得到一个conn1,把它放到这个静态变量;
假设第一个请求者还未释放,第二个请求来了,它又放的是conn2;
如果第一个请求调用Free,那么它释放的是conn2,这时候如果conn2使用prepareStatement,因为conn2已经被你close了,所以它就会报错:
You can't perform a prepareStatement operation after the connection has been closed
而第一个conn1根本就没被释放,这样次数多了,就会导致OutOfMemery解决方案:
不要DBConnection类,在需要conn的时候,直接用
conn = DriverManager.getConnection("proxool.property-test");
关闭是直接用:
conn.close();
但不能这样写,可以这样:public class DBConnection {
public static Connection getConnection() {
Connection conn=null;
try {
conn = DriverManager.getConnection("proxool.test");
System.out.println(conn+"*****************************");
return conn;
} catch (SQLException e) {
System.out.println("getConn:"+e.getMessage());
}
return conn;
}
}连接时就调用这个静态方法;释放还是直接用conn.close();
连接数的XML的设置是多少
<?xml version="1.0" encoding="UTF-8"?>
<something-else-entirely>
<proxool>
<alias>test</alias>
<driver-url>jdbc:sqlserver://localhost:1433;DatabaseName=wz</driver-url>
<driver-class>com.microsoft.sqlserver.jdbc.SQLServerDriver</driver-class>
<driver-properties>
<property name="user" value="aa"/>
<property name="password" value="aa"/>
</driver-properties>
<house-keeping-sleep-time>30000</house-keeping-sleep-time>
<maximum-new-connections>100</maximum-new-connections>
<prototype-count>200</prototype-count>
<maximum-connection-count>50</maximum-connection-count>
<minimum-connection-count>10</minimum-connection-count>
<maximum-active-time>60000</maximum-active-time>
<house-keeping-test-sql>select CURRENT_DATE</house-keeping-test-sql>
</proxool>
</something-else-entirely>
proxool.xml
<something-else-entirely>
<proxool>
<alias>testpool</alias> <driver-url>jdbc:microsoft:sqlserver://127.0.0.1:1433;DatabaseName=TestSql;SelectMethod=cursor</driver-url>
<driver-class>com.microsoft.jdbc.sqlserver.SQLServerDriver</driver-class> <driver-properties>
<property name="user" value="sa"/>
<property name="password" value=""/>
</driver-properties> <!-- proxool自动侦察各个连接状态的时间间隔(毫秒),侦察到空闲的连接就马上回收,超时的销毁-->
<house-keeping-sleep-time>300000</house-keeping-sleep-time>
<!--最大的等待请求数,即因没有空闲连接可以分配而在队列中等候的最大请求数,超过这个请求数的用户连接就不会被接受-->
<proxool.simultaneous-build-throttle>200</proxool.simultaneous-build-throttle>
<!-- maximum-new-connections>50</maximum-new-connections-->
<!-- 最少保持的空闲连接数-->
<prototype-count>5</prototype-count>
<!-- 允许最大连接数,超过了这个连接,再有请求时,就排在队列中等候,最大的等待请求数由maximum-new-connections决定-->
<maximum-connection-count>100</maximum-connection-count>
<!-- 最小连接数-->
<minimum-connection-count>20</minimum-connection-count>
<house-keeping-test-sql>select CURRENT_DATE</house-keeping-test-sql> </proxool>
</something-else-entirely>
web.xml
<servlet>
<servlet-name>ServletConfigurator</servlet-name>
<servlet-class>org.logicalcobwebs.proxool.configuration.ServletConfigurator</servlet-class>
<init-param>
<param-name>xmlFile</param-name>
<param-value>/WEB-INF/classes/proxool.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet>
<servlet-name>proxool</servlet-name>
<servlet-class>org.logicalcobwebs.proxool.admin.servlet.AdminServlet</servlet-class>
</servlet>
Java,我也是用静态的!
你把findAllVoteNameInfoList这个类,整个文件都给我看。
还有调用这个方法的类的整个代码
driver-url -〉数据库驱动
driver-class -〉驱动程序类
driver-properties -〉联机数据库的用户和密码
minimum-connection-count -〉最小连接数量,建议设置0以上,保证第一次连接时间
maximum-connection-count -〉最大连接数量,如果超过最大连接数量则会抛出异常。连接数设置过多,服务器CPU和内存性能消耗很大。
simultaneous-build-throttle -〉同时最大连接数
prototype-count -〉一次产生连接的数量。
例:如果现在prototype-count设置为4个,但是现在已经有2个可以获得的连接,那么将会试图再创建2个连接。
但不能超过最大连接数。
maximum-active-time -〉连接最大时间活动 默认5分钟
maximum-connection-lifetime -〉连接最大生命时间 默认4小时
看连接状态需要到这个地址 http://127.0.0.1:****/***/admin 访问的
就是这一句:conn = DBConnection.getConnection();
当你连续F5刷新的时候,servlet是多线程处理的。可能线程1运行到 ps = conn.prepareStatement(sql);的时候,线程2已经把conn关闭了。
楼主试一下在获取连接和释放连接的地方打印日志,看看。
DBConnection 类也有问题。
下面这行要去掉。
private static Connection conn = null;getConnection() 方法直接返回一个新的变量。
public static Connection getConnection() {
try {
Connection conn = DriverManager.getConnection("proxool.test");
System.out.println(conn+"*****************************");
return conn;
} catch (SQLException e) {
System.out.println("getConn:"+e.getMessage());
return null;
}
}
之前我跑过很多项目的,是不是因为什么有冲突呀。
conn = DBConnection.getConnection();
后面Sleep 10秒。
在这10秒内刷一下页面。让几个线程都执行到Sleep。然后等第一个线程被唤醒后执行sql,最后释放conn。之后其他几个线程被唤醒,再执行sql,就该报错了。
真正用到具体项目上要看具体应用,你说一天大概是2.5万并不是准确数字,你应该说是 在什么时候 登陆最多人是多少,一个人登陆的时候 一个连接的时间是多长,这样才能设置够用,就比如说是一个考试系统,考生一起准时登陆,那么这个时候多少个考生就是一个比较实在的数字,你连接池的数目要够这些人同时登陆使用,其实人们也不是很准确的在同一个时间登陆的,所以又要看你这一个连接需要连接多长时间。
如果出现异常情况 一般需要多长时间恢复,maximum-active-time 就是如果超过这个时间 连接池会自动给你断开,而不管你的用户连接了,生生的吧连接收回了
用不好不能说他不好