【技能实训】DMS数据挖掘项目(完整程序)

文章目录

  • [1. 系统需求分析](#1. 系统需求分析)
    • [1.1 需求概述](#1.1 需求概述)
    • [1.2 需求说明](#1.2 需求说明)
  • [2. 系统总体设计](#2. 系统总体设计)
    • [2.1 编写目的](#2.1 编写目的)
    • [2.2 总体设计](#2.2 总体设计)
      • [2.2.1 功能划分](#2.2.1 功能划分)
      • [2.2.2 数据库及表](#2.2.2 数据库及表)
      • [2.2.3 主要业务流程](#2.2.3 主要业务流程)
  • [3. 详细设计与实现](#3. 详细设计与实现)
    • [3.1 表设计](#3.1 表设计)
    • [3.2 数据库访问工具类设计](#3.2 数据库访问工具类设计)
    • [3.3 配置文件](#3.3 配置文件)
    • [3.4 实体类及设计](#3.4 实体类及设计)
    • [3.5 业务类及设计](#3.5 业务类及设计)
    • [3.6 异常处理](#3.6 异常处理)
    • [3.7 界面设计](#3.7 界面设计)
  • [4. 系统测试](#4. 系统测试)
    • [4.1 设置测试数据](#4.1 设置测试数据)

1. 系统需求分析

1.1 需求概述

DMS数据挖掘项目是一个基于C/S(Client/Server,客户/服务器)架构的系统。

1.2 需求说明

由DMS客户端和DMS服务器端两部分组成:.

●DMS 客户端作为系统的一部分,其主要任务是对数据进行采集、分析和匹配,并将匹配成功的数据发送到DMS服务器端。

●DMS 服务器端用于接收DMS客户端发送来的数据,并将数据保存到数据库中,DMS服务器端对接收的数据提供监控功能。

2. 系统总体设计

2.1 编写目的

DMS数据挖掘项目可以对多种数据类型进行采集,例如:日志数据信息的采集、物流数据信息的采集等,多种数据信息都是基于继承关系。

2.2 总体设计

2.2.1 功能划分

2.2.2 数据库及表

2.2.3 主要业务流程

3. 详细设计与实现

3.1 表设计

用户表

匹配日志表

匹配物流表

DataTableModelFromList类实现了从文件中读取出日志或物流数据,然后将数据以表格的形式显示出来的功能。

java 复制代码
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];
    }

}

MatchedTableModel类实现了从数据库中读取出日志或物流数据,然后将数据以表格的形式显示出来的功能。

java 复制代码
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 数据库访问工具类设计

DBUtil类实现了连接数据库并进行事物处理的简单操作。

java 复制代码
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 配置文件

mysql.properties如下,保存了数据库的配置数据

java 复制代码
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保存了客户端的配置

java 复制代码
host=******
port=******

server.properties保存了服务端的配置

java 复制代码
port=******

3.4 实体类及设计

DataBase父类,定义了日志数据和物流数据同有的属性

java 复制代码
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]
                ;
    }
}

LogRec类,是DataBase的子类,继承了DataBase并增加了日志数据专有的属性

java 复制代码
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(",");
    }
}

Transport类是DataBase的子类,继承了DataBase并增加了物流数据专有的属性

java 复制代码
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(",");
    }
}

MatchedDataBase类,不写代码,表示匹配后的数据

java 复制代码
package com.qst.dms.entity;

import java.io.Serializable;

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

MatchedLogRec类,继承了MatchedDataBase类,并增加了匹配日志信息的专有属性与方法

java 复制代码
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();
    }

}

MatchedTransport类,继承了MatchedDataBase类,并增加了匹配物流信息的专有属性与方法

java 复制代码
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();
    }
}

User类,定义了用户的信息,用于用户的注册和登录

java 复制代码
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 业务类及设计

DmsNetService类用于客户端与服务端的连接服务,用于确保客户端与服务端连接成功并进行数据的传输

java 复制代码
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;
    }

}

LogRecService类中有许多方法,其中包含了日志数据的文件操作以及数据库操作,实现了日志数据的存取。

java 复制代码
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;
    }

}

TransportService类中有许多方法,其中包含了物流数据的文件操作以及数据库操作,实现了物流数据的存取。

java 复制代码
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;
    }
}

UserService类实现了用户的注册以及登录信息的存储操作,将用户信息存入了数据库。

java 复制代码
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 异常处理

项目中有许多异常处理结构,比如当用户在注册时输入的用户名已经存在时,会提示"用户名已存在"的警告信息;当用户在客户端录入数据时输入了相同的id,会提示"id相同"的警告信息,并提示用户重新输入信息等等

3.7 界面设计

LoginFrame类实现了登陆界面

java 复制代码
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();
        }
    }
}

RegistFrame类实现了注册界面

java 复制代码
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);
            }
        }
    }
}

ClientFrame类实现了客户端的操作界面

java 复制代码
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();
    }



}

ServerFrame类实现了服务端的操作界面

java 复制代码
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. 系统测试

4.1 设置测试数据

用户表

匹配日志表

匹配物流表

客户端


服务端


相关推荐
AI_56782 小时前
阿里云OSS成本优化:生命周期规则+分层存储省70%
运维·数据库·人工智能·ai
送秋三十五2 小时前
一次大文件处理性能优化实录————Java 优化过程
java·开发语言·性能优化
choke2332 小时前
软件测试任务测试
服务器·数据库·sqlserver
龙山云仓2 小时前
MES系统超融合架构
大数据·数据库·人工智能·sql·机器学习·架构·全文检索
雨中飘荡的记忆2 小时前
千万级数据秒级对账!银行日终批处理对账系统从理论到实战
java
IT邦德2 小时前
OEL9.7 安装 Oracle 26ai RAC
数据库·oracle
jbtianci2 小时前
Spring Boot管理用户数据
java·spring boot·后端
Sylvia-girl2 小时前
线程池~~
java·开发语言
魔力军2 小时前
Rust学习Day3: 3个小demo实现
java·学习·rust
时艰.2 小时前
java性能调优 — 高并发缓存一致性
java·开发语言·缓存