[Skills training] DMS data mining project (complete program)

1. System requirements analysis

1.1 Overview of Requirements

DMS data mining project is a system based on C/S (Client/Server, client/server) architecture.

1.2 Requirements Description

It consists of two parts: DMS client and DMS server:
●DMS client is a part of the system, its main task is to collect, analyze and match the data, and send the matched data to the DMS server.
●The DMS server is used to receive the data sent by the DMS client and save the data in the database. The DMS server provides monitoring functions for the received data.

2. Overall system design

2.1 Purpose of writing

The DMS data mining project can collect various data types, such as the collection of log data information, logistics data information collection, etc., and various data information are based on inheritance relationships.

2.2 Overall Design

2.2.1 Function division

1

2.2.2 Database and tables

2

2.2.3 Main business process

3

3. Detailed design and implementation

3.1 Table Design

user table

4

match log table

5

Match logistics table

6

The DataTableModelFromList class implements the function of reading log or logistics data from a file, and then displaying the data in the form of a table.

package com.qst.dms.entity;

import javax.swing.table.AbstractTableModel;
import java.util.ArrayList;
import java.util.List;

public class DataTableModelFromList<T> extends AbstractTableModel {
    
    
    // 使用List来创建TableModel
    private List<String[]> datas = new ArrayList<>();
    // 标志位,区分日志和物流:1,日志;0,物流
    private int sign;

    public DataTableModelFromList(List<T> data, int sign) {
    
    
        // TODO Auto-generated constructor stub
        this.sign = sign;

        for(T obj: data) {
    
    
            try {
    
    
                String[] arr = (String[])obj.getClass().getMethod("toArray").invoke(obj);
                datas.add(arr);
            } catch (Exception e) {
    
    
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

        }

    }

    // 获取表格的行数
    public int getRowCount() {
    
    
        return datas.size();
    }

    // 获取表格的列数
    public int getColumnCount() {
    
    
        return this.sign==1?7:7;
    }

    // 获取指定位置的值
    public Object getValueAt(int rowIndex, int columnIndex) {
    
    
        return datas.get(rowIndex)[columnIndex];
    }

    // 获取表头信息
    public String getColumnName(int column) {
    
    
        String[] logArray = {
    
     "日志ID", "采集时间", "采集地点", "状态", "用户名", "IP", "日志类型" };
        String[] tranArray = {
    
     "物流ID", "采集时间", "目的地", "状态", "经手人", "收货人",
                "物流类型" };
        return sign == 1 ? logArray[column] : tranArray[column];
    }

}

The MatchedTableModel class realizes the function of reading log or logistics data from the database, and then displaying the data in the form of a table.

package com.qst.dms.entity;

import javax.swing.table.AbstractTableModel;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;

public class MatchedTableModel extends AbstractTableModel {
    
    
    // 使用ResultSet来创建TableModel
    private ResultSet rs;
    private ResultSetMetaData rsmd;
    // 标志位,区分日志和物流:1,日志;0,物流
    private int sign;

    public MatchedTableModel(ResultSet rs, int sign) {
    
    
        this.rs = rs;
        this.sign = sign;
        try {
    
    
            rsmd = rs.getMetaData();
        } catch (Exception e) {
    
    
            rsmd = null;
        }
    }

    // 获取表格的行数
    public int getRowCount() {
    
    
        try {
    
    
            rs.last();
            // System.out.println(count);
            return rs.getRow();
        } catch (Exception e) {
    
    
            return 0;
        }
    }

    // 获取表格的列数
    public int getColumnCount() {
    
    
        try {
    
    
            // System.out.println(rsmd.getColumnCount());
            return rsmd.getColumnCount();
        } catch (Exception e) {
    
    
            return 0;
        }
    }

    // 获取指定位置的值
    public Object getValueAt(int rowIndex, int columnIndex) {
    
    
        try {
    
    
            rs.absolute(rowIndex + 1);
            return rs.getObject(columnIndex + 1);
        } catch (Exception e) {
    
    
            return null;
        }
    }

    // 获取表头信息
    public String getColumnName(int column) {
    
    
        String[] logArray = {
    
     "日志ID", "采集时间", "采集地点", "状态", "用户名", "IP", "日志类型" };
        String[] tranArray = {
    
     "物流ID", "采集时间", "目的地", "状态", "经手人", "收货人",
                "物流类型" };
        return sign == 1 ? logArray[column] : tranArray[column];
    }
}

3.2 Design of database access tools

The DBUtil class realizes the simple operation of connecting to the database and performing transaction processing.

package com.qst.dms.util;

import java.sql.*;

public class DBUtil {
    
    
    static Connection conn = null;
    PreparedStatement pstmt = null;
    ResultSet rs = null;

