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 + "}"; } }