最近写了很多硬件设备的采集程序,由于数据的分析和页面的展示都是通过数据库服务器上的oracle数据库计算并且发送到前台可视化显示的。这其中就有个问题就是,一旦数据库服务器停电了或者宕机了,那么必须得有人手动重启应用服务器的程序。所以这里需要有增加一个断线重连的功能。
直接上代码
image.png
如上图所示,OracleWriter是接收并解析好的数据,insert到数据库中,在这个类的构造方法中通过scheduleAtFixedRate方法每隔十秒调用一下MonitorThread线程的逻辑,我们来主要看一下MonitorThread这个监控类。
package com.junlai.wifi.server;
import org.apache.log4j.Logger;
import java.sql.*;
public class MonitorThread implements Runnable {
private static final Logger logger = Logger.getLogger(MonitorThread.class);
private String url;
private String user;
private String password;
public MonitorThread( String url, String user, String password) {
this.url = url;
this.user = user;
this.password = password;
}
public void run() {
try {
System.out.println("MonitorThread~~~~~~~~~~~~~!!!!");
String sql = "select 1 from dual";
Statement statement = OracleWriter.conn.createStatement();
ResultSet resultSet = statement.executeQuery(sql);
/*while (resultSet.next()) {
}*/
if (resultSet != null) {
try {
resultSet.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (statement != null) {
try {
statement.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
} catch (Exception e) {
System.out.println("捕获到了异常!!!!!!!!!!!!");
e.printStackTrace();
logger.error("数据库连接中断,尝试重连" + e.getMessage());
try {
OracleWriter.conn = null;
OracleWriter.conn = DriverManager.getConnection(url, user, password);
} catch (SQLException e1) {
e1.printStackTrace();
}
}
}
}
package com.junlai.wifi.server;
import org.apache.log4j.Logger;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.concurrent.*;
/**
* Created by liz on 2018/7/9.
*/
public class OracleWriter implements WriterInterface{
private static final SimpleDateFormat SIMPLE_DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
private static final Logger logger = Logger.getLogger(OracleWriter.class);
public static volatile Connection conn = null;
private ScheduledExecutorService oraclePool = Executors.newScheduledThreadPool(1);
public static final int ORACLE_MONITOR_PERIOD = 10;
public Connection getConn() {
return conn;
}
public void setConn(Connection conn) {
this.conn = conn;
}
static {
try {
Class.forName("oracle.jdbc.driver.OracleDriver");
} catch (Exception e) {
logger.error(e.getMessage(), e);
e.printStackTrace();
}
}
public OracleWriter(String url, String user, String password) {
try {
conn = DriverManager.getConnection(url,user,password);
conn.setAutoCommit(true);
oraclePool.scheduleAtFixedRate(new MonitorThread(url,user,password),0,ORACLE_MONITOR_PERIOD, TimeUnit.SECONDS);
} catch (Exception e) {
logger.error(e.getMessage(), e);
e.printStackTrace();
}
}
}
思路
1.通过"select 1 from dual"来检测数据库是否还正常。(如果正常则应该返回"1")
2.如果服务器这个时候已经断了,则直接捕获到异常。
3.为了高效只有一个static的Connection连接,不主动关闭。但是在异常中我们手动的将OracleWriter的conn的连接对象设为null(我尝试了close,直接报错了。)等待GC把他回收,然后再把新创建的conn赋值给OracleWriter的conn。
4.大功告成,很简单吧,经了解到常见的数据库连接池的断线重连的实现原理也类似是这样。
网友评论