最近寫(xiě)了很多硬件設(shè)備的采集程序,由于數(shù)據(jù)的分析和頁(yè)面的展示都是通過(guò)數(shù)據(jù)庫(kù)服務(wù)器上的oracle數(shù)據(jù)庫(kù)計(jì)算并且發(fā)送到前臺(tái)可視化顯示的。這其中就有個(gè)問(wèn)題就是,一旦數(shù)據(jù)庫(kù)服務(wù)器停電了或者宕機(jī)了,那么必須得有人手動(dòng)重啟應(yīng)用服務(wù)器的程序。所以這里需要有增加一個(gè)斷線重連的功能。
直接上代碼

如上圖所示,OracleWriter是接收并解析好的數(shù)據(jù),insert到數(shù)據(jù)庫(kù)中,在這個(gè)類(lèi)的構(gòu)造方法中通過(guò)scheduleAtFixedRate方法每隔十秒調(diào)用一下MonitorThread線程的邏輯,我們來(lái)主要看一下MonitorThread這個(gè)監(jiān)控類(lèi)。
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("數(shù)據(jù)庫(kù)連接中斷,嘗試重連" + 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.通過(guò)"select 1 from dual"來(lái)檢測(cè)數(shù)據(jù)庫(kù)是否還正常。(如果正常則應(yīng)該返回"1")
2.如果服務(wù)器這個(gè)時(shí)候已經(jīng)斷了,則直接捕獲到異常。
3.為了高效只有一個(gè)static的Connection連接,不主動(dòng)關(guān)閉。但是在異常中我們手動(dòng)的將OracleWriter的conn的連接對(duì)象設(shè)為null(我嘗試了close,直接報(bào)錯(cuò)了。)等待GC把他回收,然后再把新創(chuàng)建的conn賦值給OracleWriter的conn。
4.大功告成,很簡(jiǎn)單吧,經(jīng)了解到常見(jiàn)的數(shù)據(jù)庫(kù)連接池的斷線重連的實(shí)現(xiàn)原理也類(lèi)似是這樣。