文章目录
- 1. 系统需求分析
- 1.1 需求概述
- 1.2 需求说明
- 2. 系统总体设计
- 2.1 编写目的
- 2.2 总体设计
- 2.2.1 功能划分
- 2.2.2 数据库及表
- 2.2.3 主要业务流程
- 3. 详细设计与实现
- 3.1 表设计
- 3.2 数据库访问工具类设计
- 3.3 配置文件
- 3.4 实体类及设计
- 3.5 业务类及设计
- 3.6 异常处理
- 3.7 界面设计
- 4. 系统测试
- 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类实现了从文件中读取出日志或物流数据,然后将数据以表格的形式显示出来的功能。
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来创建TableModelprivate List<String[]> datas = new ArrayList<>();// 标志位,区分日志和物流:1,日志;0,物流private int sign;public DataTableModelFromList(List<T> data, int sign) {// TODO Auto-generated constructor stubthis.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 blocke.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类实现了从数据库中读取出日志或物流数据,然后将数据以表格的形式显示出来的功能。
package com.qst.dms.entity;import javax.swing.table.AbstractTableModel;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;public class MatchedTableModel extends AbstractTableModel {// 使用ResultSet来创建TableModelprivate 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类实现了连接数据库并进行事物处理的简单操作。
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 blocke.printStackTrace();}}//手动回滚事务public void rollbackAll() {try {if(conn!=null&&!conn.isClosed())conn.rollback();} catch (SQLException e) {// TODO Auto-generated catch blocke.printStackTrace();}}/*** 释放资源*/public void closeAll() {// 如果rs不空,关闭rsif (rs != null) {try {rs.close();} catch (SQLException e) {e.printStackTrace();}}// 如果pstmt不空,关闭pstmtif (pstmt != null) {try {pstmt.close();} catch (SQLException e) {e.printStackTrace();}}// 如果conn不空,关闭connif (conn != null) {try {conn.close();} catch (SQLException e) {e.printStackTrace();}}}/*** 执行SQL语句,可以进行查询*/public ResultSet executeQuery(String preparedSql, Object[] param) {// 处理SQL,执行SQLtry {// 得到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,执行SQLtry {// 得到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如下,保存了数据库的配置数据
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保存了客户端的配置
host=******
port=******
server.properties保存了服务端的配置
port=******
3.4 实体类及设计
DataBase父类,定义了日志数据和物流数据同有的属性
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;}@Overridepublic String toString() {return "\nid=" + id +"\ntime=" + time +"\naddress=" + address +"\ntype=" + DataType[type];}
}
LogRec类,是DataBase的子类,继承了DataBase并增加了日志数据专有的属性
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;}@Overridepublic 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并增加了物流数据专有的属性
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;}@Overridepublic 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类,不写代码,表示匹配后的数据
package com.qst.dms.entity;import java.io.Serializable;public class MatchedDataBase implements Serializable {private static final String serialVersionUID = "1L";
}
MatchedLogRec类,继承了MatchedDataBase类,并增加了匹配日志信息的专有属性与方法
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;}@Overridepublic String toString() {return login.toString() + " | " + logout.toString();}}
MatchedTransport类,继承了MatchedDataBase类,并增加了匹配物流信息的专有属性与方法
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;}@Overridepublic String toString() {return send.toString() + " | " + trans.toString() + " | " + receive.toString();}
}
User类,定义了用户的信息,用于用户的注册和登录
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类用于客户端与服务端的连接服务,用于确保客户端与服务端连接成功并进行数据的传输
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类中有许多方法,其中包含了日志数据的文件操作以及数据库操作,实现了日志数据的存取。
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("保存匹配记录中的登出日志成功");// 保存匹配日志的IDString 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()//获取数据库中的所有匹配的日志信息,返回一个ResultSetpublic 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类中有许多方法,其中包含了物流数据的文件操作以及数据库操作,实现了物流数据的存取。
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("保存匹配物流中的接收日志成功");// 保存匹配日志的IDString 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();}}}}//获取数据库中的所有匹配的物流信息,返回一个ResultSetpublic ResultSet readTransResult() {//获取匹配物流表中的所有数据,返回ResultSetResultSet 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类实现了用户的注册以及登录信息的存储操作,将用户信息存入了数据库。
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,失败返回falsetry {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类实现了登陆界面
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();// 设置窗体的iconImageIcon 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类实现了注册界面
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();// 设置窗体的iconImageIcon 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类实现了客户端的操作界面
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,showBtnprivate 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;//日志原始数据显示Tableprivate 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;//服务端IPprivate int serverPort;//服务端端口//客户端配置文件private final static String CONFIG_FILE = "config/client.properties";private void initConfig() {try {//通过Properties类获取配置文件中的属性赋值给serverPort和serverIpProperties 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 stubsuper("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);//创建菜单条,并放入到JFrameoper = 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() {@Overridepublic void actionPerformed(ActionEvent e) {// TODO Auto-generated method stubSystem.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默认有个JPanelthis.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{@Overridepublic void actionPerformed(ActionEvent e){card.show(p, "gather");}}// 匹配日志信息监听类private class MatchedLogRecListener implements ActionListener{@Overridepublic 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{@Overridepublic 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{@Overridepublic 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{@Overridepublic 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) {// 获取日志IDint 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) {// 获取物流IDint 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{@Overridepublic 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 stubnew LoginFrame();}}
ServerFrame类实现了服务端的操作界面
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;//服务Socketprivate 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和serverIpProperties 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() {@Overridepublic void actionPerformed(ActionEvent e) {// TODO Auto-generated method stubSystem. 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 {@Overridepublic void actionPerformed(ActionEvent e) {// TODO Auto-generated method stub//切换显示卡片,参考ClientFramecard.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 {@Overridepublic 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");//存储成功,返回truereturn true;} catch (IOException | ClassNotFoundException e) {System.out.println("读取信息发生异常:" + e.getMessage() + "\n");}//否则返回Falsereturn 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 设置测试数据
用户表
匹配日志表
匹配物流表
客户端
服务端