项目前后台分离,通过ajax异步请求
这个问题困扰了我半个月,找来找去也没有找到办法,网上的资料更是少的可怜!!
报错时好时坏,总让我抱有一丝希望是网络或者服务器的问题,但是!!!计算机没有偶然事件!错就是错!
不多回想辛酸泪,直接贴上报错信息 看大家是否和我一样?
根据报错,很明显, 你不能操作一个已经被关掉的statement,就是当你访问数据库的时候,它已经被关闭了。。
那么遇到这个问题,我是怎么如何一步一步找到了答案,作为学习者,解决的办法千千万万,但是不能逃避这个报错,一定要从根源去分析这个报错到底是因为什么??并不是换一个代码就好了。。
那么开始了,当前台请求的时候,我打开了前台的控制器,查看到了一个现象:
前台居然在一次请求中,并行了5次ajax请求后台,
想了想,难道是我的C3P0连接池跟不上请求么?
查了查资料,我把C3P0改了下,代码如下:
com.mysql.jdbc.Driver
jdbc:mysql://localhost:3306/bluemsun
root
root
15
30
100
20
200
3000
7
30
1000
false
Test
false
60
0
10
true
看样子,他五个同时请求,数据库应该也能给他分配相应的资源....
试了试果然,一切正常,没有异常了.. 但是但是!!!没过一会儿,异常接二连三的开始出现了,而且一发不可收拾!!
因此第一个方案失败了,看来问题不是因为资源分配的不足,并且我上面都是按大的来写!
那么?会不会是因为两个请求同时访问一个方法的时候冲突了????
于是第二个方案来了:(在方法上加上了 synchronized 修饰词) 锁住方法,防止两个请求同时访问
public synchronized List findPageReply(int pageNum, int i, int comment_id) {
String sql="SELECT * from comment_reply WHERE comment_id='" + comment_id + "' LIMIT ?,?";
Object [] param={pageNum*i-i,i};
List list=null;
try {
if (conn==null||conn.isClosed()){
conn=JDBCUtil.getConnection();
}
list=queryRunner.query(conn,sql,new BeanListHandler(CommentReply.class),param);
}catch (Exception ex){
ex.printStackTrace();
}finally {
try {
if(conn!=null&&!conn.isClosed()){
conn.close();
}
}catch (Exception EX){
EX.printStackTrace();
}
}
return list;
调试了下,还是不行!!!
分析了下,得出结论.....到底是谁在在我正在访问的时候关了数据库的接口!!!!
我用的是Dbutils//
然后我就索性把代码全改成了jdbc写
public synchronized List findPageReply(int pageNum, int i, int comment_id) {
String sql = "SELECT * from comment_reply WHERE comment_id='" + comment_id + "' LIMIT ?,?";
Connection conn = null;
PreparedStatement st = null;
ResultSet rs = null;
conn = JDBCUtil.getConnection();
List list = new ArrayList();
try {
st = conn.prepareStatement(sql);
st.setInt(1, pageNum * i - i);
st.setInt(2, i);
rs = st.executeQuery();
while (rs.next()) {
CommentReply commentReply = new CommentReply();
commentReply.setId(rs.getInt("id"));
commentReply.setComment_id(rs.getInt("comment_id"));
commentReply.setContent(rs.getString("content"));
commentReply.setFromer(rs.getString("fromer"));
commentReply.setToer(rs.getString("toer"));
list.add(commentReply);
}
} catch (Exception ex) {
ex.printStackTrace();
} finally {
try {
rs.close();
st.close();
conn.close();
} catch (Exception ex) {
ex.printStackTrace();
}
return list;
}
没想到可以了!!!再也没有报题目的那个异常了....
那么,到底是哪里出问题了??
看了下Dao层里面的成员变量
public class UserDao {
public static Connection conn;
public static QueryRunner queryRunner = new QueryRunner();
private final static String DRIVER = "com.mysql.jdbc.Driver";
private final static String URL = "jdbc:mysql://localhost:3306/bluemsun?useUnicode=true&characterEncoding=utf-8";
private final static String USERNAME = "root";
private final static String PASSWORD = "root";
queryRunner 是一个静态成员变量
首先我怀疑是
QueryRunner,毕竟它帮我封装了那么多东西.....
于是呢,我就在每次执行查询前,重新new 一个实例。。
QueryRunner queryRunner1 = new QueryRunner();
public synchronized List findPageReply(int pageNum, int i, int comment_id) {
String sql="SELECT * from comment_reply WHERE comment_id='" + comment_id + "' LIMIT ?,?";
Object [] param={pageNum*i-i,i};
List list=null;
QueryRunner queryRunner1 = new QueryRunner();
try {
if (conn==null||conn.isClosed()){
conn=JDBCUtil.getConnection();
}
list=queryRunner1.query(conn,sql,new BeanListHandler(CommentReply.class),param);
}catch (Exception ex){
ex.printStackTrace();
}finally {
try {
if(conn!=null&&!conn.isClosed()){
conn.close();
}
}catch (Exception EX){
EX.printStackTrace();
}
}
return list;
}
以为就此可以解决这个问题了, 跑了下,wtf!!还是抛出异常!!!
实在是想不明白,这个配置啥的,都是在网上的热门博客粘的代码,为什么一到高并发,多线程的时候就出问题???
想来想去,终于知道了为什么了!!!!问题就是在static 这个关键字,
无论我在怎么去new出一个对象,只要最终我的conn关闭了,那么它就影响了我的静态成员变量conn ,直接就把conn给关了,
也就是这样子,当其他的线程访问到sql语句的时候,突然上一个语句执行完毕,把conn给关了!!
数据库给你抛出异常也是理所当然,
最后我修了下:
public class SystemDao {
//如果加了static修饰词的话并发问题无法得到解决!!!
public Connection conn;
public QueryRunner queryRunner = new QueryRunner();
private final static String DRIVER = "com.mysql.jdbc.Driver";
private final static String URL = "jdbc:mysql://localhost:3306/bluemsun?useUnicode=true&characterEncoding=utf-8";
private final static String USERNAME = "root";
private final static String PASSWORD = "root";
private static final Logger LOGGER = Logger.getLogger(SystemDao.class);
成功了!!!!
问题完美解决,同时一次性6次ajax访问同一个方法也不抛出异常了!!!