ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

基于Java+Swing+MySQL的餐厅点餐管理系统完整开发指南

基于Java+Swing+MySQL的餐厅点餐管理系统完整开发指南 简介这是一套基于Java Swing与MySQL的餐厅点餐管理系统适合Java课程设计、毕业设计或入门桌面应用开发的读者参考。系统覆盖管理员与顾客两类角色包括注册登录、套餐新增与管理、订单处理、顾客点餐、订单查看、个人信息修改和密码修改等完整业务流程功能设计贴近真实餐饮管理场景运行环境为Eclipse/IDEA搭配MySQL 8.0以上。资源包共170个文件含18个java源码文件、66个class编译文件、3个jar依赖库和1个sql数据库脚本可通过sql脚本快速初始化数据库另附62张png与16张jpg界面截图便于对照界面效果整包体积仅2.19MB结构简洁便于快速部署。目前已有1532人学习/下载。通过这套资源读者能获取可直接运行的完整项目、数据库建表脚本和可视化界面素材既可快速启动演示也能基于源码进行二次开发加深对Swing与MySQL联动开发的理解。1. 基于JavaSwingMySQL的餐厅点餐管理系统为什么桌面端项目仍然值得亲手做一遍提起Java桌面应用很多人的第一反应是“都什么年代了还在用Swing”。但恰恰是“基于JavaSwingMySQL的点餐管理系统”这类项目构成了绝大多数计算机专业学生第一次完整接触Java图形界面、JDBC数据库编程、分层架构的真实战场。它没有Spring Boot那种框架托底的舒适区所有界面跳转、事件监听、数据库连接都得自己一点点写出来。这个过程虽然显得原始但你会在里面学会最本质的Java程序运行逻辑主类怎么启动、界面线程在哪里跑、数据库连接什么时候打开什么时候关闭、异常最终会抛到哪里。本文不讲解系统演示也不贴花哨的运行截图而是把整个系统从MySQL建表到Swing界面再到JDBC业务代码完整地走一遍同时把开发期间最常见的字符集、驱动版本、表名大小写这些“卡住新手三天”的问题全部摊开来说。2. 把数据结构先钉死五张核心表与订单外键链2.1 为什么开发顺序必须先MySQL后Swing大部分首次做这类项目的同学会先启动NetBeans或Eclipse拖一个登录窗口出来鼠标拖了半天觉得很爽结果写业务逻辑的时候发现登录要查员工表点餐要写订单表结算要更新菜品销量报表要聚合订单明细——这些操作全都要依赖数据库结构。界面拖得越复杂后面改表越痛苦。桌面端项目不同于Web项目接口协议是自己定的所以数据模型的优先级远高于界面。我一般会建议先花半天时间把MySQL里的表建好再回头画界面。你先确定有哪些数据需要存以及数据之间的关系界面上放几个按钮、几个表格自然就清楚了。一个典型的餐厅点餐管理系统数据量并不大但业务的完整性要求它至少覆盖员工、菜品、会员、订单、订单明细这五个实体。2.2 建表SQL一次把类型、编码、默认值都写对下面这份SQL是一套比较通用的结构适用于MySQL 5.7和8.0两个大版本。注意我刻意少用了一些时髦特性比如JSON类型、CHECK约束目的是让你在低版本MySQL上也能直接跑通。-- 员工表登录账号、角色区分管理员和收银员 CREATE TABLE staff ( id INT PRIMARY KEY AUTO_INCREMENT COMMENT 员工ID, username VARCHAR(50) NOT NULL UNIQUE COMMENT 登录账号, password VARCHAR(255) NOT NULL COMMENT 密码(建议存MD5), real_name VARCHAR(50) NOT NULL COMMENT 真实姓名, role TINYINT NOT NULL DEFAULT 2 COMMENT 角色:1管理员,2收银员, create_time DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT 创建时间 ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT员工表; -- 菜品表状态字段用于下架 CREATE TABLE dish ( id INT PRIMARY KEY AUTO_INCREMENT COMMENT 菜品ID, name VARCHAR(100) NOT NULL COMMENT 菜品名称, category VARCHAR(50) NOT NULL COMMENT 分类:热菜/凉菜/主食/饮品, price DECIMAL(10,2) NOT NULL COMMENT 单价, status TINYINT NOT NULL DEFAULT 1 COMMENT 1在售,0下架, sales_count INT NOT NULL DEFAULT 0 COMMENT 销量统计 ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT菜品表; -- 会员表手机号作为业务主键 CREATE TABLE member ( id INT PRIMARY KEY AUTO_INCREMENT COMMENT 会员ID, phone VARCHAR(20) NOT NULL UNIQUE COMMENT 手机号, name VARCHAR(50) NOT NULL COMMENT 会员姓名, points INT NOT NULL DEFAULT 0 COMMENT 积分 ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT会员表; -- 订单表 CREATE TABLE t_order ( id INT PRIMARY KEY AUTO_INCREMENT COMMENT 订单ID, order_no VARCHAR(30) NOT NULL UNIQUE COMMENT 订单号, staff_id INT NOT NULL COMMENT 操作收银员, member_id INT DEFAULT NULL COMMENT 会员ID,可有可无, total_amount DECIMAL(10,2) NOT NULL COMMENT 订单总金额, pay_time DATETIME NOT NULL COMMENT 支付时间, FOREIGN KEY (staff_id) REFERENCES staff(id), FOREIGN KEY (member_id) REFERENCES member(id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT订单表; -- 订单明细表 CREATE TABLE t_order_item ( id INT PRIMARY KEY AUTO_INCREMENT COMMENT 明细ID, order_id INT NOT NULL COMMENT 所属订单, dish_id INT NOT NULL COMMENT 菜品ID, quantity INT NOT NULL COMMENT 数量, subtotal DECIMAL(10,2) NOT NULL COMMENT 小计, FOREIGN KEY (order_id) REFERENCES t_order(id), FOREIGN KEY (dish_id) REFERENCES dish(id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT订单明细表;这份SQL里面有四个细节值得你注意。第一订单表我命名为t_order而不是order。ORDER是MySQL的保留字你写CREATE TABLE order会直接语法报错加了前缀t_就安全了而且这个习惯在联表查询时语义也更清楚。第二所有表都使用InnoDB引擎。原因很简单外键约束在InnoDB下才真正生效你用MyISAM虽然能建出表但外键只是文档上的说明实际删除父表记录时子表不会收到限制。第三金额统一用DECIMAL(10,2)绝对不要用FLOAT或DOUBLE存钱。二进制浮点数在累加时会产生令人困惑的精度误差比如0.10.2不等于0.3。点餐系统的结算金额每分钱都要对得上用定点数才是正经做法。第四staff表里我在role字段上加了默认值2。意思是说如果程序漏传了这个字段默认创建的是收银员账号而不是管理员避免误操作把最高权限给出去。2.3 外键与索引查询快一个量级的代价建好表之后有人会纠结要不要真的在t_order_item上建外键。我的建议是建——这是桌面端系统并发量远没有Web后端那么夸张外键带来的额外检查成本完全可忽略而它带来的数据完整性保障却非常实惠。比如你删掉一个菜品如果订单明细里还在引用它MySQL会拒绝删除并报错这比你写了半天的软删除逻辑要省事得多。另外别忘了给查询字段加索引。t_order表上的pay_time一定会被用于“查询某日营业额”的报表统计不加索引时全表扫描对几十万条订单数据会卡出明显延迟。可以在建表语句之外补一句ALTER TABLE t_order ADD INDEX idx_pay_time (pay_time);关于销量统计很多人会想到用ORDER BY sales_count DESC排个序然后在程序里统计。这里我可以提醒你一句点餐系统开发到后期你大概率会需要一张“菜品销量排行”的报表。与其在Java代码里聚合数据不如直接用一条SQLSELECT d.name, SUM(ti.quantity) AS sold FROM t_order_item ti JOIN dish d ON ti.dish_id d.id GROUP BY d.id ORDER BY sold DESC;手续越少越好——这就是数据库先行带来的直接收益。你的Swing界面后期只要绑定这个查询结果就有现成的报表数据源。3. 界面层Swing组件写点餐主界面的取舍3.1 Swing开发的“劝退点”与应对方式Swing被吐槽得最多的就是界面丑、布局难调。丑的问题我承认但布局难调多半是因为没用对布局管理器。很多初学者拿到JFrame就直接setLayout(null)然后靠setBounds(x, y, w, h)去坐标手工定位这种写法在窗口拉伸或者字体缩放时必然乱套。桌面端窗口一般不允许用户自由缩放但布局管理器仍然会让你的代码简洁很多。应对方式就一条外层用BorderLayout内部面板用GridBagLayout。BorderLayout最符合点餐系统的界面结构——顶部放标题和当前登录人左侧放菜品分类列表中央放菜品表格右侧放购物车列表底部放结算按钮和统计信息。GridBagLayout虽然写起来麻烦但它能精确控制控件在面板里的位置、宽度权重、拉伸策略特别是购物车这种需要“数量列宽一点、金额列宽一点”的场景不用它很难做得舒服。3.2 主界面骨架代码JFrameJPanelJTable的最小运行结构先看下面的代码这是一个能运行的最简主窗体结构。这里我只写了框架部分业务细节在第四章展开。import javax.swing.*; import java.awt.*; public class MainFrame extends JFrame { public MainFrame() { setTitle(餐厅点餐管理系统); setSize(1024, 768); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setLocationRelativeTo(null); // 窗口居中 // 顶部登录信息 JPanel topPanel new JPanel(new FlowLayout(FlowLayout.RIGHT)); topPanel.add(new JLabel(当前操作员 UserContext.getCurrentUserName())); topPanel.add(new JButton(退出登录)); // 左侧菜品分类 JPanel leftPanel new JPanel(new BorderLayout()); JListString categoryList new JList(new String[]{热菜, 凉菜, 主食, 饮品}); leftPanel.add(new JLabel(菜品分类, SwingConstants.CENTER), BorderLayout.NORTH); leftPanel.add(new JScrollPane(categoryList), BorderLayout.CENTER); // 中央菜品列表仅展示在售 JTable dishTable new JTable(); JScrollPane dishScroll new JScrollPane(dishTable); dishTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); // 右侧购物车 JTable cartTable new JTable(); JScrollPane cartScroll new JScrollPane(cartTable); // 底部结算区 JPanel bottomPanel new JPanel(new FlowLayout(FlowLayout.RIGHT)); JLabel totalLabel new JLabel(合计0.00); JButton checkoutBtn new JButton(结算); bottomPanel.add(totalLabel); bottomPanel.add(checkoutBtn); // 组装中央用JSplitPane分隔菜品区和购物车 JSplitPane splitPane new JSplitPane( JSplitPane.HORIZONTAL_SPLIT, dishScroll, cartScroll); splitPane.setResizeWeight(0.6); // 左侧占60%宽 add(topPanel, BorderLayout.NORTH); add(leftPanel, BorderLayout.WEST); add(splitPane, BorderLayout.CENTER); add(bottomPanel, BorderLayout.SOUTH); } public static void main(String[] args) { // Swing界面必须在事件调度线程创建否则偶发界面不刷新 SwingUtilities.invokeLater(() - { new MainFrame().setVisible(true); }); } }SwingUtilities.invokeLater这行代码建议你形成肌肉记忆后面写任何Swing程序都带上它。它是Swing单线程模型的入口把界面创建任务丢给EDT事件派发线程执行如果你直接在main线程里创建JFrame某些Linux和macOS环境下窗口可能无法正确绘制。JSplitPane比用一个固定布局更实用。点餐时中央菜品的行数往往少于购物车行数分割条允许操作员手动调整两个区域的高度平衡这对桌面上鼠标操作来说体验好很多。3.3 购物车与订单窗口的组件选型购物车和菜品列表我用的是JTable而不是JList这里解释一下理由。JTable天然支持多列——菜品名称、单价、数量、小计放到一张表里每一列可以单独设置宽度。而JList只能显示单列文本你还要自己拼HTML才能做出两列的效果对TableModel的修改也会被直接映射到界面刷新效率更好。订单结算完毕后建议弹出一个新的JDialog窗口用来展示本次订单的明细。JDialog比JFrame更合适做这种临时窗口因为它可以不创建任务栏图标而且设置了setModal(true)之后用户必须关掉它才能回到主界面继续操作符合“结完账再看一眼”的使用习惯。4. 业务层JDBC连接与登录、点餐、统计三条主流程4.1 JDBC连接参数driver、url四件套Swing界面写完之后你要做的第一件事就是把数据库连接打通。这一步的重要性不用多说但连接失败之后很多人就卡住了。先看一个正确的连接工具类写法import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; public class DBUtil { // 这四个配置项建议放到配置文件这里写死仅为演示 private static final String DRIVER com.mysql.cj.jdbc.Driver; private static final String URL jdbc:mysql://localhost:3306/restaurant ?useUnicodetruecharacterEncodingutf8 useSSLfalseserverTimezoneAsia/ShanghaiallowPublicKeyRetrievaltrue; private static final String USER root; private static final String PASSWORD 你的数据库密码; static { try { Class.forName(DRIVER); } catch (ClassNotFoundException e) { throw new RuntimeException(MySQL驱动加载失败检查jar包是否在classpath, e); } } public static Connection getConnection() throws SQLException { return DriverManager.getConnection(URL, USER, PASSWORD); } public static void close(Connection conn, java.sql.Statement stmt, java.sql.ResultSet rs) { try { if (rs ! null) rs.close(); } catch (SQLException ignored) {} try { if (stmt ! null) stmt.close(); } catch (SQLException ignored) {} try { if (conn ! null) conn.close(); } catch (SQLException ignored) {} } }这套连接参数里最容易出问题的三个参数分别是useSSL、serverTimezone和allowPublicKeyRetrieval。如果去掉serverTimezone本地MySQL 8.0会报“The server time zone value”的错误。原因是MySQL服务器和JDBC驱动双方的时区默认值不一致。如果allowPublicKeyRetrieval不打开MySQL 8.0下caching_sha2_password用户连接时经常会抛出“Public Key Retrieval is not allowed”异常这是MySQL 8.0默认加密插件的策略导致的。如果不加characterEncodingutf8后面你往数据库里写入中文的时候就会变成问号这个问题我在第五章细讲。另外注意我在静态代码块里做了Class.forName(DRIVER)。在JDBC 4.0以后驱动jar包里的META-INF/services/java.sql.Driver文件会被自动扫描这一步其实可以省掉。但保留下来有个好处如果驱动jar没打包进classpath程序启动时立刻就会抛异常提示你比连接到一半才找不到类错误更明确。4.2 登录校验用PreparedStatement代替Statement登录逻辑是每个点餐系统都要经历的第一道安全关。这里有一个容易犯的经典错误——用Statement拼接SQL字符串// 错误示范千万不要这么写 String sql SELECT * FROM staff WHERE username username AND password password ; Statement stmt conn.createStatement(); ResultSet rs stmt.executeQuery(sql);这段代码在SQL注入面前毫无还手之力。比如用户在输入框敲入admin --整个SQL就变成查询admin用户了。正确做法是使用PreparedStatement参数化查询public boolean login(String username, String password) { String sql SELECT id, real_name, role FROM staff WHERE username ? AND password ?; try (Connection conn DBUtil.getConnection(); PreparedStatement ps conn.prepareStatement(sql)) { ps.setString(1, username); ps.setString(2, md5(password)); // 至少做一次MD5不要存明文 try (ResultSet rs ps.executeQuery()) { if (rs.next()) { UserContext.setCurrentUser( rs.getInt(id), rs.getString(real_name), rs.getInt(role) ); return true; } } } catch (SQLException e) { e.printStackTrace(); } return false; }PreparedStatement把参数通过setString传入数据库驱动会对值做转义处理这样拼接注入只存在于初中级教程里的反面案例中。注意这里的加密逻辑演示代码里我写了md5(password)但真实项目中MD5已经被证实不够安全建议用BCrypt或SHA-256 随机盐。对于课设项目MD5加盐属于及格水平但你要在答辩时能说出理由——这才是重点。另外连接管理这里使用了try-with-resources语法一个try块结束后Connection、PreparedStatement、ResultSet都会被自动关闭不会出现连接泄漏。桌面端应用连接池往往不需要因为使用频率低且长时间保持连接在MySQL默认wait_timeout八小时后会自动断掉反而造成困惑。每次操作临时打开连接再关闭是更稳的方案。4.3 点餐结算与当日营业额统计点餐结算的关键在于事务。用户点击“结算”那一刻程序要做三件事插入订单主表、插入订单明细表、累加菜品的销量。这三件事任何一件失败数据库就会处于不一致状态——订单有了但明细缺失。代码如下public boolean checkout(CartItem[] items, Integer memberId) { // 使用事务要么全部成功要么全部回滚 String insertOrder INSERT INTO t_order(order_no, staff_id, member_id, total_amount, pay_time) VALUES(?,?,?,?,NOW()); String insertItem INSERT INTO t_order_item(order_id, dish_id, quantity, subtotal) VALUES(?,?,?,?); String updateSales UPDATE dish SET sales_count sales_count ? WHERE id ?; Connection conn null; try { conn DBUtil.getConnection(); conn.setAutoCommit(false); // 关闭自动提交开启事务 // 生成订单号时间戳随机数避免并发冲突 String orderNo D System.currentTimeMillis() (int)(Math.random()*1000); try (PreparedStatement ps conn.prepareStatement(insertOrder, PreparedStatement.RETURN_GENERATED_KEYS)) { ps.setString(1, orderNo); ps.setInt(2, UserContext.getCurrentUserId()); if (memberId ! null) { ps.setInt(3, memberId); } else { ps.setNull(3, java.sql.Types.INTEGER); } double total 0; for (CartItem item : items) { total item.getSubtotal(); } ps.setDouble(4, total); ps.executeUpdate(); // 获取数据库自动生成的订单ID ResultSet keys ps.getGeneratedKeys(); int orderId -1; if (keys.next()) { orderId keys.getInt(1); } try (PreparedStatement psItem conn.prepareStatement(insertItem); PreparedStatement psSales conn.prepareStatement(updateSales)) { for (CartItem item : items) { psItem.setInt(1, orderId); psItem.setInt(2, item.getDishId()); psItem.setInt(3, item.getQuantity()); psItem.setDouble(4, item.getSubtotal()); psItem.addBatch(); psSales.setInt(1, item.getQuantity()); psSales.setInt(2, item.getDishId()); psSales.addBatch(); } psItem.executeBatch(); psSales.executeBatch(); } } conn.commit(); return true; } catch (SQLException e) { try { if (conn ! null) conn.rollback(); } catch (SQLException ex) { ex.printStackTrace(); } e.printStackTrace(); return false; } finally { try { if (conn ! null) { conn.setAutoCommit(true); conn.close(); } } catch (SQLException e) { e.printStackTrace(); } } }这段代码里有两个容易被忽略的点。第一是PreparedStatement.RETURN_GENERATED_KEYS参数没有它你拿不到数据库自增的订单ID你没法往下插入明细。第二是addBatch()executeBatch()批量执行这是把多条INSERT合并成一次网络往返的技巧在桌面端虽然体感差异不大但代码结构更清晰。当日销售额统计比想象中简单得多SELECT COALESCE(SUM(total_amount), 0) AS today_amount FROM t_order WHERE DATE(pay_time) CURDATE();COALESCE在这里很关键因为如果今天还没有任何订单SUM会返回NULL而不是0Java侧解析rs.getDouble时会把NULL转成0但万一哪一天没有订单就显示不出金额那界面就有问题了。加上COALESCE之后SQL就永远返回数字。5. 开发期间最容易翻车的5个地方现象、原因、解决办法5.1 Class.forName之后仍然连接超时现象程序启动后卡在DriverManager.getConnection这一行等几十秒后抛CommunicationsException: Communications link failure。原因MySQL服务没有启动。Windows下最容易出现这种局面——装了MySQL但忘了注册成服务每次要手动打开命令行启动或者是在服务管理器里启动了但端口被占用。解决办法先确认服务状态。Windows上运行net start mysqlLinux上运行systemctl status mysqld。然后确认端口通不通telnet 127.0.0.1 3306如果telnet连不上八成是MySQL服务没起来。再检查一下URL里的localhost是解析到了IPv6还是IPv4某些机器localhost会指向::1而MySQL只监听IPv4把localhost换成127.0.0.1能绕开这个玄学问题。5.2 MySQL驱动类名不同导致ClassNotFound现象Class.forName(com.mysql.jdbc.Driver)抛出ClassNotFoundException。原因mysql-connector-java 5.x的驱动类名是com.mysql.jdbc.Driver但8.x已经把它改为com.mysql.cj.jdbc.Driver。旧类名在新驱动里只是遗留的桥接类在某些版本被移除了。解决办法在pom.xml或lib目录里查看你的jar版本。如果是8.0写com.mysql.cj.jdbc.DriverURL里记得带上serverTimezoneAsia/Shanghai。如果你是在做一个新项目直接使用8.0以上的驱动旧驱动连不上MySQL 5.7.44和8.0。常见做法是把驱动jar放进项目的lib目录然后用IDE的“Add as Library”导入避免手动设置classpath时漏掉。5.3 数据库中文全部变成问号现象通过点餐系统插入的菜名、用户名在MySQL里显示为???但在Navicat里手动插入中文又是正常的。原因十有八九是JDBC连接URL没有指定字符集。MySQL服务端默认字符集可能是latin1你直接写入UTF-8编码的中文数据存储层面上编码不匹配就变成了问号。解决办法URL里加useUnicodetruecharacterEncodingutf8并且确认建表语句里加了DEFAULT CHARSETutf8mb4。这两个地方缺一不可。另外如果你的Windows控制台运行Java程序时打出中文乱码那是系统控制台编码本身是GBK与数据库存储无关你可以在程序里用-Dfile.encodingUTF-8运行参数修正避免和数据库字符集问题混在一起排查。5.4 JTable刷新不生效改了数据界面还是老样子现象结算完购物车表格清空后调用table.repaint()但界面纹丝不动。原因repaint()只是让组件重新绘制像素不会重新读取数据模型。JTable的数据来源于TableModel你直接清空了List但没有让TableModel知道数据已经变了。解决办法不要直接操作List再repaint。应该重新构造一个DefaultTableModel对象或调用model.setRowCount(0)来清空数据行。由于TableModel会主动发事件给视图表格会自动重绘。如果你用的是自己继承AbstractTableModel的模型记得在数据变化后主动调用fireTableDataChanged()。5.5 表名大小写导致部署到Linux上查询失败现象Windows上开发的程序运行得好好的部署到Linux服务器多见于把数据库搬到生产或考试环境后执行SELECT * FROM t_order报Table restaurant.t_order doesnt exist。原因MySQL在Windows上lower_case_table_names默认值为1表名不区分大小写在Linux上默认值为0区分大小写。你在Windows建的表叫T_OrderLinux上找t_order就找不到。解决办法从开发第一天就统一使用小写表名这是成本最低的方案。如果已经发生在Linux端修改MySQL配置文件/etc/my.cnf在[mysqld]段下加lower_case_table_names1然后重启MySQL——注意改这个参数之前最好备份数据因为需要重建表才能完全生效。6. 最后一公里把系统变成能交付的jar并做一轮完整验证课设和毕设答辩的逻辑是程序能跑起来只是起点能交付脱离IDE的独立可运行jar包才是加分项。下面这一步我建议你一定会做——用命令行启动验证整个项目打包正确性。先用mvn package或IDE的Artifacts功能打包出带依赖的jar。打包时注意要带上MySQL驱动jar即使用maven-shade-plugin或IDE里“Include in project build”。如果最终只导出了一个几十KB的空壳jar那必然报ClassNotFoundException。打包之后打开命令行执行一次java -Dfile.encodingUTF-8 -jar restaurant-system.jar为什么一定要手动跑一次因为IDEA里运行程序时会自动帮你加上一堆classpath参数而命令行是最真实的环境。如果你在命令行能跑起来说明驱动jar、配置文件、日志库都齐了演示时不会翻车。启动成功后建议按这个清单做一次回归验证用普通收银员账号登录确认没有员工管理菜单新增一个菜品刷新菜品列表确认在售状态为1点一个菜品到购物车结算后去MySQL执行SELECT * FROM t_order_item确认明细行数正确查当日报表确认金额等于购物车合计关掉程序重新打开确认销量数据持久化这五步走完系统基本达到了可交付状态。如果想把项目做成局域网多机部署可以在另一台电脑上装MySQL服务端或直接把连接URL的localhost改成数据库所在机器的IP地址。这里有个隐患你需要提前知道MySQL默认只监听localhost需要把bind-address改成0.0.0.0并新建一个允许%远程访问的账号否则局域网内其他机器连不上。最后说一个我自己栽过跟头的习惯数据库密码和连接信息不要直接写死在业务代码里至少抽到config.properties外面。虽然Swing项目没有Web项目那么强的安全要求但答辩时你拿出一个配置文件解释“连接信息与业务代码解耦便于部署切换环境”评委的印象分会明显不同。数据库这块宁可多花半小时做扎实也别等报表统计时被一句“数据对不上”逼得从头找。做桌面端管理系统这么多年我最大的体会就是Swing项目不是用来展示前沿技术的而是用来检验你对Java最基础能力的掌握程度——事件、线程、IO、集合、JDBC每一个环节都是你自己亲手拼出来的。遇到它给的这些坑也不用怕踩过一次下次你就知道先看编码再看表名大小写。希望帮到你。本文还有配套的精品资源点击获取
返回列表