1. 程式人生 > >JAVA實踐專案---樹莓派資訊自動化採集後入庫專案(五)

JAVA實踐專案---樹莓派資訊自動化採集後入庫專案(五)

專案原始碼可訪問我的github:https://github.com/Spacider/Gather-and-store
如果覺得好的話請給個star哦~

開發IDE: IDEA 2018.03 JDK 1.8
開發環境: macOS 10.13.6 (如windows請對專案中部分路徑進行改寫)
資料庫: Oracle 11g


第四階段:傳送給我們的服務端,並進行入庫操作

這一階段我們的任務就是接收上節客戶端傳送的物件資料,並且在分析以後把資料寫入資料庫!

在這裡插入圖片描述

此層專案結構為:
在這裡插入圖片描述


接下來,看程式碼:
1.編寫一個EnvServer介面,其中有個抽象方法,作用就是接收各個客戶端傳送過來的集合物件:

/**
 * 伺服器端模組
 */
public interface EnvServer extends WossModel  {
    /**
     * 接收各個客戶端傳送過來的集合物件 Collection(Environment)
     */
    void receive();
}

新建立一個實現包為Impl ,建立實現類EnvServerImpl,其中實現了receive方法,在寫receive方法之前,我們先定義一個執行緒來接收,運用執行緒可以很好的體現"持續性"讀取的特點。

class EnvServerThread extends Thread {

    private Socket socket;
    public EnvServerThread (Socket socket){
        this.socket = socket;
    }
}

使用構造器把socket 物件傳入!這樣我們就可以線上程類中操作流來接收我們需要的資料了!

is = socket.getInputStream();
ois = new ObjectInputStream(is);
List <Environment> environmentList = (List <Environment>) ois.readObject();

獲取到我們的輸入流時,直接將其包裝成物件流(上文發過來的時候使用物件流傳送),故我們可以通過readObject方法來得到我們上文從客戶端發過來的物件!

之後receive 方法可以這麼寫:

/**
     * 伺服器接收方法
     */
    public void receive() {
        Socket socket = null;

        try {
            ServerSocket server = new ServerSocket(port);
            logger.info("server 啟動"+ server);
            while(true){
                socket = server.accept();
                new EnvServerThread(socket).start();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

執行EnvServerImpl類和ClientMain類和DataServer類,在服務端的執行緒中列印物件陣列,在看見陣列並且陣列正確時,就說明你這一部分寫對了!


2.在獲得物件以後我們需要對陣列進行入庫操作:
編寫介面

/**
 * 入庫模組
 */
public interface DBStore extends WossModel {
    /**
     * 把伺服器接收到的資料寫入到資料庫中持久儲存
     * 注意資料的錄入是按天進行錄入的
     * t_s ---> 拆分成多張表
     * 20/5 取餘數
     * t_s0 t_s1 t_s2 t_s3 t_s4
     * @param col
     */
    void saveEnvToDB(Collection<Environment> col);
}

資料庫操作自然會用到jdbc!為了方便編寫一個數組庫的操作類,裡邊包含各種關於資料庫的操作:
此處,請記得修改你的檔案路徑,第二記得修改檔案中的內容,修改為你對應資料庫的連結資訊!
這個和一般網上所寫的都差不多,就直接貼程式碼了:

/**
 * 資料庫處理幫助類
 * 書寫關於資料庫的一些操作方法,比如 獲取連線物件 、 封裝插入方法
 */
public class DBhelper {

    // dhcp 緩衝池物件
    private static BasicDataSource DATA_SOURCE;

    static {
        Properties properties = new Properties();
        FileInputStream fis = null;
        try {
            fis = new FileInputStream(new File("/Users/wjh/Desktop/FirstProject/src/main/resources/config.properties"));
            properties.load(fis);

            // 通過讀取 properties 檔案來初始化 DATA_SOURCE
            DATA_SOURCE = new BasicDataSource();
            DATA_SOURCE = BasicDataSourceFactory.createDataSource(properties);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            IOUtil.close(fis);
        }
    }

    /**
     * 獲取 Connection 連線物件
     * @return
     */
    public static Connection getConnction(){
        Connection connection = null;
        try {
            connection = DATA_SOURCE.getConnection();
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return connection;
    }

    /**
     * 處理 SQL 語句方法
     * @param sql
     */
    public static void ExecuteSql(String sql){
        Connection connection = getConnction();
        PreparedStatement ps = null;

        try {
            ps = connection.prepareStatement(sql);
            ps.execute();
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            try {
                if (ps != null) {
                    ps.close();
                }
                if (connection != null) {
                    connection.close();
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
}

之後我們就可以寫入庫的實現類DBStoreImpl
通過我們剛才寫的資料庫操作類來獲得一個數據庫連結:

 Connection connection = DBhelper.getConnction();

之後就是對物件的拆分並通過PreparedStatement來對sql語句進行預載入,把對應的資料存入:

for (Environment environment : col) {
                DateFormat sdf = new SimpleDateFormat("yyyy-MM-dd-HH:mm:ss");
                Timestamp timestamp = environment.getGather_date();
                String tsStr = sdf.format(timestamp);
                // gather_date=2018-09-15 11:17:48.0

                String[] time = tsStr.split("\\-");
                String day = time[2];

                // 拼接 sql 語句
                String sql = "insert into T_DETAIL_" + day
                        + " values(?,?,?,?,?,?,?,?,?,?)";

                ps = connection.prepareStatement(sql);

                ps.setString(1,environment.getName());
                ps.setString(2,environment.getSrcID());
                ps.setString(3,environment.getDstID());
                ps.setString(4,environment.getDevID());
                ps.setString(5,environment.getSensorAddress());
                ps.setInt(6,environment.getCount());
                ps.setInt(7,environment.getCmd());
                ps.setString(8,environment.getData()+"");
                ps.setInt(9,environment.getStatus());
                ps.setTimestamp(10,environment.getGather_date());

接下來是對陣列執行的處理,這裡採用了快取機制,等待 count 為100條的整數倍時再執行響應的sql語句,當sql語句較多時可以減少大量sql等待的場景。

ps.addBatch();

if ( count % 100 == 0 ) {
      ps.executeBatch();
  }
  count ++;

實現了入庫的操作之後在EnvServerImpl類的執行緒類中加入如下一行,
把資料遞交給入庫類處理:

// 資料庫入庫操作
dbStore.saveEnvToDB(environmentList);

最後,執行EnvServerImpl類和ClientMain類和DataServer類,看到提示資訊,並發現資料庫內有我們需要的資料的時候,就完成了當前部分的編寫!