ARTICLE DETAIL

资讯详情

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

JavaWeb个人网上银行系统源码拆包:MVC分层与事务管理实战

JavaWeb个人网上银行系统源码拆包:MVC分层与事务管理实战 简介本资源为基于JavaWeb开发的个人网上银行系统完整项目包采用MVC模式分层设计面向计算机相关专业的在校学生、教师及企业开发者可用于毕业设计、课程设计、大作业或初期项目立项演示。压缩包共368个文件约64.8MB包含52个Java源文件、31个JSP页面、84个JavaScript脚本、48个CSS样式及83张PNG截图另附数据库SQL脚本、项目报告文档与系统截图覆盖登录、存款、转账、定期存款、活期转定期、信息展示及日志查看等核心功能模块。项目代码均经过功能验证可稳定运行并配有需求分析、总体设计、详细设计、数据库设计与测试说明便于读者理解MVC架构与银行业务逻辑。目前已有147人学习下载适合作为入门进阶参考或二次开发基础。1. 个人网上银行系统源码拆包一套能跑通存转定期的 JavaWeb 毕设很多同学做毕业设计时最头疼的不是写不出代码而是找不到一套结构完整、能跑通、还带报告和截图的参考项目。这套基于 JavaWeb 的个人网上银行系统正好卡在这个需求点上——它用 MVC 模式把用户登录、存款、转账、定期存款、活期转定期、日志查看这些银行核心业务串了起来附带数据库脚本、设计报告和系统截图。适合计算机相关专业的在校生做课程设计或毕设也适合刚接触 JavaWeb 想找一个完整案例练手的开发者。下面我从拆包结构、环境搭建、核心功能实现到踩坑排查把这份资源完整过一遍。2. 拆包看结构MVC 分层与数据库表怎么对应拿到压缩包先别急着导入 IDE花十分钟把目录结构和数据库脚本对一遍后面能省掉大量返工。这套项目用的是经典 MVC 三层架构配合 JSP 做视图层Servlet 做控制层JavaBean DAO 做模型层前端还引了 Bootstrap、FontAwesome、Summernote、Datepicker 这些静态资源。2.1 目录结构与技术栈清单解压后大致会看到这么几块内容目录/文件作用技术点src/Java 源码Servlet、JavaBean、DAO、工具类WebContent/ 或 webapp/前端资源JSP、CSS、JS、字体图标sql/ 或 db/数据库脚本MySQL 建表与初始数据报告文档设计说明需求分析、详细设计、测试截图目录运行效果各功能页面截图前端资源里能看到fontawesome-webfont.svg_v4.3.0、fontawesome-webfont.ttf_v4.3.0、fontawesome-webfont.woff_v4.3.0、fontawesome-webfont.eot_v4.3.0、fontawesome-webfont.woff2_v4.3.0这一整套字体文件说明图标用的是 FontAwesome 4.3.0。样式表里有bootstrap.min.css、animate.css、datepicker3.css、summernote-bs3.css、style.css基本可以判断前端是 Bootstrap 3 jQuery 那一套日期选择用 bootstrap-datepicker富文本编辑用 Summernote。这套组合在当年的课程设计里非常主流兼容性好改起来也顺手。提示如果解压后看到_v4.3.0这种带下划线和等号的文件名是某些下载工具或服务器给静态资源加的版本参数直接重命名去掉_v4.3.0后缀即可否则 CSS 里引用字体时可能 404。2.2 数据库表与业务功能的映射关系银行系统的核心在数据库设计。根据报告里的功能清单至少需要这么几张表用户表user存登录账号、密码、姓名、身份证、联系方式对应登录功能。账户表account存卡号、余额、账户类型活期/定期、开户时间对应存款和查询。交易记录表transaction存流水号、卡号、交易类型、金额、交易时间、备注对应转账、存取款、日志查看。定期存款表deposit存定期单号、卡号、本金、利率、存期、到期日对应定期存款和活期转定期。建表时注意金额字段用DECIMAL(15,2)而不是FLOAT这是血泪经验——浮点数在多次加减后会出现精度丢失银行系统里一分钱的误差都是事故。交易时间用DATETIME别用TIMESTAMP后者有 2038 年上限虽然课程设计跑不到那时候但习惯要养好。CREATE TABLE account ( card_no VARCHAR(20) PRIMARY KEY, user_id INT NOT NULL, balance DECIMAL(15,2) DEFAULT 0.00, account_type VARCHAR(10) DEFAULT 活期, open_time DATETIME DEFAULT CURRENT_TIMESTAMP, status TINYINT DEFAULT 1 ) ENGINEInnoDB DEFAULT CHARSETutf8mb4;这段建表语句里card_no做主键是因为卡号本身唯一且业务查询频繁balance用DECIMAL保证金额精确status字段用来做账户冻结/注销的软删除比物理删除安全。ENGINEInnoDB是为了支持事务转账操作必须在一个事务里完成扣款和入账否则中途失败会出现单边账。3. 环境搭建与项目导入从 JDK 到 Tomcat 的完整链路环境配置是新手翻车最多的地方。这套项目是传统 JavaWeb 项目不是 Spring Boot所以没有内嵌服务器必须自己配 Tomcat。下面按顺序走一遍。3.1 JDK、Tomcat、MySQL 版本选择版本不匹配是启动失败的头号原因。根据项目年代和技术栈推荐这套组合组件推荐版本说明JDK1.8高版本 JDK 编译老项目容易出兼容问题Tomcat8.5 或 9.0别用 Tomcat 10包名从 javax 变 jakarta 会全红MySQL5.7 或 8.08.0 需要改驱动类和连接串IDEIDEA 或 EclipseIDEA 需配 Web 模块和 ArtifactsTomcat 10 是最大的坑。它把 Servlet API 的包名从javax.servlet改成了jakarta.servlet这套老项目的 import 全是 javax换 Tomcat 10 直接编译不过。我一般会先确认项目里 import 的是哪个包再决定 Tomcat 版本。3.2 IDEA 导入与 Artifacts 配置IDEA 导入传统 JavaWeb 项目的关键在 Project Structure 里配三样东西SDK、Web 模块、Artifacts。# 第一步确认 JDK 版本 java -version # 输出应为 1.8.x # 第二步确认 MySQL 服务在跑 mysql -u root -p -e SELECT VERSION(); # 第三步导入数据库脚本 mysql -u root -p bank_db sql/bank_db.sql导入脚本后打开 IDEAFile → Project StructureProjectSDK 选 1.8Language level 选 8。Modules确认 src 被标记为 SourcesWebContent 或 webapp 被标记为 Web Resource Directoryweb.xml 路径指对。Artifacts新增 Web Application: Exploded把编译输出和 Web 资源都加进去。Run/Debug Configurations新增 Tomcat LocalDeployment 里选刚才的 ArtifactApplication context 设成/bank。配置完启动浏览器访问http://localhost:8080/bank/能看到登录页就成功了一半。3.3 数据库连接配置与驱动项目里通常有个db.properties或直接在工具类里写死连接信息。找到它改成自己的jdbc.drivercom.mysql.cj.jdbc.Driver jdbc.urljdbc:mysql://localhost:3306/bank_db?useSSLfalseserverTimezoneAsia/ShanghaicharacterEncodingutf8 jdbc.usernameroot jdbc.password你的密码MySQL 8.0 的驱动类是com.mysql.cj.jdbc.Driver5.7 是com.mysql.jdbc.Driver写错会报ClassNotFoundException。连接串里的serverTimezone必须加否则 8.0 会报时区错误。useSSLfalse是关掉 SSL 警告本地开发用不上。如果项目用的是连接池常见的是 Druid 或 C3P0还要检查连接池配置文件里的 URL 和账号密码是否同步改了。注意改完配置后一定要重新 Build Artifacts否则 Tomcat 跑的还是旧的 class 文件改了等于没改。4. 核心功能实现登录、存款、转账、定期存款的代码逻辑功能实现是这套项目的价值所在。报告里列了登录、存款、删除、修改、查询、信息展示、转账、定期存款、查看日志、活期转定期这些模块我挑几个最核心的讲清楚代码逻辑和参数设计。4.1 登录功能Session 管理与密码校验登录是入口逻辑不复杂但安全细节容易忽略。典型流程是JSP 表单提交账号密码 → Servlet 接收 → DAO 查库比对 → 成功则写 Session 并跳转主页。// LoginServlet.java 核心逻辑 protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String username req.getParameter(username); String password req.getParameter(password); UserDao userDao new UserDao(); User user userDao.findByUsername(username); if (user null) { req.setAttribute(msg, 用户不存在); req.getRequestDispatcher(login.jsp).forward(req, resp); return; } // 密码建议存 MD5 或 BCrypt 哈希别存明文 String hashed MD5Util.encode(password); if (!hashed.equals(user.getPassword())) { req.setAttribute(msg, 密码错误); req.getRequestDispatcher(login.jsp).forward(req, resp); return; } req.getSession().setAttribute(currentUser, user); resp.sendRedirect(main.jsp); }这段代码里findByUsername返回 null 和密码不匹配要分开提示方便调试但生产环境建议统一提示账号或密码错误防止枚举攻击。密码用 MD5 加盐或 BCrypt 哈希项目里如果存的是明文建议自己补一个哈希工具类。Session 里存 User 对象后续页面用session.getAttribute(currentUser)取当前登录人配合一个登录拦截 Filter 防止未登录直接访问内部页面。4.2 存款与查询事务边界与金额精度存款操作表面是加钱实际涉及账户余额更新和交易流水插入两步必须放在一个事务里。public boolean deposit(String cardNo, BigDecimal amount) { Connection conn null; try { conn DBUtil.getConnection(); conn.setAutoCommit(false); // 开启事务 // 第一步更新余额 String sql1 UPDATE account SET balance balance ? WHERE card_no ?; PreparedStatement ps1 conn.prepareStatement(sql1); ps1.setBigDecimal(1, amount); ps1.setString(2, cardNo); ps1.executeUpdate(); // 第二步插入流水 String sql2 INSERT INTO transaction(card_no, type, amount, trade_time) VALUES(?,?,?,NOW()); PreparedStatement ps2 conn.prepareStatement(sql2); ps2.setString(1, cardNo); ps2.setString(2, 存款); ps2.setBigDecimal(3, amount); ps2.executeUpdate(); conn.commit(); // 两步都成功才提交 return true; } catch (Exception e) { if (conn ! null) conn.rollback(); // 任一步失败全回滚 e.printStackTrace(); return false; } finally { DBUtil.close(conn); } }金额参数用BigDecimal而不是double这是银行系统的铁律。setAutoCommit(false)开启事务两步 SQL 都执行成功才commit任何一步抛异常就rollback保证不会出现钱加了但没流水或有流水但钱没加的单边情况。查询功能相对简单按卡号或交易时间范围查transaction表注意分页数据量大了不分页会拖垮页面。4.3 转账与活期转定期跨账户操作的一致性转账是这套系统里最考验事务设计的模块涉及两个账户的余额变动。public boolean transfer(String fromCard, String toCard, BigDecimal amount) { Connection conn null; try { conn DBUtil.getConnection(); conn.setAutoCommit(false); // 检查转出账户余额是否充足加行锁防止并发 String checkSql SELECT balance FROM account WHERE card_no ? FOR UPDATE; PreparedStatement checkPs conn.prepareStatement(checkSql); checkPs.setString(1, fromCard); ResultSet rs checkPs.executeQuery(); if (!rs.next() || rs.getBigDecimal(balance).compareTo(amount) 0) { conn.rollback(); return false; } // 扣转出方 String outSql UPDATE account SET balance balance - ? WHERE card_no ?; // 加转入方 String inSql UPDATE account SET balance balance ? WHERE card_no ?; // 插两条流水 // ... 执行后 commit conn.commit(); return true; } catch (Exception e) { if (conn ! null) conn.rollback(); return false; } finally { DBUtil.close(conn); } }关键在SELECT ... FOR UPDATE它给转出账户的行加了排他锁防止两个并发转账同时读到相同余额导致超额转出。活期转定期的逻辑类似只是目标从另一个活期账户变成定期存款表扣活期余额、插定期记录、更新账户类型同样在一个事务里完成。定期存款的利率和到期日计算项目里一般是按固定利率和存期算比如三个月 1.35%、一年 1.75%到期日 存入日 存期。5. 避坑与排查启动报错、乱码、事务失效的常见问题这套项目虽然经过验证但换台机器、换个版本就可能出问题。下面是我实际拆包时遇到的几类高频故障。5.1 启动报 ClassNotFoundException: com.mysql.jdbc.Driver现象Tomcat 启动后访问登录页提交表单报 500控制台提示找不到 MySQL 驱动类。原因项目用的驱动类名和实际 MySQL 版本不匹配或者mysql-connector-java.jar没放进WEB-INF/lib。解决MySQL 8.0 用com.mysql.cj.jdbc.Driver5.7 用com.mysql.jdbc.Driver。确认 jar 包在WEB-INF/lib下IDEA 里还要在 Project Structure → Artifacts 里确认该 jar 被包含进输出。改完重新 Build。5.2 页面中文乱码现象JSP 页面显示的问号或乱码表单提交的中文存进数据库变成乱码。原因三处编码没统一——JSP 页面pageEncoding、请求体编码、数据库连接串编码。解决JSP 头部加% page contentTypetext/html;charsetUTF-8 pageEncodingUTF-8 %Servlet 里req.setCharacterEncoding(UTF-8)和resp.setContentType(text/html;charsetUTF-8)连接串加characterEncodingutf8数据库和表用utf8mb4。四处都对了才不会乱码。5.3 转账后余额不对或流水缺失现象转账成功提示了但一方余额没变或者流水少了一条。原因事务没生效通常是setAutoCommit(false)没设或者 DAO 里每次操作都拿了新连接导致两步不在同一个事务里。解决确保整个转账流程共用一个 Connection在 Service 层开启和提交事务DAO 层只负责执行 SQL 不自己关连接。检查conn.commit()和conn.rollback()是否成对出现。5.4 Tomcat 启动端口被占用现象启动报Address already in use: bind。原因8080 端口被其他程序另一个 Tomcat、某些开发工具占了。解决改 Tomcat 的conf/server.xml里 Connector 的 port或者用netstat -ano | findstr 8080找到占用进程结束掉。IDEA 里也可以在 Run Configuration 的 Startup/Connection 里改端口。5.5 静态资源 404页面没样式现象登录页能打开但没样式没图标控制台一堆 404。原因CSS、JS、字体文件的路径不对或者 Artifact 里没包含 WebContent 下的静态资源。解决检查 JSP 里引用路径是相对路径还是绝对路径建议用${pageContext.request.contextPath}/css/xxx.css。确认 Artifacts 的 Output Layout 里 WebContent 整个目录被加进去了。字体文件那个_v4.3.0后缀如果没去掉CSS 里引用的路径对不上也会 404。6. 二次开发与验证把课程设计改成能写进简历的项目这套源码直接交作业没问题但如果你想让它成为简历上的亮点得做点二次开发。我的习惯是先从数据库设计文档反推业务边界再挑一两个模块做增强最后用测试用例验证改动没破坏原有功能。6.1 从功能验证到自动化测试项目自带的测试是手工点页面报告里也是手工测试记录。想验证改动是否安全可以补几个 JUnit 测试覆盖核心逻辑Test public void testTransferInsufficientBalance() { AccountService service new AccountService(); // 转出账户余额 100转 200 应失败 boolean result service.transfer(6222001, 6222002, new BigDecimal(200)); assertFalse(余额不足时应转账失败, result); // 验证双方余额未变 assertEquals(new BigDecimal(100), service.getBalance(6222001)); } Test public void testDepositThenQuery() { AccountService service new AccountService(); service.deposit(6222001, new BigDecimal(500)); assertEquals(new BigDecimal(600), service.getBalance(6222001)); }这两个用例一个测边界余额不足一个测正常流程存款后查询。跑通它们至少说明事务和金额计算没大问题。测试数据用独立的测试库别污染演示数据。6.2 三个能写进简历的增强方向第一加密码加密和登录拦截。把明文密码改成 BCrypt 哈希加一个 Filter 拦截未登录请求这是安全基线面试官看到会加分。第二加交易流水分页和条件查询。原项目的日志查看如果是一次性全查出来数据一多就卡。改成按时间范围 交易类型 分页查询用LIMIT offset, size实现前端配合分页组件。第三加简单的并发控制演示。用 JMeter 或自己写多线程模拟同一账户并发转账对比加FOR UPDATE和不加的结果这个实验能让你真正理解数据库锁面试时讲出来很有说服力。6.3 验证清单与交付前检查改完之后按这个清单过一遍再交付检查项验证方法通过标准登录正确/错误密码各试一次正确进主页错误有提示存款存 100 后查余额余额增加 100流水多一条转账转出转入各查一次双方余额正确两条流水定期活期转定期后查两张表活期减少定期增加并发两线程同时转同一账户无超额转出余额正确乱码输入中文姓名和备注页面和数据库都正常显示这套流程走下来你对 MVC 分层、事务管理、数据库锁的理解会比只跑通 demo 深一个层次。从那以后我每次拿到这类课程设计源码都强制先跑一遍上面的验证清单再动手改避免在错误的基础上叠功能。希望这套拆解能帮你少走点弯路顺利把项目跑起来、改下去。本文还有配套的精品资源点击获取
返回列表