别再写if-else了!用Java MVC模式重构超市收银登录模块(附完整代码)

张开发
2026/4/8 0:54:30 15 分钟阅读

分享文章

别再写if-else了!用Java MVC模式重构超市收银登录模块(附完整代码)
从面条代码到优雅架构用MVC模式重构超市收银登录模块实战超市收银系统作为零售业的核心业务支撑其代码质量直接影响着系统的稳定性和可维护性。很多Java初学者在开发这类系统时常常会陷入面条式代码的陷阱——将所有逻辑堆砌在同一个类中导致代码难以阅读、测试和维护。本文将带你从零开始用MVC设计模式重构一个典型的超市收银登录模块展示如何将混乱的代码转化为清晰、可扩展的架构。1. 为什么我们需要重构登录模块在超市收银系统中登录功能看似简单实则承担着重要的安全验证和权限控制职责。一个典型的初学者实现往往将所有代码塞在main方法中就像下面这样public static void main(String[] args) { System.out.println(请输入用户名); Scanner scanner new Scanner(System.in); String username scanner.nextLine(); System.out.println(请输入密码); String password scanner.nextLine(); // 数据库连接和验证逻辑全部混在一起 try { Connection conn DriverManager.getConnection(jdbc:mysql://localhost:3306/sale, root, 123456); Statement stmt conn.createStatement(); ResultSet rs stmt.executeQuery(SELECT * FROM t_user WHERE usernameusername); if(rs.next()) { if(rs.getString(password).equals(password)) { System.out.println(登录成功); } else { System.out.println(密码错误); } } else { System.out.println(用户不存在); } } catch(SQLException e) { e.printStackTrace(); } }这种写法存在几个严重问题安全性风险直接拼接SQL语句存在SQL注入漏洞难以测试业务逻辑与数据库访问耦合无法单独测试验证逻辑缺乏扩展性若要增加验证码功能或日志记录需要修改多处代码职责不清一个方法承担了太多职责违反单一职责原则2. MVC架构的核心思想与优势MVCModel-View-Controller是一种经典的设计模式它将应用程序分为三个核心组件Model模型负责数据和业务逻辑View视图负责展示数据和用户界面Controller控制器接收用户输入协调模型和视图在Java项目中我们通常使用包(package)来组织这些组件src/ ├── controller/ # 控制器 ├── model/ # 模型 │ ├── dao/ # 数据访问对象 │ └── vo/ # 值对象 ├── service/ # 业务逻辑 ├── util/ # 工具类 └── view/ # 视图MVC模式的优势在于关注点分离各组件职责明确便于团队协作可测试性各层可以独立测试可维护性修改一个组件不会影响其他组件可扩展性可以方便地添加新功能3. 重构登录模块的详细步骤3.1 定义数据模型Model首先我们创建用户实体类对应数据库中的用户表// src/model/vo/User.java package model.vo; public class User { private String username; private String password; private String realName; private String role; // 构造方法、getter和setter省略 }然后创建数据访问对象(DAO)负责与数据库交互// src/model/dao/UserDao.java package model.dao; import model.vo.User; import util.DBUtil; import java.sql.*; public class UserDao { public User findByUsername(String username) { String sql SELECT * FROM t_user WHERE username ?; try (Connection conn DBUtil.getConnection(); PreparedStatement stmt conn.prepareStatement(sql)) { stmt.setString(1, username); ResultSet rs stmt.executeQuery(); if (rs.next()) { User user new User(); user.setUsername(rs.getString(username)); user.setPassword(rs.getString(password)); user.setRealName(rs.getString(real_name)); user.setRole(rs.getString(role)); return user; } } catch (SQLException e) { e.printStackTrace(); } return null; } }3.2 实现业务逻辑层Service业务逻辑层处理核心的业务规则如登录验证// src/service/UserService.java package service; import model.dao.UserDao; import model.vo.User; public class UserService { private UserDao userDao new UserDao(); public boolean login(String username, String password) { User user userDao.findByUsername(username); return user ! null user.getPassword().equals(password); } public User getUserInfo(String username) { return userDao.findByUsername(username); } }3.3 创建控制器Controller控制器负责处理用户输入调用相应的服务// src/controller/LoginController.java package controller; import service.UserService; import model.vo.User; import java.util.Scanner; public class LoginController { private UserService userService new UserService(); private Scanner scanner new Scanner(System.in); public void showLogin() { System.out.println( 超市收银系统登录 ); for (int attempt 0; attempt 3; attempt) { System.out.print(用户名: ); String username scanner.nextLine(); System.out.print(密码: ); String password scanner.nextLine(); if (userService.login(username, password)) { User user userService.getUserInfo(username); showWelcome(user); return; } System.out.println(用户名或密码错误请重试); } System.out.println(登录失败系统退出); System.exit(0); } private void showWelcome(User user) { System.out.println(\n欢迎 user.getRealName() [ user.getRole() ]); System.out.println(登录时间: new java.util.Date()); } }3.4 实现视图层View视图层负责展示信息在控制台应用中相对简单// src/view/MainView.java package view; import controller.LoginController; public class MainView { public static void main(String[] args) { LoginController loginController new LoginController(); loginController.showLogin(); } }4. 关键优化点与最佳实践4.1 数据库连接池优化原始的DBUtil每次获取新连接效率低下我们可以引入连接池// src/util/DatabasePool.java package util; import org.apache.commons.dbcp2.BasicDataSource; import java.sql.Connection; import java.sql.SQLException; public class DatabasePool { private static BasicDataSource dataSource new BasicDataSource(); static { dataSource.setUrl(jdbc:mysql://localhost:3306/sale); dataSource.setUsername(root); dataSource.setPassword(123456); dataSource.setMinIdle(5); dataSource.setMaxIdle(10); dataSource.setMaxTotal(25); } public static Connection getConnection() throws SQLException { return dataSource.getConnection(); } }4.2 密码安全存储明文存储密码非常危险我们应该使用哈希算法// src/util/SecurityUtil.java package util; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; public class SecurityUtil { public static String hashPassword(String password) { try { MessageDigest md MessageDigest.getInstance(SHA-256); byte[] hashedBytes md.digest(password.getBytes()); StringBuilder sb new StringBuilder(); for (byte b : hashedBytes) { sb.append(String.format(%02x, b)); } return sb.toString(); } catch (NoSuchAlgorithmException e) { throw new RuntimeException(哈希算法不可用, e); } } public static boolean verifyPassword(String input, String storedHash) { return hashPassword(input).equals(storedHash); } }4.3 日志记录添加日志记录可以帮助排查问题// src/util/Logger.java package util; import java.io.FileWriter; import java.io.IOException; import java.text.SimpleDateFormat; import java.util.Date; public class Logger { private static final String LOG_FILE system.log; public static void log(String message) { String timestamp new SimpleDateFormat(yyyy-MM-dd HH:mm:ss).format(new Date()); String logEntry timestamp - message \n; try (FileWriter writer new FileWriter(LOG_FILE, true)) { writer.write(logEntry); } catch (IOException e) { System.err.println(无法写入日志: e.getMessage()); } } }5. 完整代码结构与运行效果最终的代码结构如下supermarket-cashier/ ├── pom.xml └── src/ ├── main/ │ ├── java/ │ │ ├── controller/ │ │ │ └── LoginController.java │ │ ├── model/ │ │ │ ├── dao/ │ │ │ │ └── UserDao.java │ │ │ └── vo/ │ │ │ └── User.java │ │ ├── service/ │ │ │ └── UserService.java │ │ ├── util/ │ │ │ ├── DatabasePool.java │ │ │ ├── Logger.java │ │ │ └── SecurityUtil.java │ │ └── view/ │ │ └── MainView.java │ └── resources/ │ └── log4j2.xml └── test/ └── java/ └── service/ └── UserServiceTest.java运行效果示例 超市收银系统登录 用户名: cashier1 密码: 123456 欢迎张三 [收银员] 登录时间: Wed May 15 14:30:45 CST 20236. 如何进一步扩展系统基于MVC架构我们可以轻松扩展系统功能添加权限控制在UserService中添加角色验证实现记住我功能使用Cookie存储加密的token增加验证码在LoginController中添加验证码验证多语言支持在view层实现国际化切换UI框架只需修改view层不影响业务逻辑重构后的代码不仅更清晰、更安全也为未来的功能扩展打下了坚实基础。下次当你面对一堆面条代码时不妨考虑用MVC模式来重新组织它们你会发现代码维护变得如此轻松。

更多文章