写的是JSP应用。
只要8小时内没有访问数据库,应用再次通过jdbc访问数据库就会发生异常。本人用的是Mysql5.5不能通过在链接字符窜增加autoReconnect=true解决。只有Mysql 4.x才能通过这个办法解决。
private static String url = "jdbc:mysql://localhost:3306/remote?autoReconnect=true&useUnicode=true&characterEncoding=utf8";
然后我就想,能不能开一个线程,每隔8小时访问一次Mysql数据库。原理
下面开始试验。
我将Mysql5.5的 wati_timeout设置为10
set global wait_timeout=10
只要过10秒不访问访问应用,那么就会报错。还原了事故现场。
然后增加以下代码,增加一个线程,每隔10秒访问一次数据库,那么就不会报错,而且页面正常显示。下面的Listener使用的是Servlet 3.0的写法,低版本的请百度。
package servlet;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;
import utils.MysqlTool;
/**
* 保持和MYSQL的链接,每8小时连接一次,Mysql wait_timeout为28800
* @author
*
*/
@WebListener
public class KeepMysqlListener implements ServletContextListener {
private MyThread myThread;
public KeepMysqlListener(){
}
@Override
public void contextDestroyed(ServletContextEvent arg0) {
if (myThread != null && myThread.isInterrupted()) {
myThread.interrupt(); //销毁线程
}
}
@Override
public void contextInitialized(ServletContextEvent arg0) {
if (myThread == null) {
myThread = new MyThread();
myThread.start(); // servlet 上下文初始化时启动线程
}
}
}
class MyThread extends Thread {
public void run() {
while (!this.isInterrupted()) {// 线程未中断执行循环
try {
MysqlTool.keepMysql();
Thread.sleep(10*1000); //每隔10m秒执行一次 测试成功后可以改成8小时的 8*60*60*1000ms
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
其中MysqlTool.keepMysql()方法如下:
package utils;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
public class MysqlTool {
//数据库连接对象
private static Connection conn = null;
//驱动程序名
private static String driver = "com.mysql.jdbc.Driver";
//URL指向要访问的数据库名mydata
private static String url = "jdbc:mysql://localhost:3306/remote?autoReconnect=true&useUnicode=true&characterEncoding=utf8";
//MySQL配置时的用户名
private static String username = "root";
//MySQL配置时的密码
private static String password = "";
// 获得连接对象
private static synchronized Connection getConn(){
if(conn == null){
try {
Class.forName(driver);
conn = DriverManager.getConnection(url, username, password);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}catch (SQLException e) {
e.printStackTrace();
}
}
return conn;
}
public static String keepMysql(){
PreparedStatement pstmt = null;
String sql = "SELECT 1 FROM USERS";
ResultSet rs = null;
String str= "";
try {
pstmt = getConn().prepareStatement(sql);
rs = pstmt.executeQuery();
//System.out.println(pstmt.toString());
while (rs.next()) {
str = rs.getString(1);
}
rs.close();
pstmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
return str;
}
}
测试成功之后,将代码中的10*1000替换成 8*60*60*1000即可。
|