文章目录
- 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来创建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类实现了从数据库中读取出日志或物流数据,然后将数据以表格的形式显示出来的功能。
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类实现了连接数据库并进行事物处理的简单操作。
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如下,保存了数据库的配置数据
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;
}
@Override
public 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;
}
@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并增加了物流数据专有的属性
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类,不写代码,表示匹配后的数据
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;
}
@Override
public 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;
}
@Override
public 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("保存匹配记录中的登出日志成功");
// 保存匹配日志的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类中有许多方法,其中包含了物流数据的文件操作以及数据库操作,实现了物流数据的存取。
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类实现了用户的注册以及登录信息的存储操作,将用户信息存入了数据库。
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类实现了登陆界面
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类实现了注册界面
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类实现了客户端的操作界面
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类实现了服务端的操作界面
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 设置测试数据
用户表
匹配日志表
匹配物流表
客户端
服务端