    /**
     * 得到数据库连接
     */
    public static Connection getConnection() throws ClassNotFoundException,
            SQLException, InstantiationException, IllegalAccessException {
    
    
        // 通过Config获取Mysql数据库配置信息
        String driver = Config.getValue("driver");
        String url = Config.getValue("url");
        String user = Config.getValue("user");
        String pwd = Config.getValue("password");

            // 指定驱动程序
            Class.forName(driver);
            // 建立数据库连结
            conn = DriverManager.getConnection(url, user, pwd);
            conn.setAutoCommit(false);//----------
            return conn;

    }
    //手动提交事务
    public void commitAll() {
    
    

        try {
    
    
            if(conn!=null&&!conn.isClosed())
                conn.commit();
        } catch (SQLException e) {
    
    
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
    //手动回滚事务

    public void rollbackAll() {
    
    
        try {
    
    
            if(conn!=null&&!conn.isClosed())
                conn.rollback();
        } catch (SQLException e) {
    
    
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
    /**
     * 释放资源
     */
    public void closeAll() {
    
    
        // 如果rs不空,关闭rs
        if (rs != null) {
    
    
            try {
    
    
                rs.close();
            } catch (SQLException e) {
    
    
                e.printStackTrace();
            }
        }
        // 如果pstmt不空,关闭pstmt
        if (pstmt != null) {
    
    
            try {
    
    
                pstmt.close();
            } catch (SQLException e) {
    
    
                e.printStackTrace();
            }
        }
        // 如果conn不空,关闭conn
        if (conn != null) {
    
    
            try {
    
    
                conn.close();
            } catch (SQLException e) {
    
    
                e.printStackTrace();
            }
        }
    }

    /**
     * 执行SQL语句,可以进行查询
     */
    public ResultSet executeQuery(String preparedSql, Object[] param) {
    
    
        // 处理SQL,执行SQL
        try {
    
    
            // 得到PreparedStatement对象
            pstmt = conn.prepareStatement(preparedSql);
            if (param != null) {
    
    
                for (int i = 0; i < param.length; i++) {
    
    
                    // 为预编译sql设置参数
                    pstmt.setObject(i + 1, param[i]);
                }
            }
            // 执行SQL语句
            rs = pstmt.executeQuery();
        } catch (SQLException e) {
    
    
            // 处理SQLException异常
            e.printStackTrace();
        }
        return rs;
    }

    /**
     * 执行SQL语句,可以进行增、删、改的操作,不能执行查询
     */
    public int executeUpdate(String preparedSql, Object[] param) {
    
    
        int num = 0;
        // 处理SQL,执行SQL
        try {
    
    
            // 得到PreparedStatement对象
            pstmt = conn.prepareStatement(preparedSql);
            if (param != null) {
    
    
                for (int i = 0; i < param.length; i++) {
    
    
                    // 为预编译sql设置参数
                    pstmt.setObject(i + 1, param[i]);
                }
            }
            // 执行SQL语句
            num = pstmt.executeUpdate();
        } catch (SQLException e) {
    
    
            if (e instanceof SQLIntegrityConstraintViolationException) {
    
    
                System.out.println("主键冲突,跳过当前记录");
                return 0;
            } else {
    
    
                // 处理其他SQL异常
                e.printStackTrace();
            }
        }
        return num;
    }
}

3.3 Configuration file

mysql.properties is as follows, which saves the configuration data of the database

driver = com.mysql.cj.jdbc.Driver
url = jdbc:mysql://localhost:3306/数据库名?serverTimezone=Asia/Shanghai&useSSL=false&useUnicode=true&characterEncoding=utf-8
user = ****
password = ******

client.properties saves the configuration of the client

host=******
port=******

server.properties saves the configuration of the server

port=******

3.4 Entity class and design

The parent class of DataBase defines the attributes common to log data and logistics data

package com.qst.dms.entity;

import java.io.Serializable;

public class DataBase implements Serializable {
    
    
    public static final int IN = 1;
    public static final int OUT = 0;
    // ID标识
    public int id;
    // 时间
    public String time;
    // 地点
    public String address;
    // 状态
    public int type;
    // 状态常量
    public static final int GATHER = 1;//"采集"
    public static final int MATHCH = 2;//"匹配";
    public static final int RECORD = 3;//"记录";
    public static final int SEND = 4;//"发送";
    public static final int RECIVE = 5;//"接收";
    public static final int WRITE = 6;//"归档";
    public static final int SAVE = 7;//"保存";
    public static final String DataType[]=new String[]{
    
    
            null,
            "GATHER",
            "MATHCH",
            "RECORD",
            "SEND",
            "RECIVE",
            "WRITE",
            "SAVE"
    };
    public DataBase(int id, String time, String address, int type) {
    
    
        this.id = id;
        this.time = time;
        this.address = address;
        this.type = type;
    }

    public DataBase() {
    
    

    }

    public int getId() {
    
    
        return id;
    }

    public void setId(int id) {
    
    
        this.id = id;
    }

    public String getTime() {
    
    
        return time;
    }

    public void setTime(String time) {
    
    
        this.time = time;
    }

    public String getAddress() {
    
    
        return address;
    }

    public void setAddress(String address) {
    
    
        this.address = address;
    }

    public int getType() {
    
    
        return type;
    }

    public void setType(int type) {
    
    
        this.type = type;
    }

    @Override
    public String toString() {
    
    
        return  "\nid=" + id +
                "\ntime=" + time +
                "\naddress=" + address +
                "\ntype=" + DataType[type]
                ;
    }
}

The LogRec class is a subclass of DataBase, which inherits DataBase and adds log data-specific attributes

package com.qst.dms.entity;

import javax.xml.crypto.Data;
import java.io.Serializable;
import java.util.Date;

public class LogRec extends DataBase implements Serializable {
    
    

    private static final String serialVersionUID = "1L";
    /**
     *  登录用户名
     */
    private String user;
    /**
     * 登录用户主机IP地址
     */
    private String ip;
    /**
     * 登录状态:登录、登出
     */
    private int logType;
    /**
     * 登录常量LOG_IN、登出常量常量LOG_OUT
     */
    public static final int LOG_IN=1;
    public static final int LOG_OUT=0;
    public static final String LogTypeArray[]=new String[]{
    
    
            "LogOut",
            "LogIn"
    };

    public LogRec(int id, String time, String address, int type, String user, String ip, int logType) {
    
    
        super(id, time, address, type);
        this.user = user;
        this.ip = ip;
        this.logType = logType;
    }

    public LogRec() {
    
    
        super();
    }

    public String getUser() {
    
    
        return user;
    }

    public void setUser(String user) {
    
    
        this.user = user;
    }

    public String getIp() {
    
    
        return ip;
    }

    public void setIp(String ip) {
    
    
        this.ip = ip;
    }

    public int getLogType() {
    
    
        return logType;
    }

    public void setLogType(int logType) {
    
    
        this.logType = logType;
    }

    @Override
    public String toString() {
    
    
        return  "LogRec: " +
                super.toString() +
                "\nuser=" + user +
                "\nip=" + ip +
                "\nlogType=" + LogTypeArray[logType] +
                "\n";
    }

    public String[] toArray() {
    
    
        String data = this.getId() + "," + this.getTime() + "," + this.getAddress() + "," + this.getType() + "," + this.getUser() + "," + this.getIp() + "," + LogTypeArray[this.getLogType()];
        return data.split(",");
    }
}

The Transport class is a subclass of DataBase, which inherits DataBase and adds logistics data-specific attributes

package com.qst.dms.entity;

import java.io.Serializable;
import java.util.Date;

public class Transport extends DataBase implements Serializable {
    
    

    private static final String serialVersionUID = "1L";
    /**
     * 经手人
     */
    private String handler;
    /**
     * 收货人
     */
    private String reciver;
    /**
     * 物流状态
     */
    private int transportType;
    /**
     * 物流状态常量:发货中, 送货中, 已签收
     */
    public static final int SENDING = 1;// 发货中
    public static final int TRANSPORTING = 2;// 送货中
    public static final int RECEIVED = 3;// 已签收
    public static final String TransportArray[]=new String[]{
    
    
            null,
            "SENDDING",
            "TRANSPORTING",
            "RECIEVED"
    };

    public Transport(int id, String time, String address, int type, String handler, String reciver, int transportType) {
    
    
        super(id, time, address, type);
        this.handler = handler;
        this.reciver = reciver;
        this.transportType = transportType;
    }

    public Transport() {
    
    
        super();
    }

    public String getHandler() {
    
    
        return handler;
    }

    public void setHandler(String handler) {
    
    
        this.handler = handler;
    }

    public String getReciver() {
    
    
        return reciver;
    }

    public void setReciver(String reciver) {
    
    
        this.reciver = reciver;
    }

    public int getTransportType() {
    
    
        return transportType;
    }

    public void setTransportType(int transportType) {
    
    
        this.transportType = transportType;
    }

    @Override
    public String toString() {
    
    
        return  "Transport: " +
                super.toString() +
                "\nhandler=" + handler +
                "\nreciver=" + reciver +
                "\ntransportType=" + TransportArray[transportType] +
                "\n";
    }

    public String[] toArray() {
    
    
        String data = this.getId() + "," + this.getTime() + "," + this.getAddress() + "," + this.getType() + "," + this.getHandler() + "," + this.getReciver() + "," + TransportArray[this.getTransportType()];
        return data.split(",");
    }
}

The MatchedDataBase class, without writing code, represents the matched data

package com.qst.dms.entity;

import java.io.Serializable;

public class MatchedDataBase implements Serializable {
    
    
    private static final String serialVersionUID = "1L";
}

The MatchedLogRec class inherits the MatchedDataBase class and adds proprietary properties and methods for matching log information

package com.qst.dms.entity;

import java.io.Serializable;

public class MatchedLogRec extends MatchedDataBase implements Serializable {
    
    

    private static final String serialVersionUID = "1L";
    private LogRec login;
    private LogRec logout;

    // user用户登录名
    public String getUser() {
    
    
        return login.getUser();
    }

    // 登入时刻
    public String getLogInTime() {
    
    
        return login.getTime();
    }

    // 登出时刻
    public String getLogoutTime() {
    
    
        return logout.getTime();
    }

    // 登入记录
    public LogRec getLogin() {
    
    
        return login;
    }

    // 登出记录
    public LogRec getLogout() {
    
    
        return logout;
    }

    public MatchedLogRec() {
    
    
    }

    public MatchedLogRec(LogRec login, LogRec logout) {
    
    
        this.login = login;
        this.logout = logout;
    }

    @Override
    public String toString() {
    
    
        return login.toString() + " | " + logout.toString();
    }

}

The MatchedTransport class inherits the MatchedDataBase class and adds proprietary attributes and methods for matching logistics information

package com.qst.dms.entity;

import java.io.Serializable;

public class MatchedTransport extends MatchedDataBase implements Serializable {
    
    

    private static final String serialVersionUID = "1L";
    private Transport send;
    private Transport trans;
    private Transport receive;

    public MatchedTransport(Transport send, Transport tran, Transport rec) {
    
    
        this.send=send;
        this.trans=tran;
        this.receive=rec;
    }

    public MatchedTransport() {
    
    

    }

    public Transport getSend() {
    
    
        return send;
    }

    public void setSend(Transport send) {
    
    
        this.send = send;
    }

    public Transport getTrans() {
    
    
        return trans;
    }

    public void setTrans(Transport trans) {
    
    
        this.trans = trans;
    }

    public Transport getReceive() {
    
    
        return receive;
    }

    public void setReceive(Transport receive) {
    
    
        this.receive = receive;
    }

    @Override
    public String toString() {
    
    
        return send.toString() + " | " + trans.toString() + " | " + receive.toString();
    }
}

The User class defines user information for user registration and login

package com.qst.dms.entity;

public class User {
    
    

    public String username;
    public String password;
    public Integer gender;
    public String hobby;
    public String address;
    public String degree;


    public User() {
    
    
    }

    public User(String username, String password, Integer gender, String hobby, String address, String degree) {
    
    
        this.username = username;
        this.password = password;
        this.gender = gender;
        this.hobby = hobby;
        this.address = address;
        this.degree = degree;
    }



    /**
     * 获取
     * @return username
     */
    public String getUsername() {
    
    
        return username;
    }

    /**
     * 设置
     * @param username
     */
    public void setUsername(String username) {
    
    
        this.username = username;
    }

    /**
     * 获取
     * @return password
     */
    public String getPassword() {
    
    
        return password;
    }

    /**
     * 设置
     * @param password
     */
    public void setPassword(String password) {
    
    
        this.password = password;
    }

    /**
     * 获取
     * @return gender
     */
    public Integer getGender() {
    
    
        return gender;
    }

    /**
     * 设置
     * @param gender
     */
    public void setGender(Integer gender) {
    
    
        this.gender = gender;
    }

    /**
     * 获取
     * @return hobby
     */
    public String getHobby() {
    
    
        return hobby;
    }

    /**
     * 设置
     * @param hobby
     */
    public void setHobby(String hobby) {
    
    
        this.hobby = hobby;
    }

    /**
     * 获取
     * @return address
     */
    public String getAddress() {
    
    
        return address;
    }

    /**
     * 设置
     * @param address
     */
    public void setAddress(String address) {
    
    
        this.address = address;
    }

    /**
     * 获取
     * @return degree
     */
    public String getDegree() {
    
    
        return degree;
    }

    /**
     * 设置
     * @param degree
     */
    public void setDegree(String degree) {
    
    
        this.degree = degree;
    }

    public String toString() {
    
    
        return "User{username = " + username + ", password = " + password + ", gender = " + gender + ", hobby = " + hobby + ", address = " + address + ", degree = " + degree + "}";
    }
}

3.5 Business category and design

The DmsNetService class is used for the connection service between the client and the server, to ensure the successful connection between the client and the server and to transmit data

package com.qst.dms.service;


import com.qst.dms.net.Request;
import com.qst.dms.net.Response;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

import java.net.Socket;

public class DmsNetService {
    
    
    private  static  DmsNetService instance = new DmsNetService();
    private  DmsNetService(){
    
    
    }

    public static DmsNetService getInstance(){
    
    
        return  instance;
    }

    public static void  sendRequest(Socket socket, Request request) throws IOException{
    
    
        ObjectOutputStream out = new ObjectOutputStream(socket.getOutputStream());
        out.writeObject(request);
        out.flush();
    }

    public static Request receiveRequest(Socket socket) throws ClassNotFoundException, IOException{
    
    
        ObjectInputStream in = new ObjectInputStream(socket.getInputStream());
        Request req = (Request)in.readObject();
        return req;
    }

    public static void sendResponse(Socket socket, Response response) throws IOException{
    
    
        ObjectOutputStream out = new ObjectOutputStream(socket.getOutputStream());
        out.writeObject(response);
        out.flush();
    }

    public static Response receiveResponse(Socket socket) throws IOException,ClassNotFoundException{
    
    
        ObjectInputStream in = new ObjectInputStream(socket.getInputStream());
        Response res = (Response)in.readObject();
        return res;
    }

}

There are many methods in the LogRecService class, including the file operation and database operation of the log data, and realize the access of the log data.

package com.qst.dms.service;

import com.qst.dms.entity.LogRec;
import com.qst.dms.entity.MatchedLogRec;
import com.qst.dms.exception.DataAnalyseException;
import com.qst.dms.gather.LogRecAnalyse;
import com.qst.dms.util.AppendObjectOutputStream;
import com.qst.dms.util.DBUtil;
import java.io.*;
import java.sql.*;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Scanner;

public class LogRecService {
    
    

    private static final String saveFile = "MatchedLogRec.dat";
    private Scanner scanner;

    public LogRecService() {
    
    
        scanner = new Scanner(System.in);
    }

    public LogRec inputLog() {
    
    
        int id, type, logType;
        String address;
        String user;
        String ip;
        String formattedDate;
        while (true) {
    
    
            try {
    
    
                System.out.println("请输入ID标识:");
                id = scanner.nextInt();

                Date currentDate = new Date();
                SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                formattedDate = dateFormat.format(currentDate);

                System.out.println("请输入地址:");
                address = scanner.next();
                type = LogRec.GATHER;

                System.out.println("请输入登录用户名:");
                user = scanner.next();

                System.out.println("请输入主机IP:");
                ip = scanner.next();

                System.out.println("请输入登录状态(1表示登录,0表示登出):");
                logType = scanner.nextInt();
                if (logType == 0 || logType == 1) {
    
    
                    break;
                } else {
    
    
                    throw new IllegalArgumentException("非法的登录状态");
                }
            } catch (Exception e) {
    
    
                System.out.println("输入错误,请重新输入");
                scanner.nextLine();
            }
        }
        return new LogRec(id, formattedDate, address, type, user, ip, logType);
    }

    public void showLog(List<LogRec> logRecs) {
    
    
        System.out.println("日志信息:");
        for (LogRec logRec : logRecs) {
    
    
            System.out.println(logRec);
        }
    }

    // 匹配日志信息输出,参数是集合
    public void showMatchLog(List<MatchedLogRec> matchLogs) {
    
    
        System.out.println("匹配日志信息:");
        for (MatchedLogRec matchLog : matchLogs) {
    
    
            System.out.println(matchLog);
        }
    }

    // 保存
    public static void saveLogRec(List<LogRec> Logs) {
    
    
        try {
    
    
            AppendObjectOutputStream.setFile(new File(saveFile));
            File file = AppendObjectOutputStream.getFile();
            FileOutputStream fileOut = new FileOutputStream(file, true);
            AppendObjectOutputStream objOut = new AppendObjectOutputStream(file);

            for (LogRec Log : Logs) {
    
    
                objOut.writeObject(Log);
            }

            objOut.close();
            fileOut.close();
            System.out.println("匹配日志信息保存成功\n");
        } catch (IOException e) {
    
    
            System.out.println("保存匹配日志信息发生异常:" + e.getMessage()+"\n");
        }
    }

    //匹配
    public static List<MatchedLogRec> readMatchLogRec() {
    
    

        List<MatchedLogRec> matchedLogs = new ArrayList<>();

        List<LogRec> logs = readLogRec();

        try {
    
    
            AppendObjectOutputStream.setFile(new File(saveFile));
            File file = AppendObjectOutputStream.getFile();
            if (!file.exists()) {
    
    
                file.createNewFile();
            }

            FileInputStream fileIn = new FileInputStream(file);

            // 创建一个ObjectInputStream对象输入流,并连接文件输入流
            ObjectInputStream objIn = new ObjectInputStream(fileIn);

            // 创建日志数据分析对象
            LogRecAnalyse logAnalyse = new LogRecAnalyse(logs);

            // 日志数据过滤
            logAnalyse.doFilter();

            // 日志数据匹配分析
            try {
    
    
                List<MatchedLogRec> objs = logAnalyse.matchData(); // 进行数据匹配
                // 处理匹配的日志数据
                // 判断objs集合是否是配置日志集合
                if (objs instanceof List<?>) {
    
    
                    // 将集合强制类型转换成配置日志集合
                    matchedLogs = (List<MatchedLogRec>) objs;
                }
            } catch (DataAnalyseException e) {
    
    
                System.out.println(e.getMessage());
            }

            objIn.close();
            fileIn.close();
            System.out.println("匹配日志信息读取完成\n");
        } catch (IOException e) {
    
    
            System.out.println("读取匹配日志信息发生异常:" + e.getMessage()+"\n");
        }

        return matchedLogs;
    }

    //显示日志
    public static List<LogRec> readLogRec() {
    
    

        List<LogRec> logs = new ArrayList<>();

        try {
    
    
            AppendObjectOutputStream.setFile(new File(saveFile));
            File file = AppendObjectOutputStream.getFile();
            if (!file.exists()) {
    
    
                file.createNewFile();
            }

            FileInputStream fileIn = new FileInputStream(file);

            // 创建一个ObjectInputStream对象输入流,并连接文件输入流
            ObjectInputStream objIn = new ObjectInputStream(fileIn);

            // 使用异常处理和EOFException异常处理读取结束
            try {
    
    
                while (true) {
    
    
                    LogRec log = (LogRec) objIn.readObject();
                    logs.add(log);
                }
            } catch (EOFException e) {
    
    
                // 读取结束,不做任何操作
            }

            objIn.close();
            fileIn.close();

            System.out.println("日志信息读取完成\n");
        } catch (IOException | ClassNotFoundException e) {
    
    
            System.out.println("读取日志信息发生异常:" + e.getMessage() +"\n");
        }

        return logs;
    }

    //显示能匹配的日志信息
    public static List<LogRec> readLogRecs() {
    
    
        List<LogRec> logs = new ArrayList<>();
        List<MatchedLogRec> matchlogs = readMatchLogRec();
        for(MatchedLogRec matchlog:matchlogs){
    
    
            logs.add(matchlog.getLogin());
            logs.add(matchlog.getLogout());
        }

        return logs;
    }

    /*
    // 匹配日志信息保存到数据库,参数是集合
    public static void saveMatchLogToDB() {

        List<MatchedLogRec> matchLogs = readMatchLogRec();

        List<LogRec> login = new ArrayList<>();
        List<LogRec> logout = new ArrayList<>();

        List<LogRec> logs = readLogRec();

        Connection conn = null;
        try {
            DBUtil db = new DBUtil();
            conn = db.getConnection();

            for (MatchedLogRec matchlog : matchLogs) {
                int loginId = matchlog.getLogin().getId();
                int logoutId = matchlog.getLogout().getId();

                for (LogRec log : logs) {
                    if (log.getId() == loginId) {
                        login.add(log);
                    } else if (log.getId() == logoutId) {
                        logout.add(log);
                    }
                }
            }

            // 保存匹配记录中的登录日志
            String querySqllogin = "INSERT INTO log_in VALUES (?, ?, ?, ?, ?, ?, ?)";
            for (LogRec log : login) {
                Object[] queryParams = {log.getId(), log.getTime(), log.getAddress(), log.getType(), log.getUser(), log.getIp(), log.getLogType()};
                db.executeUpdate(querySqllogin, queryParams);
            }
            System.out.println("保存匹配记录中的登录日志成功");

            // 保存匹配记录中的登出日志
            String querySqllogout = "INSERT INTO log_out VALUES (?, ?, ?, ?, ?, ?, ?)";
            for (LogRec log : logout) {
                Object[] queryParams = {log.getId(), log.getTime(), log.getAddress(), log.getType(), log.getUser(), log.getIp(), log.getLogType()};
                db.executeUpdate(querySqllogout, queryParams);
            }
            System.out.println("保存匹配记录中的登出日志成功");

            // 保存匹配日志的ID
            String querySqlmatch = "INSERT INTO log_match VALUES (?, ?)";
            for (MatchedLogRec matchlog : matchLogs) {
                Object[] queryParams = {matchlog.getLogin().getId(), matchlog.getLogout().getId()};
                db.executeUpdate(querySqlmatch, queryParams);
            }
            System.out.println("保存匹配日志的ID成功");

            db.commitAll();

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            // 关闭数据库连接,释放资源
            if (conn != null) {
                try {
                    conn.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    */
/*
    public static List<MatchedLogRec> readMatchedLogFromDB() {
        DBUtil db = new DBUtil();
        Connection conn = null;
        List<MatchedLogRec> matchedLogs = new ArrayList<>();

        try {
            conn = db.getConnection();

            // 查询匹配的日志
            String querySqlMatchedLogs = "SELECT * FROM log_match";

            ResultSet matchedLogsResult = db.executeQuery(querySqlMatchedLogs,null);

            while (matchedLogsResult.next()) {
                int loginId = matchedLogsResult.getInt("login_id");
                int logoutId = matchedLogsResult.getInt("logout_id");

                // 获取登录记录
                LogRec login = new LogRec();

                String querySqlLogin = "SELECT * FROM log_in WHERE id = ?";
                Object[] loginParams = { loginId };
                ResultSet loginResult = db.executeQuery(querySqlLogin, loginParams);

                if (loginResult.next()) {
                    // 设置登录记录的属性值
                    login.setId(loginResult.getInt("id"));
                    login.setTime(loginResult.getString("time"));
                    login.setAddress(loginResult.getString("address"));
                    login.setType(loginResult.getInt("type"));
                    login.setUser(loginResult.getString("user"));
                    login.setIp(loginResult.getString("ip"));
                    login.setLogType(loginResult.getInt("logtype"));

                    // 获取登出记录
                    LogRec logout = new LogRec();

                    String querySqlLogout = "SELECT * FROM log_out WHERE id = ?";
                    Object[] logoutParams = { logoutId };
                    ResultSet logoutResult = db.executeQuery(querySqlLogout, logoutParams);

                    if (logoutResult.next()) {
                        // 设置登出记录的属性值
                        logout.setId(logoutResult.getInt("id"));
                        logout.setTime(logoutResult.getString("time"));
                        logout.setAddress(logoutResult.getString("address"));
                        logout.setType(logoutResult.getInt("type"));
                        logout.setUser(logoutResult.getString("user"));
                        logout.setIp(logoutResult.getString("ip"));
                        logout.setLogType(logoutResult.getInt("logtype"));

                        // 添加匹配登录信息到匹配集合
                        MatchedLogRec matchedLog = new MatchedLogRec( login,  logout);
                        matchedLogs.add(matchedLog);
                    }

                    logoutResult.close();
                }

                loginResult.close();
            }
            matchedLogsResult.close();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            // 关闭数据库连接,释放资源
            if (conn != null) {
                try {
                    conn.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }

        return matchedLogs;
    }

 */

    public static void saveLogResult(List<MatchedLogRec> matchlogs) {
    
    

        Connection conn = null;
        try {
    
    
            DBUtil db = new DBUtil();
            conn = db.getConnection();

            // 保存匹配记录中的登录日志
            String querySqllogin = "INSERT INTO gather_logrec VALUES (?, ?, ?, ?, ?, ?, ?)";
            for (MatchedLogRec matchlog : matchlogs) {
    
    
                Object[] queryinParams = {
    
    matchlog.getLogin().getId(), matchlog.getLogin().getTime(), matchlog.getLogin().getAddress(), matchlog.getLogin().getType(), matchlog.getLogin().getUser(), matchlog.getLogin().getIp(), matchlog.getLogin().getLogType()};
                db.executeUpdate(querySqllogin, queryinParams);
                Object[] queryoutParams = {
    
    matchlog.getLogout().getId(), matchlog.getLogout().getTime(), matchlog.getLogout().getAddress(), matchlog.getLogout().getType(), matchlog.getLogout().getUser(), matchlog.getLogout().getIp(), matchlog.getLogout().getLogType()};
                db.executeUpdate(querySqllogin, queryoutParams);
            }
            System.out.println("保存匹配记录日志到数据库成功");

            db.commitAll();

        } catch (Exception e) {
    
    
            e.printStackTrace();
        } finally {
    
    
            // 关闭数据库连接,释放资源
            if (conn != null) {
    
    
                try {
    
    
                    conn.close();
                } catch (SQLException e) {
    
    
                    e.printStackTrace();
                }
            }
        }
    }

    //LogRecService类中增加方法readLogResult()
    //获取数据库中的所有匹配的日志信息,返回一个ResultSet
    public static ResultSet readLogResult() {
    
    

        ResultSet matchedLogsResult = null;
        //获取匹配日志表中的所有数据,返回ResultSet
        //创建语句时使用:
        DBUtil db = new DBUtil();
        Connection conn = null;

        try {
    
    
            conn = db.getConnection();

            Statement st = conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_UPDATABLE);

            // 查询匹配的日志
            String querySqlMatchedLogs = "SELECT * FROM gather_logrec";

            matchedLogsResult = st.executeQuery(querySqlMatchedLogs);

        } catch (Exception e) {
    
    
            e.printStackTrace();
        }
        return matchedLogsResult;
    }

}

There are many methods in the TransportService class, which includes the file operation and database operation of logistics data, and realizes the access of logistics data.

package com.qst.dms.service;

import com.qst.dms.entity.MatchedLogRec;
import com.qst.dms.entity.MatchedTransport;
import com.qst.dms.entity.Transport;
import com.qst.dms.exception.DataAnalyseException;
import com.qst.dms.gather.TransportAnalyse;
import com.qst.dms.util.AppendObjectOutputStream;
import com.qst.dms.util.DBUtil;
import java.io.*;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Scanner;

public class TransportService {
    
    

    private static final String saveFile = "MatchedTransport.dat";
    private Scanner scanner;

    public TransportService() {
    
    
        scanner = new Scanner(System.in);
    }

    public Transport inputTransport() {
    
    
        int transportType;
        int id, type;
        String formattedDate;
        String address, handler, receiver;

        while (true) {
    
    
            try {
    
    
                System.out.println("请输入ID标识:");
                id = scanner.nextInt();

                Date currentDate = new Date();
                SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                formattedDate = dateFormat.format(currentDate);

                System.out.println("请输入地址:");
                address = scanner.next();
                type = Transport.GATHER;

                System.out.println("请输入货物经手人:");
                handler = scanner.next();

                System.out.println("请输入收货人:");
                receiver = scanner.next();

                System.out.println("请输入物流状态(1表示发货中,2表示送货中,3表示已签收):");
                transportType = scanner.nextInt();
                if (transportType == 1 || transportType == 2 || transportType == 3) {
    
    
                    break;
                } else {
    
    
                    throw new IllegalArgumentException("非法的物流状态");
                }
            } catch (Exception e) {
    
    
                System.out.println("输入错误,请重新输入");
                scanner.nextLine();
            }
        }

        return new Transport(id, formattedDate, address, type, handler, receiver, transportType);
    }

    public void showTransport(List<Transport> transports) {
    
    
        System.out.println("物流信息:");
        for (Transport transport : transports) {
    
    
            System.out.println(transport);
        }
    }

    // 匹配物流信息输出,参数是集合
    public void showMatchTransport(List<MatchedTransport> matchTrans) {
    
    
        System.out.println("匹配物流信息:");
        for (MatchedTransport matchTran : matchTrans) {
    
    
            System.out.println(matchTran);
        }
    }

    // 保存
    public static void saveTransport(List<Transport> transports) {
    
    
        try {
    
    
            AppendObjectOutputStream.setFile(new File(saveFile));
            File file = AppendObjectOutputStream.getFile();
            FileOutputStream fileOut = new FileOutputStream(file, true);
            AppendObjectOutputStream objOut = new AppendObjectOutputStream(file);

            for (Transport transport : transports) {
    
    
                objOut.writeObject(transport);
            }

            objOut.close();
            fileOut.close();
            System.out.println("匹配物流信息保存成功\n");
        } catch (IOException e) {
    
    
            System.out.println("保存匹配物流信息发生异常:" + e.getMessage() + "\n");
        }
    }

    //匹配
    public static List<MatchedTransport> readMatchTransport() {
    
    

        List<MatchedTransport> matchedTransports = new ArrayList<>();

        List<Transport> transports = readTransport();

        try {
    
    
            AppendObjectOutputStream.setFile(new File(saveFile));
            File file = AppendObjectOutputStream.getFile();
            if (!file.exists()) {
    
    
                file.createNewFile();
            }

            FileInputStream fileIn = new FileInputStream(file);

            // 创建一个ObjectInputStream对象输入流,并连接文件输入流
            ObjectInputStream objIn = new ObjectInputStream(fileIn);

            // 创建物流数据分析对象

            TransportAnalyse ta = new TransportAnalyse(transports);

            // 物流数据过滤
            ta.doFilter();

            try {
    
    
                // 物流数据分析
                List<MatchedTransport> objs = ta.matchData();
                // 判断objs集合是否是匹配物流集合
                if (objs instanceof List<?>) {
    
    
                    // 将集合强制类型转换成匹配物流集合
                    matchedTransports = (ArrayList<MatchedTransport>) objs;
                }
            } catch (DataAnalyseException e) {
    
    
                System.out.println(e.getMessage());
            }

            objIn.close();
            fileIn.close();

            System.out.println("匹配物流信息读取完成\n");
        } catch (IOException e) {
    
    
            System.out.println("读取匹配物流信息发生异常:" + e.getMessage() + "\n");
        }

        return matchedTransports;
    }

    //显示物流信息
    public static List<Transport> readTransport() {
    
    
        List<Transport> transports = new ArrayList<>();

        try {
    
    
            AppendObjectOutputStream.setFile(new File(saveFile));
            File file = AppendObjectOutputStream.getFile();
            if (!file.exists()) {
    
    
                file.createNewFile();
            }

            FileInputStream fileIn = new FileInputStream(file);

            // 创建一个ObjectInputStream对象输入流,并连接文件输入流
            ObjectInputStream objIn = new ObjectInputStream(fileIn);

            // 使用异常处理和EOFException异常处理读取结束
            try {
    
    
                while (true) {
    
    
                    Transport transport = (Transport) objIn.readObject();
                    transports.add(transport);
                }
            } catch (EOFException e) {
    
    
                // 读取结束,不做任何操作
            }

            objIn.close();
            fileIn.close();

            System.out.println("物流信息读取完成\n");
        } catch (IOException | ClassNotFoundException e) {
    
    
            System.out.println("读取物流信息发生异常:" + e.getMessage() + "\n");
        }

        return transports;
    }

    //显示能匹配的物流信息
    public static List<Transport> readTransports() {
    
    
        List<Transport> transports = new ArrayList<>();
        List<MatchedTransport> matchtrans = readMatchTransport();

        for(MatchedTransport matchtran : matchtrans){
    
    
            transports.add(matchtran.getSend());
            transports.add(matchtran.getTrans());
            transports.add(matchtran.getReceive());
        }

        return transports;
    }
/*
    // 匹配日志信息保存到数据库,参数是集合
    public static void saveMatchTransportToDB() {

        List<MatchedTransport> matchTrans = readMatchTransport();

        List<Transport> sendList = new ArrayList<>();
        List<Transport> tranList = new ArrayList<>();
        List<Transport> recList = new ArrayList<>();

        List<Transport> transports = readTransport();

        Connection conn = null;

        try {
            DBUtil db = new DBUtil();
            conn = db.getConnection();

            for (MatchedTransport matchTran : matchTrans){
                int send = matchTran.getSend().getId();
                int tran = matchTran.getTrans().getId();
                int rec =  matchTran.getReceive().getId();

                for (Transport transport : transports){
                    if (transport.getId() == send){
                        sendList.add(transport);
                    }else if(transport.getId() == tran){
                        tranList.add(transport);
                    }else if(transport.getId() == rec){
                        recList.add(transport);
                    }
                }
            }

            String querySqllogsend = "INSERT INTO send VALUES (?, ?, ?, ?, ?, ?, ?)";
            for (Transport transport: sendList) {
                Object[] queryParams = {transport.getId(), transport.getTime(), transport.getAddress(), transport.getType(), transport.getHandler(), transport.getReciver(), transport.getTransportType()};
                db.executeUpdate(querySqllogsend, queryParams);
            }
            System.out.println("保存匹配物流中的发送日志成功");

            String querySqllogtran = "INSERT INTO tran VALUES (?, ?, ?, ?, ?, ?, ?)";
            for (Transport transport: tranList) {
                Object[] queryParams = {transport.getId(), transport.getTime(), transport.getAddress(), transport.getType(), transport.getHandler(), transport.getReciver(), transport.getTransportType()};
                db.executeUpdate(querySqllogtran, queryParams);
            }
            System.out.println("保存匹配物流中的运输日志成功");

            String querySqllogrec = "INSERT INTO receive VALUES (?, ?, ?, ?, ?, ?, ?)";
            for (Transport transport: recList) {
                Object[] queryParams = {transport.getId(), transport.getTime(), transport.getAddress(), transport.getType(), transport.getHandler(), transport.getReciver(), transport.getTransportType()};
                db.executeUpdate(querySqllogrec, queryParams);
            }
            System.out.println("保存匹配物流中的接收日志成功");


            // 保存匹配日志的ID
            String querySqlmatch = "INSERT INTO matchtrans VALUES (?, ?, ?)";
            for (MatchedTransport matchtran : matchTrans) {
                Object[] queryParams = {matchtran.getSend().getId(), matchtran.getTrans().getId(), matchtran.getReceive().getId()};
                db.executeUpdate(querySqlmatch, queryParams);
            }
            System.out.println("保存匹配物流的ID成功");

            db.commitAll();

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            // 关闭数据库连接,释放资源
            if (conn != null) {
                try {
                    conn.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public static List<MatchedTransport> readMatchedTransportFromDB() {
        DBUtil db = new DBUtil();
        Connection conn = null;
        List<MatchedTransport> matchedtrans = new ArrayList<>();

        try {
            conn = db.getConnection();

            // 查询匹配的日志
            String querySqlmatchedtrans = "SELECT * FROM matchtrans";

            ResultSet matchedtransResult = db.executeQuery(querySqlmatchedtrans,null);

            while (matchedtransResult.next()) {
                int sendId = matchedtransResult.getInt("sendid");
                int tranId = matchedtransResult.getInt("tranid");
                int recId = matchedtransResult.getInt("recid");

                Transport sendList = new Transport();

                String querySqlsendList = "SELECT * FROM send WHERE id = ?";
                Object[] sendListParams = { sendId };
                ResultSet sendResult = db.executeQuery(querySqlsendList, sendListParams);

                if (sendResult.next()) {

                    sendList.setId(sendResult.getInt("id"));
                    sendList.setTime(sendResult.getString("time"));
                    sendList.setAddress(sendResult.getString("address"));
                    sendList.setType(sendResult.getInt("type"));
                    sendList.setHandler(sendResult.getString("handler"));
                    sendList.setReciver(sendResult.getString("receiver"));
                    sendList.setTransportType(sendResult.getInt("trantype"));

                    Transport tranList = new Transport();

                    String querySqltranList = "SELECT * FROM tran WHERE id = ?";
                    Object[] tranListParams = { tranId };
                    ResultSet tranListResult = db.executeQuery(querySqltranList, tranListParams);

                    if (tranListResult.next()) {
                        // 设置登出记录的属性值
                        tranList.setId(tranListResult.getInt("id"));
                        tranList.setTime(tranListResult.getString("time"));
                        tranList.setAddress(tranListResult.getString("address"));
                        tranList.setType(tranListResult.getInt("type"));
                        tranList.setHandler(tranListResult.getString("handler"));
                        tranList.setReciver(tranListResult.getString("receiver"));
                        tranList.setTransportType(tranListResult.getInt("trantype"));


                        Transport recList = new Transport();

                        String querySqlrecList = "SELECT * FROM receive WHERE id = ?";
                        Object[] recListParams = { recId };
                        ResultSet recListResult = db.executeQuery(querySqlrecList, recListParams);

                        if (recListResult.next()) {
                            // 设置登出记录的属性值
                            recList.setId(recListResult.getInt("id"));
                            recList.setTime(recListResult.getString("time"));
                            recList.setAddress(recListResult.getString("address"));
                            recList.setType(recListResult.getInt("type"));
                            recList.setHandler(recListResult.getString("handler"));
                            recList.setReciver(recListResult.getString("receiver"));
                            recList.setTransportType(recListResult.getInt("trantype"));

                            // 添加匹配登录信息到匹配集合
                            MatchedTransport matchedLog = new MatchedTransport( sendList, tranList, recList);
                            matchedtrans.add(matchedLog);
                        }

                        recListResult.close();
                    }

                    tranListResult.close();
                }

                sendResult.close();
            }
            matchedtransResult.close();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            // 关闭数据库连接,释放资源
            if (conn != null) {
                try {
                    conn.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }

        return matchedtrans;
    }

 */
    // 匹配日志信息保存到数据库,参数是集合
    public static void saveTranResult(List<MatchedTransport> matchtrans) {
    
    

        Connection conn = null;

        try {
    
    
            DBUtil db = new DBUtil();
            conn = db.getConnection();


            String querySqllogsend = "INSERT INTO gather_transport VALUES (?, ?, ?, ?, ?, ?, ?)";
            for (MatchedTransport matchtran: matchtrans) {
    
    
                Object[] queryParamsSend = {
    
    matchtran.getSend().getId(), matchtran.getSend().getTime(), matchtran.getSend().getAddress(), matchtran.getSend().getType(), matchtran.getSend().getHandler(), matchtran.getSend().getReciver(), matchtran.getSend().getTransportType()};
                db.executeUpdate(querySqllogsend, queryParamsSend);
                Object[] queryParamsTran = {
    
    matchtran.getTrans().getId(), matchtran.getTrans().getTime(), matchtran.getTrans().getAddress(), matchtran.getTrans().getType(), matchtran.getTrans().getHandler(), matchtran.getTrans().getReciver(), matchtran.getTrans().getTransportType()};
                db.executeUpdate(querySqllogsend, queryParamsTran);
                Object[] queryParamsRec = {
    
    matchtran.getReceive().getId(), matchtran.getReceive().getTime(), matchtran.getReceive().getAddress(), matchtran.getReceive().getType(), matchtran.getReceive().getHandler(), matchtran.getReceive().getReciver(), matchtran.getReceive().getTransportType()};
                db.executeUpdate(querySqllogsend, queryParamsRec);
            }
            System.out.println("保存匹配物流日志到数据库成功");


            db.commitAll();

        } catch (Exception e) {
    
    
            e.printStackTrace();
        } finally {
    
    
            // 关闭数据库连接,释放资源
            if (conn != null) {
    
    
                try {
    
    
                    conn.close();
                } catch (SQLException e) {
    
    
                    e.printStackTrace();
                }
            }
        }
    }
    //获取数据库中的所有匹配的物流信息,返回一个ResultSet
    public ResultSet readTransResult() {
    
    
        //获取匹配物流表中的所有数据,返回ResultSet
        ResultSet matchedTransResult = null;
        //获取匹配日志表中的所有数据,返回ResultSet
        //创建语句时使用:
        DBUtil db = new DBUtil();
        Connection conn = null;
        ArrayList<MatchedTransport> matchedTrans = new ArrayList<>();

        try {
    
    
            conn = db.getConnection();
            Statement st = conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_UPDATABLE);

            // 查询匹配的日志
            String querySqlMatchedLogs = "SELECT * FROM gather_transport";

            matchedTransResult = st.executeQuery(querySqlMatchedLogs);

        } catch (Exception e) {
    
    
            e.printStackTrace();
        }
        return matchedTransResult;
    }
}

The UserService class implements user registration and storage of login information, and stores user information in the database.

package com.qst.dms.service;

import com.qst.dms.entity.User;
import com.qst.dms.util.DBUtil;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;

public class UserService {
    
    

    DBUtil db = new DBUtil();
    Connection conn = null;

    // 根据用户名查询用户,各用户的用户名不能相同
    public User findUserByName(String userName) {
    
    
        // 返回符合条件的用户对象
        User user = new User();

        try {
    
    
            try {
    
    
                conn = db.getConnection();
            } catch (ClassNotFoundException e) {
    
    
                e.printStackTrace();
            } catch (SQLException throwables) {
    
    
                throwables.printStackTrace();
            } catch (InstantiationException e) {
    
    
                e.printStackTrace();
            } catch (IllegalAccessException e) {
    
    
                e.printStackTrace();
            }


            String querySqluser = "SELECT * FROM users WHERE username = ?";
            Object[] userParams = {
    
    userName};
            ResultSet userResult = db.executeQuery(querySqluser, userParams);
            db.commitAll();

            if (userResult.next()) {
    
    
                // 设置登出记录的属性值
                user.setUsername(userResult.getString("username"));
                user.setPassword(userResult.getString("password"));
                user.setAddress(userResult.getString("address"));
                user.setGender(userResult.getInt("gender"));
                user.setHobby(userResult.getString("hobby"));
                user.setDegree(userResult.getString("degree"));
            }
            userResult.close();

        } catch (Exception e) {
    
    
            e.printStackTrace();
        } finally {
    
    
            // 关闭数据库连接,释放资源
            if (conn != null) {
    
    
                try {
    
    
                    conn.close();
                } catch (SQLException e) {
    
    
                    e.printStackTrace();
                }
            }
        }
        return user;
    }

    // 保存用户信息
    public boolean saveUser(User user) {
    
    
        // 返回保存结果,成功返回true,失败返回false
        try {
    
    
            try {
    
    
                conn = db.getConnection();
            } catch (ClassNotFoundException e) {
    
    
                e.printStackTrace();
            } catch (SQLException throwables) {
    
    
                throwables.printStackTrace();
            } catch (InstantiationException e) {
    
    
                e.printStackTrace();
            } catch (IllegalAccessException e) {
    
    
                e.printStackTrace();
            }

            String querySqluser = "INSERT INTO users(username,password,gender,hobby,address,degree) VALUES (?, ?, ?, ?, ?, ?)";
            Object[] queryParams = {
    
    user.getUsername(), user.getPassword(), user.getGender(), user.getHobby(), user.getAddress(), user.getDegree()};
            db.executeUpdate(querySqluser, queryParams);
            db.commitAll();
            return true;

        } catch (Exception e) {
    
    
            e.printStackTrace();
        } finally {
    
    
            // 关闭数据库连接,释放资源
            if (conn != null) {
    
    
                try {
    
    
                    conn.close();
                } catch (SQLException e) {
    
    
                    e.printStackTrace();
                }
            }
        }
        return false;
    }
}

3.6 Exception handling

There are many exception handling structures in the project. For example, when the user name entered by the user during registration already exists, a warning message "User name already exists" will be prompted; when the user enters the same id when entering data on the client, it will be prompted "same id" warning message, and prompt the user to re-enter the information, etc.

3.7 Interface Design

The LoginFrame class implements the login interface

package com.qst.dms.ui;

import com.qst.dms.entity.User;
import com.qst.dms.service.UserService;

import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class LoginFrame extends JFrame {
    
    
    // 主面板
    private JPanel p;
    // 标签
    private JLabel lblName, lblPwd;
    // 用户名,文本框
    private JTextField txtName;
    // 密码,密码框
    private JPasswordField txtPwd;
    // 确认、取消和注册,按钮
    private JButton btnOk, btnCancle, btnRegist;
    // 登录用户
    private static User user;

    // 用户业务类
    private UserService userService;

    // 构造方法
    public LoginFrame() {
    
    
        super("登录");
        // 实例化用户业务类对象
        userService = new UserService();

        // 设置窗体的icon
        ImageIcon icon = new ImageIcon("images\\dms.png");
        this.setIconImage(icon.getImage());

        // 实例化组件
        p = new JPanel();
        // 使用null布局
        p.setLayout(null);
        lblName = new JLabel("用户名:");
        lblPwd = new JLabel("密    码:");
        txtName = new JTextField(20);
        txtPwd = new JPasswordField(20);
        txtPwd.setEchoChar('*');

        btnOk = new JButton("登录");
        btnOk.addActionListener((ActionListener) new LoginListener());

        btnCancle = new JButton("重置");
        btnCancle.addActionListener(new LoginFrame.ResetListener());

        btnRegist = new JButton("注册");
        btnRegist.addActionListener(new RegistListener());

        lblName.setBounds(30, 30, 60, 25);
        lblPwd.setBounds(30, 60, 60, 25);
        txtName.setBounds(95, 30, 120, 25);
        txtPwd.setBounds(95, 60, 120, 25);
        btnOk.setBounds(30, 90, 60, 25);
        btnCancle.setBounds(95, 90, 60, 25);
        btnRegist.setBounds(160, 90, 60, 25);

        p.add(lblName);
        p.add(txtName);
        p.add(lblPwd);
        p.add(txtPwd);
        p.add(btnOk);
        p.add(btnCancle);
        p.add(btnRegist);

        // 主面板放入窗体中
        this.add(p);
        // 设置窗体大小和位置
        this.setSize(280, 170);
        // 设置窗口在屏幕中央
        this.setLocationRelativeTo(null);
        //this.setAlwaysOnTop(true);
        // 设置窗体不能改变大小
        this.setResizable(false);
        // 设置窗体的默认关闭按钮
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        // 设置窗体初始可见
        this.setVisible(true);
    }

    // 监听类,负责处理登录按钮
    public class LoginListener implements ActionListener {
    
    
        // 重写actionPerFormed()方法,事件处理逻辑
        public void actionPerformed(ActionEvent e) {
    
    
            // 根据用户名查询用户
            try{
    
    
                user = userService.findUserByName((txtName.getText().trim()));
                if (user != null) {
    
    
                    //判断输入的密码是否正确
                    if (user.getPassword().equals(new String(txtPwd.getPassword()))) {
    
    
                        //输出提示信息
                        JOptionPane.showMessageDialog(null, "登录成功!", "成功提示", JOptionPane.PLAIN_MESSAGE);
                        //登录成功
                        LoginFrame.this.setVisible(false);
                        //显示主窗口
                        new ClientFrame();
                    } else {
    
    
                        //输出提示信息
                        JOptionPane.showMessageDialog(null, "密码错误!请重新输入!", "错误提示", JOptionPane.ERROR_MESSAGE);
                        //清空密码框
                        txtPwd.setText("");
                    }
                } else {
    
    
                    //输出提示信息
                    JOptionPane.showMessageDialog(null, "该用户不存在,请先注册!", "错误提示", JOptionPane.ERROR_MESSAGE);
                }
            }catch (Exception t){
    
    
                JOptionPane.showMessageDialog(null, "该用户不存在,请先注册!", "错误提示", JOptionPane.ERROR_MESSAGE);
            }
        }
    }

    // 监听类,负责处理重置按钮
    public class ResetListener implements ActionListener {
    
    
        // 重写actionPerFormed()方法,事件处理方法
        public void actionPerformed(ActionEvent e) {
    
    
            // 清空文本框
            try {
    
    
                txtName.setText("");
                txtPwd.setText("");
            }catch(Exception t){
    
    
                JOptionPane.showMessageDialog(null, "重置失败!", "错误提示", JOptionPane.ERROR_MESSAGE);
            }
        }
    }

    // 监听类,负责处理注册按钮
    public class RegistListener implements ActionListener {
    
    
        // 重写actionPerFormed()方法,事件处理方法
        public void actionPerformed(ActionEvent e) {
    
    
            // 创建注册窗口
            new RegistFrame();
        }
    }
}

The RegistFrame class implements the registration interface

package com.qst.dms.ui;

import com.qst.dms.entity.User;
import com.qst.dms.service.UserService;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class RegistFrame extends JFrame{
    
    
    // 主面板
    private JPanel p;

    // 标签
    private JLabel lblName, lblPwd, lblRePwd, lblSex, lblHobby, lblAdress,
            lblDegree;
    // 用户名,文本框
    private static JTextField txtName;
    // 密码和确认密码,密码框
    private static JPasswordField txtPwd;
    private static JPasswordField txtRePwd;
    // 性别,单选按钮
    private static JRadioButton rbMale;
    private static JRadioButton rbFemale;
    // 爱好,多选框
    private static JCheckBox ckbRead;
    private static JCheckBox ckbNet;
    private static JCheckBox ckbSwim;
    private static JCheckBox ckbTour;
    // 地址,文本域
    private static JTextArea txtAdress;
    // 学历,组合框
    private static JComboBox<String> cmbDegree;
    // 确认和取消,按钮
    private JButton btnOk, btnCancle;
    // 注册的用户
    private static User user;

    // 用户业务类
    private UserService userService;
    private Image iconImage;

    // 构造方法
    public RegistFrame() {
    
    
        super("注册");

        // 实例化用户业务类对象
        userService = new UserService();

        // 设置窗体的icon
        ImageIcon icon = new ImageIcon("images\\dms.png");
        this.setIconImage(icon.getImage());

        // 设置面板布局,网格布局
        p = new JPanel(new GridLayout(8, 1));
        // 实例化组件
        lblName = new JLabel("用  户  名:");
        lblPwd = new JLabel("密        码:");
        lblRePwd = new JLabel("确认密码:");
        lblSex = new JLabel("性       别:");
        lblHobby = new JLabel("爱        好:");
        lblAdress = new JLabel("地        址:");
        lblDegree = new JLabel("学        历:");
        txtName = new JTextField(16);
        txtPwd = new JPasswordField(16);
        txtRePwd = new JPasswordField(16);
        rbMale = new JRadioButton("男");
        rbFemale = new JRadioButton("女");

        // 性别的单选逻辑
        ButtonGroup bg = new ButtonGroup();
        bg.add(rbMale);
        bg.add(rbFemale);

        ckbRead = new JCheckBox("阅读");
        ckbNet = new JCheckBox("上网");
        ckbSwim = new JCheckBox("游泳");
        ckbTour = new JCheckBox("旅游");
        txtAdress = new JTextArea(3, 20);

        // 组合框显示的学历数组
        String str[] = {
    
     "小学", "初中", "高中", "本科", "硕士", "博士" };
        cmbDegree = new JComboBox<String>(str);
        // 设置组合框可编辑
        cmbDegree.setEditable(true);
        btnOk = new JButton("确定");
        // 注册监听器,监听确定按钮
        btnOk.addActionListener((ActionListener) new RegisterListener());
        btnCancle = new JButton("重置");
        // 注册监听器,监听重置按钮
        btnCancle.addActionListener(new ResetListener());
        // 将组件分组放入面板,然后将小面板放入主面板
        JPanel p1 = new JPanel(new FlowLayout(FlowLayout.LEFT));
        p1.add(lblName);
        p1.add(txtName);
        p.add(p1);
        JPanel p2 = new JPanel(new FlowLayout(FlowLayout.LEFT));
        p2.add(lblPwd);
        p2.add(txtPwd);
        p.add(p2);
        JPanel p3 = new JPanel(new FlowLayout(FlowLayout.LEFT));
        p3.add(lblRePwd);
        p3.add(txtRePwd);
        p.add(p3);
        JPanel p4 = new JPanel(new FlowLayout(FlowLayout.LEFT));
        p4.add(lblSex);
        p4.add(rbMale);
        p4.add(rbFemale);
        p.add(p4);
        JPanel p5 = new JPanel(new FlowLayout(FlowLayout.LEFT));
        p5.add(lblHobby);
        p5.add(ckbRead);
        p5.add(ckbNet);
        p5.add(ckbSwim);
        p5.add(ckbTour);
        p.add(p5);
        JPanel p6 = new JPanel(new FlowLayout(FlowLayout.LEFT));
        p6.add(lblAdress);
        p6.add(txtAdress);
        p.add(p6);
        JPanel p7 = new JPanel(new FlowLayout(FlowLayout.LEFT));
        p7.add(lblDegree);
        p7.add(cmbDegree);
        p.add(p7);
        JPanel p8 = new JPanel(new FlowLayout(FlowLayout.CENTER));
        p8.add(btnOk);
        p8.add(btnCancle);
        p.add(p8);
        // 主面板放入窗体中
        this.add(p);
        // 设置窗体大小和位置居中
        this.setSize(310, 400);
        this.setLocationRelativeTo(null);
        // 设置窗体不可改变大小
        this.setResizable(false);

        // 设置窗体初始可见
        this.setVisible(true);
    }


    public void setIconImage(Image iconImage) {
    
    
        this.iconImage = iconImage;
    }

    // 监听类,负责处理确认按钮的业务逻辑
    private class RegisterListener implements ActionListener {
    
    
        // 重写actionPerFormed()方法,事件处理方法
        public void actionPerformed(ActionEvent e) {
    
    
            // 获取用户输入的数据
            String userName = txtName.getText().trim();
            String password = new String(txtPwd.getPassword());
            String rePassword = new String(txtRePwd.getPassword());

            int sex = Integer.parseInt(rbFemale.isSelected()?"0":"1");
            String hobby = (ckbRead.isSelected()?"阅读":"")
                    + (ckbNet.isSelected()?"上网":"")
                    + (ckbNet.isSelected()?"游泳":"")
                    + (ckbNet.isSelected()?"旅游":"");

            String address = txtAdress.getText().trim();
            String degree = cmbDegree.getSelectedItem().toString().trim();

            user = userService.findUserByName((txtName.getText().trim()));
            if(user != null){
    
    
                JOptionPane.showMessageDialog(null, "用户名已存在!", "错误提示", JOptionPane.ERROR_MESSAGE);
                return;
            }


            //判断两次输入密码是否一致

            try {
    
    
                if (password.equals(rePassword)) {
    
    
                    //将数据封装到对象中
                    user = new User(userName, password, sex, hobby, address, degree);

                    //保存数据
                    if (userService.saveUser(user)) {
    
    
                        //输出提示信息
                        JOptionPane.showMessageDialog(null, "注册成功!", "成功提示", JOptionPane.PLAIN_MESSAGE);
                    } else {
    
    
                        //输出提示信息
                        JOptionPane.showMessageDialog(null, "注册失败!", "错误提示", JOptionPane.ERROR_MESSAGE);
                    }

                } else {
    
    
                    //输出提示信息
                    JOptionPane.showMessageDialog(null, "两次输入的密码不一致!", "错误提示", JOptionPane.ERROR_MESSAGE);
                }
            }catch (Exception t){
    
    
                JOptionPane.showMessageDialog(null, "注册失败!", "错误提示", JOptionPane.ERROR_MESSAGE);

            }

        }
    }
    // 监听类,负责处理重置按钮
    public static class ResetListener implements ActionListener {
    
    
        // 重写actionPerFormed()方法,重置组件内容事件处理方法
        public void actionPerformed(ActionEvent e) {
    
    
            // 清空姓名、密码、确认密码内容
            try {
    
    
                txtName.setText("");
                txtPwd.setText("");
                txtRePwd.setText("");
                // 重置单选按钮为未选择
                rbMale.setSelected(false);
                rbFemale.setSelected(false);
                // 重置所有的复选按钮为未选择
                ckbRead.setSelected(false);
                ckbNet.setSelected(false);
                ckbSwim.setSelected(false);
                ckbTour.setSelected(false);
                // 清空地址栏
                txtAdress.setText("");
                // 重置组合框为未选择状态
                cmbDegree.setSelectedIndex(0);
            }catch (Exception t){
    
    
                JOptionPane.showMessageDialog(null, "重置失败!", "错误提示", JOptionPane.ERROR_MESSAGE);
            }
        }
    }
}

The ClientFrame class implements the operation interface of the client

package com.qst.dms.ui;

import com.qst.dms.entity.*;
import com.qst.dms.net.Request;
import com.qst.dms.net.Response;
import com.qst.dms.service.DmsNetService;
import com.qst.dms.service.LogRecService;
import com.qst.dms.service.TransportService;
import com.qst.dms.util.Config;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.Socket;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Properties;

public class ClientFrame extends JFrame {
    
    
    //菜单
    private JMenuBar menuBar;//包含多个菜单
    private JMenu oper, help, matchMenu;
    private JMenuItem mGather, mSave, mSend, mShow, mCheck, mHelp, mLog, mTransport, mExit;

    //工具栏mShow,showBtn
    private JToolBar toolBar;
    private JButton gatherBtn, logBtn, transportBtn, saveBtn, sendBtn, showBtn;

    //数据采集和显示卡片布局组件
    private JPanel p;//数据采集和显示的界面面板,里面采用CardLayout布局,分别显示采集界面和显示界面
    private JTabbedPane jGather, jShow;
    private CardLayout card;

    //日志数据采集组件
    private JTextField txtLogId, txtName, txtLocation, txtIP;
    private JRadioButton rbLogin, rbLogout;
    private JButton btnLogConfirm, btnLogReset;

    //物流数据采集组件
    private JTextField txtTransId, txtAdress, txtHandler, txtReceiver;
    private JComboBox<String> cmbTanStatus;
    private JButton btnTranConfirm, btnTranReset;

    private JTable logTable;//日志原始数据显示Table
    private JTable transTable;//物流原始数据显示Table

    //日志数据存储集合
    private ArrayList<LogRec> logList = new ArrayList<>();
    private ArrayList<MatchedLogRec> matchLogList = new ArrayList<>();
    //物流数据存储集合
    private ArrayList<Transport> transList = new ArrayList<>();
    private ArrayList<MatchedTransport> matchTransList = new ArrayList<>();

    //日志与物流业务对象
    private LogRecService logRecService = new LogRecService();
    private TransportService transService = new TransportService();

    private String serverIp;//服务端IP
    private int serverPort;//服务端端口

    //客户端配置文件
    private final static String CONFIG_FILE = "config/client.properties";

    private void initConfig() {
    
    
        try {
    
    
            //通过Properties类获取配置文件中的属性赋值给serverPort和serverIp
            Properties p = new Properties();
            //加载配置类
            p.load(new FileInputStream(CONFIG_FILE));

            serverIp = p.getProperty("host");
            serverPort = Integer.parseInt(p.getProperty("port"));

        } catch (Exception e) {
    
    
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }

    // 构造方法
    public ClientFrame() {
    
    
        // TODO Auto-generated constructor stub
        super("DMS客户端");//给窗口一个名称,显示左上角
        ImageIcon icon = new ImageIcon("images\\dms.png");
        this.setIconImage(icon.getImage());

        initConfig();//读取配置文件
        initMenu();//初始化菜单
        initToolBar();//初始化工具栏


//--------数据采集界面的设计----------
        //后面补充代码
        card = new CardLayout();
        p = new JPanel(card);
        this.getContentPane().add(p, BorderLayout.CENTER);
        jGather = new JTabbedPane(JTabbedPane.TOP);
        p.add(jGather, "gather");
        jShow = new JTabbedPane(JTabbedPane.TOP);
        jShow.addTab("日志", new JScrollPane());
        jShow.addTab("物流", new JScrollPane());
        p.add(jShow, "show");

        initLogGatherGUI();
        initGatherTransport();

        initGatherLogRecShowUI();
        initGatherTransportShowUI();


//--------数据采集界面的设计结束----------


        //数据采集的监听

        mGather.addActionListener(new miGatherListener());//数据采集菜单项增加监听
        gatherBtn.addActionListener(new miGatherListener());//工具栏上采集按钮监听


        //数据显示监听
        mShow.addActionListener(new miShowListener());
        showBtn.addActionListener(new miShowListener());


        //帮助菜单的监听设置

        // 注册监听
        mHelp.addActionListener(new ActionListener() {
    
    
            public void actionPerformed(ActionEvent e) {
    
    
                // 显示消息对话框
                JOptionPane.showMessageDialog(null, "本系统实现数据的采集、过滤分析匹配、保存、发送及显示功能", "帮助", JOptionPane.QUESTION_MESSAGE);
            }
        });
        // 注册监听
        mCheck.addActionListener(new ActionListener() {
    
    
            public void actionPerformed(ActionEvent e) {
    
    
                // 显示消息对话框
                JOptionPane.showMessageDialog(null, "版本:1.0版", "关于", JOptionPane.WARNING_MESSAGE);
            }
        });

        //initGatherLogRecShowUI();//日志显示界面初始化
        //initGatherTransportShowUI();//物流采集界面初始化

        // 设置窗体大小
        this.setSize(600, 400);
        // 设置窗口在屏幕中央
        this.setLocationRelativeTo(null);//居中
        // 设置默认的关闭按钮操作为退出程序
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        // 设置窗体初始可见
        this.setVisible(true);
    }

    // 初始化菜单的方法
    private void initMenu() {
    
    

        //-------系统菜单的初始化开始----------------
        menuBar = new JMenuBar();
        this.setJMenuBar(menuBar);//创建菜单条,并放入到JFrame

        oper = new JMenu("操作");
        help = new JMenu("帮助");
        menuBar.add(oper);
        menuBar.add(help);

        mGather = new JMenuItem("采集数据");

        mGather.addActionListener(new miGatherListener());

        //子菜单
        matchMenu = new JMenu("匹配数据");
        mLog = new JMenuItem("日志数据匹配");
        mLog.addActionListener(new MatchedLogRecListener());
        mTransport = new JMenuItem("物流数据匹配");
        mTransport.addActionListener(new MatchedTransportListener());
        matchMenu.add(mLog);
        matchMenu.add(mTransport);

        mSave = new JMenuItem("保存数据");
        mSave.addActionListener(new SaveActionListener());

        mSend = new JMenuItem("发送数据");
        mSend.addActionListener(new SendActionListener());
        mShow = new JMenuItem("显示数据");

        mExit = new JMenuItem("退出应用");

        mExit.addActionListener(new ActionListener() {
    
    
            @Override
            public void actionPerformed(ActionEvent e) {
    
    
                // TODO Auto-generated method stub
                System.exit(0);
            }

        });

        oper.add(mGather);
        oper.add(matchMenu);
        oper.add(mSave);
        oper.add(mSend);
        oper.add(mShow);
        oper.add(mExit);

        mCheck = new JMenuItem("关于系统");
        mHelp = new JMenuItem("查看帮助");
        help.add(mCheck);
        help.add(mHelp);

        //-------系统菜单的初始化结束----------------
    }

    // 初始化工具栏的方法
    private void initToolBar() {
    
    

        //-------系统工具栏的初始化------------
        toolBar = new JToolBar();

        ImageIcon icon1 = new ImageIcon("images\\gatherData.png");

        gatherBtn = new JButton("采集数据", icon1);

        gatherBtn.addActionListener(new miGatherListener());

        ImageIcon icon2 = new ImageIcon("images\\matchData.png");
        logBtn = new JButton("日志数据匹配", icon2);
        logBtn.addActionListener(new MatchedLogRecListener());//-----------------
        ImageIcon icon3 = new ImageIcon("images\\matchData.png");
        transportBtn = new JButton("物流数据匹配", icon3);
        transportBtn.addActionListener(new MatchedTransportListener());//------------
        ImageIcon icon4 = new ImageIcon("images\\saveData.png");
        saveBtn = new JButton("保存数据", icon4);
        saveBtn.addActionListener(new SaveActionListener());
        ImageIcon icon5 = new ImageIcon("images\\sendData.png");
        sendBtn = new JButton("发送数据", icon5);
        sendBtn.addActionListener(new SendActionListener());
        ImageIcon icon6 = new ImageIcon("images\\showData.png");
        showBtn = new JButton("显示数据", icon6);

        toolBar.add(gatherBtn);
        toolBar.add(logBtn);
        toolBar.add(transportBtn);
        toolBar.add(saveBtn);
        toolBar.add(sendBtn);
        toolBar.add(showBtn);

        //JFrame默认有个JPanel
        this.getContentPane().add(toolBar, BorderLayout.NORTH);

        //-------系统工具栏的初始化结束------------
    }

    // 初始化日志数据采集界面的方法
    private void initLogGatherGUI() {
    
    
        JPanel pLog = new JPanel();
        jGather.addTab("日志", pLog);
        pLog.setLayout(new BoxLayout(pLog, BoxLayout.Y_AXIS));

        JPanel pLogId = new JPanel();
        pLog.add(pLogId);
        pLogId.setLayout(new FlowLayout(FlowLayout.CENTER, 5, 5));

        JLabel lblLogId = new JLabel("日志ID:");
        pLogId.add(lblLogId);

        txtLogId = new JTextField();
        txtLogId.setPreferredSize(new Dimension(100, 20));
        pLogId.add(txtLogId);

        JPanel pName = new JPanel();
        pLog.add(pName);
        pName.setLayout(new FlowLayout(FlowLayout.CENTER, 5, 5));

        JLabel lblName = new JLabel("用户名:");
        pName.add(lblName);

        txtName = new JTextField();
        txtName.setPreferredSize(new Dimension(100, 20));
        pName.add(txtName);

        JPanel pLocation = new JPanel();
        pLog.add(pLocation);

        JLabel lblLocation = new JLabel("登录地点:");
        pLocation.add(lblLocation);

        txtLocation = new JTextField();
        txtLocation.setPreferredSize(new Dimension(100, 20));
        pLocation.add(txtLocation);

        JPanel pIP = new JPanel();
        pLog.add(pIP);

        JLabel lblIP = new JLabel("登录IP:");
        pIP.add(lblIP);

        txtIP = new JTextField();
        txtIP.setPreferredSize(new Dimension(100, 20));
        pIP.add(txtIP);

        JPanel pLogStatus = new JPanel();
        pLog.add(pLogStatus);

        JLabel lblLogStatus = new JLabel("登录状态:");
        pLogStatus.add(lblLogStatus);

        rbLogin = new JRadioButton("登录");
        pLogStatus.add(rbLogin);
        rbLogin.setSelected(true);

        rbLogout = new JRadioButton("登出");
        pLogStatus.add(rbLogout);

        ButtonGroup bg = new ButtonGroup();
        bg.add(rbLogin);
        bg.add(rbLogout);

        JPanel pLogButton = new JPanel();
        pLog.add(pLogButton);

        btnLogConfirm = new JButton("确认");
        // 添加确认按钮监听
        btnLogConfirm.addActionListener(new GatherLogListener());
        pLogButton.add(btnLogConfirm);

        btnLogReset = new JButton("重置");
        // 添加重置按钮监听
        btnLogReset.addActionListener(new ResetListener());
        pLogButton.add(btnLogReset);
    }

    // 初始化物流数据采集界面的方法
    private void initGatherTransport() {
    
    
        //-----物流数据采集详情界面------
        JPanel pTran = new JPanel();
        jGather.addTab("物流", new JScrollPane(pTran));
        pTran.setLayout(new BoxLayout(pTran, BoxLayout.Y_AXIS));

        JPanel pTransId = new JPanel();
        pTran.add(pTransId);

        JLabel lblTransId = new JLabel("物流ID: ");
        pTransId.add(lblTransId);

        txtTransId = new JTextField();
        txtTransId.setPreferredSize(new Dimension(100, 20));
        pTransId.add(txtTransId);

        JPanel pAdress = new JPanel();
        pTran.add(pAdress);

        JLabel lblAdress = new JLabel("目的地:");
        pAdress.add(lblAdress);

        txtAdress = new JTextField();
        txtAdress.setPreferredSize(new Dimension(100, 20));
        pAdress.add(txtAdress);

        JPanel pHandler = new JPanel();
        pTran.add(pHandler);

        JLabel lblHandler = new JLabel("经手人");
        pHandler.add(lblHandler);

        txtHandler = new JTextField();
        txtHandler.setPreferredSize(new Dimension(100, 20));
        pHandler.add(txtHandler);

        JPanel pReceiver = new JPanel();
        pTran.add(pReceiver);

        JLabel lblReceiver = new JLabel("收货人:");
        pReceiver.add(lblReceiver);

        txtReceiver =new JTextField();
        txtReceiver.setPreferredSize(new Dimension(100,20));
        pReceiver.add(txtReceiver);

        JPanel pTranStatus = new JPanel();
        pTran.add(pTranStatus);

        JLabel lblTranStatus =new JLabel("物流状态:");
        pTranStatus.add(lblTranStatus);

        String[] tranStatus = new String[] {
    
    "发货中","送货中", "已签收"};
        cmbTanStatus=new JComboBox<String>(tranStatus);
        pTranStatus.add(cmbTanStatus);
        JPanel pTranButton=new JPanel();
        pTran.add(pTranButton);

        btnTranConfirm=new JButton("确认");
        btnTranConfirm.addActionListener(new GatherTransListener());
        pTranButton.add(btnTranConfirm);

        btnTranReset=new JButton("重置");
        btnTranReset.addActionListener(new ResetListener());
        pTranButton.add(btnTranReset);
    }


    private void initGatherLogRecShowUI(){
    
    
        JPanel pLog = new JPanel();
        jGather.addTab("日志数据显示", pLog);
        pLog.setLayout(new BoxLayout(pLog, BoxLayout.Y_AXIS));
    }

    private void initGatherTransportShowUI(){
    
    
        JPanel pLog = new JPanel();
        jGather.addTab("物流数据显示", pLog);
        pLog.setLayout(new BoxLayout(pLog, BoxLayout.Y_AXIS));
    }

    private void flushGatherLogRecShowUI(){
    
    
        DataTableModelFromList<LogRec> logModel = new DataTableModelFromList<>(logList,1);
        JTable logTable = new JTable(logModel);
        jGather.addTab("日志数据显示",new JScrollPane(logTable));
    }

    private  void flushGatherTransportShowUI(){
    
    
        DataTableModelFromList<Transport> logModel = new DataTableModelFromList<>(transList,2);
        JTable transTable = new JTable(logModel);
        jGather.addTab("物流数据显示",new JScrollPane(transTable));
    }

    // 数据采集监听类
    private class miGatherListener implements ActionListener{
    
    
        @Override
        public void actionPerformed(ActionEvent e){
    
    
            card.show(p, "gather");
        }

    }


    // 匹配日志信息监听类
    private class MatchedLogRecListener implements ActionListener{
    
    

        @Override
        public void actionPerformed(ActionEvent e) {
    
    
            //参考前面字符控制界面,自己完成代码
            try {
    
    
                if(LogRecService.readLogRecs().size()>0){
    
    
                    JOptionPane.showMessageDialog(null, "日志数据匹配成功!", "提示", JOptionPane.INFORMATION_MESSAGE);
                } else{
    
    
                    JOptionPane.showMessageDialog(null, "日志数据匹配失败!", "警告" , JOptionPane. WARNING_MESSAGE);
                }
            }catch (Exception t){
    
    
                JOptionPane.showMessageDialog(null, "日志数据匹配失败!", "警告" , JOptionPane. WARNING_MESSAGE);
            }
        }
    }

    // 匹配物流信息监听类
    private class MatchedTransportListener implements ActionListener{
    
    

        @Override
        public void actionPerformed(ActionEvent e) {
    
    
            //参考前面字符控制界面,自己完成代码
            try {
    
    
                if (TransportService.readTransports().size()>0) {
    
    
                    JOptionPane.showMessageDialog(null, "物流数据匹配成功!", "提示", JOptionPane.INFORMATION_MESSAGE);
                }else{
    
    
                    JOptionPane.showMessageDialog(null, "物流数据匹配失败!", "警告", JOptionPane.WARNING_MESSAGE);
                }
            } catch (Exception t) {
    
    
                JOptionPane.showMessageDialog(null, "物流数据匹配失败!", "警告", JOptionPane.WARNING_MESSAGE);
            }
        }
    }

    private class SaveActionListener implements ActionListener{
    
    

        @Override
        public void actionPerformed(ActionEvent e) {
    
    
            try {
    
    
                LogRecService.saveLogRec(logList);
                TransportService.saveTransport(transList);

                logList.clear();
                transList.clear();
                JOptionPane.showMessageDialog(null, "保存成功!", "提示" , JOptionPane. INFORMATION_MESSAGE);
            }catch (Exception t){
    
    
                JOptionPane.showMessageDialog(null, "保存失败!", "警告" , JOptionPane. WARNING_MESSAGE);
            }
        }
    }

    private class SendActionListener implements ActionListener{
    
    

        @Override
        public void actionPerformed(ActionEvent e) {
    
    

            List<MatchedLogRec> matchedlogs = LogRecService.readMatchLogRec();
            List<? extends MatchedDataBase> matchedDataList1 = new ArrayList<>(matchedlogs);
            try {
    
    
                // 创建一个Socket并连接到服务器
                Socket socket = new Socket(serverIp, serverPort);
                Date time = new Date();
                SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                String formattedDate = dateFormat.format(time);
                // 发送请求
                Request request = new Request(formattedDate,"localhost",Request.DATA_TYPE_LOGREC, (List<MatchedDataBase>)matchedDataList1);

                //System.out.println(request);

                DmsNetService.sendRequest(socket, request);
                System.out.println("发送请求: " + request);

                // 接收响应
                Response response = DmsNetService.receiveResponse(socket);
                System.out.println("接收响应: " + response);

                // 关闭Socket连接
                socket.close();
            } catch (IOException | ClassNotFoundException t) {
    
    
                t.printStackTrace();
            }

            List<MatchedTransport> matchedtrans = TransportService.readMatchTransport();
            List<? extends MatchedDataBase> matchedDataList2 = new ArrayList<>(matchedtrans);
            try {
    
    
                // 创建一个Socket并连接到服务器
                Socket socket = new Socket(serverIp, serverPort);
                Date time = new Date();
                SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                String formattedDate = dateFormat.format(time);
                // 发送请求
                Request request = new Request(formattedDate,"localhost",Request.DATA_TYPE_LOGREC, (List<MatchedDataBase>)matchedDataList2);

                //System.out.println(request);

                DmsNetService.sendRequest(socket, request);
                System.out.println("发送请求: " + request);

                // 接收响应
                Response response = DmsNetService.receiveResponse(socket);
                System.out.println("接收响应: " + response);

                // 关闭Socket连接
                socket.close();
            } catch (IOException | ClassNotFoundException t) {
    
    
                t.printStackTrace();
            }

        }
    }


    // 日志数据采集监听类
    private class GatherLogListener implements ActionListener {
    
    
        // 数据采集的事件处理方法
        public void actionPerformed(ActionEvent e) {
    
    
            // 获取日志ID
            int id = Integer. parseInt(txtLogId. getText(). trim());
            // 创建当前时间
            Date currentDate = new Date();
            SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            String time = dateFormat.format(currentDate);

            // 获取地址栏地址
            String adress = txtLocation. getText(). trim();
            // 设置数据类型为:采集
            int type = DataBase. GATHER;
            // 获取用户姓名
            String user = txtName. getText(). trim();
            // 获取ip地址
            String ip = txtIP. getText(). trim();
            // 设置日志类型
            int logType = rbLogin. isSelected() ? LogRec. LOG_IN: LogRec. LOG_OUT;
            // 将数据封装到日志对象
            LogRec log = new LogRec(id, time, adress, type, user, ip, logType);
            List<LogRec> same = LogRecService.readLogRecs();
            // 将日志对象添加到日志列表
            for (LogRec t:same){
    
    
                if(t.getId()==log.getId()){
    
    
                    JOptionPane.showMessageDialog(null, "ID重复!", "警告" , JOptionPane. WARNING_MESSAGE);
                    return;
                }
            }
            for (LogRec t:logList){
    
    
                if(t.getId()==log.getId()){
    
    
                    JOptionPane.showMessageDialog(null, "ID重复!", "警告" , JOptionPane. WARNING_MESSAGE);
                    return;
                }
            }
            logList.add(log);
            // 显示对话框
            JOptionPane.showMessageDialog(null, "日志采集成功!", "提示" , JOptionPane. INFORMATION_MESSAGE);

            jGather.removeAll();

            initLogGatherGUI();
            initGatherTransport();

            flushGatherLogRecShowUI();
            flushGatherTransportShowUI();
            //logTable.updateUI();//更新了JTable的数据来源List,更新JTable界面

        }
    }


    // 物流数据采集监听类
    private class GatherTransListener implements ActionListener {
    
    
        // 数据采集的事件处理方法
        public void actionPerformed(ActionEvent e) {
    
    
            // 获取物流ID
            int id = Integer. parseInt(txtTransId. getText(). trim());
            // 创建当前时间
            Date currentDate = new Date();
            SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            String time = dateFormat.format(currentDate);
            // 获取地址栏地址
            String adress = txtAdress. getText(). trim();
            // 设置数据类型为: 采集
            int type = DataBase. GATHER;
            // 获取经手人信息
            String handler = txtHandler. getText(). trim();
            // 获取发送人信息
            String reciver = txtReceiver. getText(). trim();
            // 设置物流类型
            int transportType = cmbTanStatus. getSelectedIndex() +1;
            // 将数据包装成物流对象
            Transport trans = new Transport(id, time, adress, type, handler, reciver, transportType);
            List<Transport> same = TransportService.readTransports();
            // 将日志对象添加到日志列表
            for (Transport t : same){
    
    
                if(t.getId() == trans.getId()){
    
    
                    JOptionPane.showMessageDialog(null, "ID重复!", "警告" , JOptionPane. WARNING_MESSAGE);
                    return;
                }
            }
            for (Transport t : transList){
    
    
                if(t.getId() == trans.getId()){
    
    
                    JOptionPane.showMessageDialog(null, "ID重复!", "警告" , JOptionPane. WARNING_MESSAGE);
                    return;
                }
            }

            // 将物流对象放入物流列表
            transList. add(trans);

            jGather.removeAll();
            initLogGatherGUI();
            initGatherTransport();
            flushGatherLogRecShowUI();
            flushGatherTransportShowUI();

            //logTable.updateUI();

            // 显示对话框
            JOptionPane. showMessageDialog(null, "物流采集成功!", "提示", JOptionPane.INFORMATION_MESSAGE);
        }
    }

    // 重置按钮监听类
    private class ResetListener implements ActionListener {
    
    
        // 重置按钮的事件处理方法
        public void actionPerformed(ActionEvent e) {
    
    
            txtName.setText("");
            txtLocation.setText("");
            txtIP.setText("");
            txtAdress.setText("");
            txtHandler.setText("");
            txtReceiver.setText("");
        }
    }

    private  class miShowListener implements  ActionListener{
    
    
        @Override
        public void actionPerformed(ActionEvent e){
    
    
            card.show(p, "show");

            jShow.removeAll();

            ClientFrame.this.flushMatchedLogTable();
            ClientFrame.this.flushMatchedTransTable();
        }
    }

    private void flushMatchedLogTable(){
    
    
        DataTableModelFromList<LogRec> logModel = new DataTableModelFromList<>(logRecService.readLogRecs(),1);
        JTable logTable = new JTable(logModel);
        jShow.addTab("日志",new JScrollPane(logTable));
    }

    private  void flushMatchedTransTable(){
    
    
        DataTableModelFromList<Transport> logModel = new DataTableModelFromList<>(transService.readTransports(),2);
        JTable transTable = new JTable(logModel);
        jShow.addTab("物流",new JScrollPane(transTable));
    }


    public static void main(String[] args) {
    
    
        // TODO Auto-generated method stub
        new LoginFrame();
    }



}

The ServerFrame class implements the operation interface of the server

package com.qst.dms.ui;

import com.qst.dms.entity.*;
import com.qst.dms.net.Request;
import com.qst.dms.net.Response;
import com.qst.dms.service.DmsNetService;
import com.qst.dms.service.LogRecService;
import com.qst.dms.service.TransportService;
import com.qst.dms.util.AppendObjectOutputStream;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Properties;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;

public class ServerFrame extends JFrame{
    
    
    // 菜单
    private JMenuBar menuBar;// 包含多个菜单
    private JMenu oper, help;
    private JMenuItem mCheck, mHelp, mExit, mFlush;
    // 显示卡片布局组件
    private JPanel p;// 数据显示的界面面板,里面采用CardLayout布局,分别显示采集界面和显示界面
    private JTabbedPane jShow;
    private CardLayout card;
    private JTable logrecTable;
    private JTable transportTable;
    // 数据服务对象
    private LogRecService logRecService = new LogRecService();
    private TransportService transService = new TransportService();
    private ServerSocket serverSocket;//服务Socket
    private Executor threadPool;//线程池
    private int threadPoolSize =100;//线程池的大小
    private int serverPort = 8000;//服务端口号
    private File tmpFile;//临时文件
    private long saveInterval =5000;//保存数据的间隔时间
    private Thread mdStore;//保存数据的线程对象
    private int queueSize = 100;//队列大小
    private BlockingQueue<MatchedDataBase> queue;//接收数据的队列
    private final static String CONFIG_FILE = "config/server.properties";

    //服务端配置文件
    private void initConfig() {
    
    
        try {
    
    
            //通过Properties类获取配置文件中的属性赋值给serverPort和serverIp
            Properties p = new Properties();
            //加载配置类
            p.load(new FileInputStream(CONFIG_FILE));
            serverPort = Integer.parseInt(p.getProperty("port"));

        } catch (Exception e) {
    
    
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }

    public ServerFrame(){
    
    
        super("DMS服务器");// 给窗口一个名称,显示左上角 initConfig();//初始化配置参数
        ImageIcon icon= new ImageIcon("images\\dns.png");
        this.setIconImage(icon.getImage());
        initConfig();
        initMenu();
        // 数据显示界面的设计
        card= new CardLayout();
        p = new JPanel(card);// 显示卡片(JPanel或者 JPanel子典)
        this. getContentPane().add(p, BorderLayout.CENTER);// CardLayout布局的JPanel加到JFrame中 数据表格阻件
        // 数据显示界面的设计(卡片2)一
        jShow = new JTabbedPane(JTabbedPane.TOP);
        transportTable = new JTable();
        logrecTable = new JTable();
        p.add(jShow, "show");
        this.flushMatchedLogTable();
        this.flushMatchedTransTable();

        // 注册监听
        mHelp. addActionListener(new ActionListener() {
    
    
            public void actionPerformed(ActionEvent e) {
    
    
                JOptionPane. showMessageDialog(null,"本系统实现数据的采集、过滤分析匹配、保存、发送总显示功能", "帮助" ,JOptionPane.QUESTION_MESSAGE);
            }
        });
        // 注册监听
        mCheck. addActionListener(new ActionListener() {
    
    
            public void actionPerformed(ActionEvent e) {
    
    
                JOptionPane.showMessageDialog(null,"版本:1.0版", "关于", JOptionPane. WARNING_MESSAGE);
            }
        });
        // 设置窗体大小
        this.setSize(600, 400);
        // 设置窗口在屏幕中央
        this.setLocationRelativeTo(null);// 居中
        // 设置默认的关闭按钮操作为退出程序
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        // 设置窗体初始可见
        this.setVisible(true);
        start();
    }
    private void initMenu(){
    
    
        menuBar = new JMenuBar();
        this.setJMenuBar(menuBar);
        oper = new JMenu("操作");
        help = new JMenu("帮助");
        menuBar.add(oper);
        menuBar.add(help);
        mFlush = new JMenuItem("刷新");
        mExit = new JMenuItem("退出应用");
        mExit.addActionListener(new ActionListener() {
    
    
            @Override
            public void actionPerformed(ActionEvent e) {
    
    
                // TODO Auto-generated method stub
                System. exit(0);
            }
        });
        mFlush.addActionListener(new miShowListener());
        oper.add(mFlush);
        oper.add(mExit);
        mCheck = new JMenuItem("关于系统");
        mHelp = new JMenuItem("查看帮助");
        help.add(mCheck);
        help.add(mHelp);
    }
    private class miShowListener implements ActionListener {
    
    

        @Override
        public void actionPerformed(ActionEvent e) {
    
    
            // TODO Auto-generated method stub
            //切换显示卡片,参考ClientFrame
            card.show(p,"show");
            jShow.removeAll();
            ServerFrame.this.flushMatchedLogTable();
            ServerFrame.this.flushMatchedTransTable();
        }

    }

    private void flushMatchedLogTable(){
    
    
        MatchedTableModel logModel = new MatchedTableModel(logRecService.readLogResult(),1);
        JTable logTable = new JTable(logModel);
        jShow.addTab("匹配日志",new JScrollPane(logTable));
    }

    private  void flushMatchedTransTable(){
    
    
        MatchedTableModel logModel = new MatchedTableModel(transService.readTransResult(),2);
        JTable transTable = new JTable(logModel);
        jShow.addTab("匹配物流",new JScrollPane(transTable));
    }

    //接收数据从存储队列
    class MatchedDataBaseReceiver implements Runnable {
    
    
        Socket s;

        public MatchedDataBaseReceiver(Socket s) {
    
    
            this.s = s;
        }

        public void run() {
    
    
            try {
    
    
                //接收数据存储到数据队列
                Request request = DmsNetService.receiveRequest(s);
                System.out.println("接收请求" + request);
                List<MatchedDataBase> datas = request.getData();
                for(MatchedDataBase data :datas){
    
    
                    queue.put(data);
                }

                Date time = new Date();
                SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                String formattedDate = dateFormat.format(time);
                //发送响应对象
                Response response = new Response(formattedDate,Response.OK);

                DmsNetService.sendResponse(s,response);
                System.out.println("发送响应:" + response);

            } catch (Exception e) {
    
    
                e.printStackTrace();
            }
        }
    }

    class MatchedDataBaseStore extends Thread {
    
    
        @Override
        public void run() {
    
    
            while (true) {
    
    
                try {
    
    
                    // 每5秒钟将队列中的数据保存到临时文件
                    try {
    
    
                        Thread.sleep(saveInterval);
                    } catch (InterruptedException e) {
    
    
                        e.printStackTrace();
                    }
                    tmpFile = new File("tempData.dat");

                    AppendObjectOutputStream.setFile(tmpFile);
                    File file = AppendObjectOutputStream.getFile();
                    FileOutputStream fileOut = new FileOutputStream(file, true);
                    AppendObjectOutputStream objOut = new AppendObjectOutputStream(file);
                    while (!queue.isEmpty()) {
    
    
                        // 从队列中取出数据并写入临时文件
                        MatchedDataBase data = queue.poll();
                        objOut.writeObject(data);
                    }
                    objOut.close();
                    fileOut.close();
                    System.out.println("保存成功");
                } catch (IOException e) {
    
    
                    e.printStackTrace();
                }

                if (tmpFile.exists() && !tmpFile.isDirectory()) {
    
    
                    // 如果临时文件存在,则将数据转存到数据库
                    try {
    
    
                        storeToDB(tmpFile);
                    } catch (IOException e) {
    
    
                        e.printStackTrace();
                    } catch (ClassNotFoundException e) {
    
    
                        e.printStackTrace();
                    }
                    tmpFile.delete();
                }
            }
        }
    }

    public boolean storeToDB(File tmpFile) throws IOException, ClassNotFoundException {
    
    
        //从数据文件中读取数据并存储到数据库
        List<MatchedLogRec> matchlogs = new ArrayList<>();
        List<MatchedTransport> matchtrans = new ArrayList<>();

        try {
    
    
            AppendObjectOutputStream.setFile(tmpFile);
            File file = AppendObjectOutputStream.getFile();
            if (!file.exists()) {
    
    
                file.createNewFile();
            }

            FileInputStream fileIn = new FileInputStream(file);

            // 创建一个ObjectInputStream对象输入流,并连接文件输入流
            ObjectInputStream objIn = new ObjectInputStream(fileIn);

            // 使用异常处理和EOFException异常处理读取结束
            try {
    
    
                while (true) {
    
    
                    MatchedDataBase data = (MatchedDataBase) objIn.readObject();

                    // 根据具体对象类型将数据添加到对应的列表中
                    if (data instanceof MatchedLogRec) {
    
    
                        matchlogs.add((MatchedLogRec) data);
                    } else if (data instanceof MatchedTransport) {
    
    
                        matchtrans.add((MatchedTransport) data);
                    }
                }
            } catch (EOFException e) {
    
    
                // 读取结束,不做任何操作
            }

            objIn.close();
            fileIn.close();
            System.out.println("————————————————————————————————————————————————————————");
            System.out.println(matchlogs);
            LogRecService.saveLogResult(matchlogs);
            System.out.println("————————————————————————————————————————————————————————");
            System.out.println(matchtrans);
            TransportService.saveTranResult(matchtrans);


            System.out.println("信息读取完成\n");
            //存储成功,返回true
            return true;
        } catch (IOException | ClassNotFoundException e) {
    
    
            System.out.println("读取信息发生异常:" + e.getMessage() + "\n");
        }
        //否则返回False
        return false;
    }

    public void start() {
    
    
        try{
    
    
            //绑定服务器端口号
            serverSocket = new ServerSocket(serverPort);
            //创建线程池对象
            threadPool= Executors.newFixedThreadPool(threadPoolSize);
            queue = new LinkedBlockingQueue<MatchedDataBase>(queueSize);
            //创建并启动数据存储线程
            mdStore = new MatchedDataBaseStore();
            mdStore.start();
            //循环监听网络请求
            while(true){
    
    
                //服务器主循环,等待客户的监听
                System.out.println("等待客户的连接");
                Socket socket = serverSocket.accept();
                //有客户连接以后,提交到线程池执行
                System.out.println("提交客户处理线程!");
                threadPool.execute(new MatchedDataBaseReceiver(socket));
            }
        }catch(Exception e){
    
    
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }

    public static void main(String[] args) {
    
    
        new ServerFrame();
    }

}

4. System testing

4.1 Set up test data

user table

7

match log table

8

Match logistics table

9

client

10
11

Server

12
13

Guess you like

Origin blog.csdn.net/m0_68111267/article/details/131625235