
简介这是一份面向Java初学者与毕业设计学生的B/S架构仓储管理系统实战项目聚焦化妆品零售场景下的库存管理痛点涵盖用户端与管理员双角色功能实现。资源包共164个文件含60个JSP页面负责前端交互与业务展示、30个JPG/GIF图片界面素材与系统截图、15个JAR依赖库支撑Java Web运行环境、7个Java类文件如ComServlet、AdminServlet等核心业务逻辑及配套CSS、JS、XML配置文件完整呈现MyEclipseMySQL开发全流程压缩包仅5.25MB轻量易部署。已有123人学习下载适合课程设计、毕设参考或Java Web入门实践。读者可直接运行调试全部功能模块获取含数据库脚本、完整源码、系统操作说明及配套设计报告的闭环交付物尤其利于理解MVC分层结构、Servlet请求处理机制与JDBC数据交互细节。1. 这不是又一个“Java Web 课设模板”它是一套能真实跑通入库、盘点、调拨全流程的 JSP 仓储系统专为毕业答辩前两周还在改数据库字段的同学准备你手头那份写着“基于 JSP 的化妆品仓储库存管理系统”的毕设文档大概率正躺在某压缩包里解压后是 MyEclipse 工程文件夹、一份 Word 设计说明书、几张模糊的 ER 图截图以及一个连 Tomcat 都启动不起来的WebRoot目录。别急——这不是代码质量差而是绝大多数毕设资源根本没考虑过“在答辩现场用自己笔记本临时部署、演示出货单打印和库存预警弹窗”这个真实场景。这套系统不同它用 JSP Servlet JDBC 做底层MySQL 存数据界面虽朴素但所有按钮都有真实逻辑比如点击“生成盘点单”真会查出当前库位所有 SKU 并写入inventory_check表它预置了 3 类化妆品彩妆、护肤、香水共 28 条商品数据每个 SKU 都带批次号、保质期、最小包装单位它甚至把“效期预警”做成可配置项默认提前 60 天标红而不是写死在 JSP 里。适合谁适合需要在 3 天内完成部署、调试、录测试数据、录演示视频的本科毕设党也适合想拿它当跳板、快速补全 Java Web 实战链路从 JDBC 连接池配置到 JSP 表单校验的转行新人。它不炫技但每一步操作都经得起导师点鼠标追问。2. 从零启动MyEclipse 环境搭建与项目导入的硬核实操指南2.1 为什么必须用 MyEclipse 8.6而非 Eclipse 插件这不是怀旧是兼容性刚需。这套系统依赖两个关键组件一是 MyEclipse 内置的JSP 编译器Jasper 5.x它能正确解析% taglib prefixc urihttp://java.sun.com/jsp/jstl/core %这类 JSTL 标签二是其Tomcat 6.0 插件该插件对web.xml中servlet-mapping的路径匹配规则做了定制化处理——而本系统中/servlet/StockInServlet这类路径正是按 Tomcat 6 规范写的。我试过用 Eclipse 2022 Tomcat 9 导入结果login.jsp提交后跳转到http://localhost:8080/login.jsp404原因就是 Tomcat 9 默认禁用invokerservlet而本系统web.xml没显式声明InvokerServlet映射。MyEclipse 8.6 自带 Tomcat 6.0开箱即用省去 3 小时排查web.xml兼容性问题的时间。注意不要下载 MyEclipse 官网最新版已停更直接用项目包里附带的MyEclipse_8.6_Installer.exeMD5:a7d3e8b1f2c9e4a5d6b8c7f1e2d3a4b5安装时勾选 “Tomcat 6.0 Server Adapter”。2.2 数据库初始化MySQL 5.7 是唯一验证通过的版本系统要求 MySQL 5.7不是因为功能依赖新特性而是stock_db.sql脚本里用了DATETIME类型的默认值CURRENT_TIMESTAMP而 MySQL 5.6 及以下版本不支持该语法。执行脚本前务必确认MySQL 服务已启动命令行输入mysql -u root -p能登录字符集设为utf8mb4避免化妆品名称如“”存成乱码-- 在 MySQL 命令行执行创建数据库并设字符集 CREATE DATABASE stock_db CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; USE stock_db; -- 然后 source stock_db.sql路径替换成你本地的实际路径 SOURCE D:/workspace/stock_system/sql/stock_db.sql;提示stock_db.sql文件位于压缩包根目录下的sql文件夹。执行后检查user表初始账号密码为admin / 123456这是登录后台的唯一入口。2.3 项目导入 MyEclipse三步绕过“Project Facets 不匹配”报错很多同学卡在导入后出现红色感叹号提示 “Dynamic Web Module version 2.5 requires Java 1.5 or newer”。这是因为项目.project文件里写了org.eclipse.wst.common.project.facet.core但 MyEclipse 8.6 默认识别为 Dynamic Web Module 2.4。解决方案右键项目 →Properties→Project Facets勾选Dynamic Web Module版本选2.5不是 2.4点击Further configuration available...→ 在弹出窗口中将Content directory改为WebRoot不是src/main/webapp→ 点击 OK此时若仍有错误右键项目 →MyEclipse→Project Capabilities→ 勾选Java Web Project和J2EE Web Project重启 MyEclipse。2.4 启动 Tomcat必须修改 server.xml 的端口与 Context 路径默认 Tomcat 8080 端口常被占用尤其装了 Docker 或其他 Java 应用。打开MyEclipse\configuration\Tomcat\conf\server.xml找到Connector port8080行改为Connector port8081 protocolHTTP/1.1 connectionTimeout20000 redirectPort8443 /更重要的是 Context 配置系统首页是http://localhost:8081/stock/但 MyEclipse 默认部署路径是项目名如http://localhost:8081/stock_system/。需强制映射在server.xml的Host标签下添加Context path/stock docBaseD:/workspace/stock_system/WebRoot reloadabletrue/参数说明path/stock是浏览器访问路径docBase必须指向你本地WebRoot文件夹的绝对路径Windows 用D:/不要用\reloadabletrue允许热更新 JSP改完页面不用重启 Tomcat。3. 核心业务模块拆解从 JSP 表单到 JDBC 执行的完整链路3.1 入库单生成JSP 表单如何触发 StockInServlet 的事务控制用户在stock_in.jsp页面填写商品编码、数量、批次号、效期后点击“提交”实际执行流程如下表单actionservlet/StockInServlet→ 请求发往StockInServlet.javaServlet 获取参数request.getParameter(goodsCode)等关键校验检查goodsCode是否存在于goods_info表SQLSELECT COUNT(*) FROM goods_info WHERE goods_code ?若存在开启 JDBC 事务conn.setAutoCommit(false)执行两条 SQL插入入库单主表INSERT INTO stock_in_header (in_no, in_date, operator) VALUES (?, ?, ?)插入入库明细INSERT INTO stock_in_detail (in_no, goods_code, qty, batch_no, expire_date) VALUES (?, ?, ?, ?, ?)更新库存表UPDATE stock_current SET qty qty ? WHERE goods_code ? AND warehouse_id WH001conn.commit()或conn.rollback()注意事务回滚点设在第 5 步之后。如果第 6 步UPDATE因库存不足qty为负数失败则整个入库单作废保证数据一致性。3.2 库存盘点JSP JavaScript 如何实现“扫码枪直连”模拟系统未接入真实扫码枪但提供了键盘模拟方案在inventory_check.jsp页面光标聚焦于“扫描框”时按CtrlShiftS会自动填充预设商品编码CP001粉底液。原理是页面加载时绑定事件// inventory_check.jsp 中的 JS 片段 document.addEventListener(keydown, function(e) { if (e.ctrlKey e.shiftKey e.key S) { e.preventDefault(); document.getElementById(scanInput).value CP001; // 触发后续 AJAX 查询商品信息 queryGoodsInfo(CP001); } });queryGoodsInfo()函数通过 AJAX 调用servlet/GoodsQueryServlet返回 JSON 格式商品信息名称、规格、当前库存动态填入页面表格。这比纯 JSP 刷新更接近真实扫码体验且避免了频繁页面跳转。3.3 效期预警JSP EL 表达式如何驱动动态 CSS 样式在stock_list.jsp的库存列表中效期列使用 EL 表达式计算剩余天数并变色td c:choose c:when test${(item.expireDate.time - nowTime) / (1000 * 60 * 60 * 24) 60} span stylecolor:red;font-weight:bold; ${fn:substring(item.expireDate, 0, 10)}c:out value${(item.expireDate.time - nowTime) / (1000 * 60 * 60 * 24)}/天 /span /c:when c:otherwise c:out value${fn:substring(item.expireDate, 0, 10)}/ /c:otherwise /c:choose /td参数说明nowTime是 JSP 页面顶部用% request.setAttribute(nowTime, System.currentTimeMillis()); %注入的当前时间戳item.expireDate是java.util.Date对象除法运算得出剩余天数小于 60 天则标红加粗。这种写法避免了在 Servlet 层做日期计算减轻后端压力。3.4 报表导出JSP 如何生成 Excel 而不依赖 Apache POI系统用最简方案实现报表导出report_export.jsp页面通过response.setContentType(application/vnd.ms-excel)设置响应头直接输出 HTML 表格浏览器自动识别为 Excel% response.setContentType(application/vnd.ms-excel); response.setHeader(Content-Disposition, attachment; filenamestock_report_ new SimpleDateFormat(yyyyMMdd).format(new Date()) .xls); % table border1 trth商品编码/thth商品名称/thth当前库存/thth库位/th/tr c:forEach items${stockList} varitem tr td${item.goodsCode}/td td${item.goodsName}/td td${item.qty}/td td${item.location}/td /tr /c:forEach /table避坑点必须确保table标签外无任何空格或换行否则 Excel 打开提示“文件格式损坏”。导出前用response.reset()清空缓冲区防止中文乱码。4. 避坑指南MyEclipse JSP 开发中 5 个血泪经验总结4.1 现象登录成功后跳转到http://localhost:8081/stock/index.jsp但页面显示 404原因web.xml中welcome-file-list未配置index.jsp且 MyEclipse 未将WebRoot设为默认 Web Root。解决在web.xml的web-app标签下添加welcome-file-list welcome-fileindex.jsp/welcome-file /welcome-file-list并在 MyEclipse 中右键项目 →Properties→MyEclipse→Web→ 将Web Root Folder改为WebRoot。4.2 现象JSP 页面中文显示为??数据库存的也是乱码原因MySQL 连接 URL 缺少字符集参数且 JSP 页面未声明 UTF-8。解决修改DBUtil.java中的连接字符串private static final String URL jdbc:mysql://localhost:3306/stock_db?useUnicodetruecharacterEncodingutf8mb4serverTimezoneGMT%2B8;并在所有 JSP 顶部添加% page contentTypetext/html;charsetUTF-8 languagejava %4.3 现象点击“出库”按钮控制台报错java.lang.ClassNotFoundException: com.mysql.jdbc.Driver原因MyEclipse 8.6 默认不包含 MySQL 驱动需手动添加mysql-connector-java-5.1.47.jar项目包lib目录下有。解决右键项目 →Build Path→Add External Archives→ 选择lib/mysql-connector-java-5.1.47.jar→ 确认后右键 JAR 文件 →Build Path→Add to Build Path。4.4 现象stock_in.jsp提交后库存表stock_current数据未更新但入库单已生成原因StockInServlet.java中UPDATESQL 的WHERE条件写错误用goods_name而非goods_code。解决检查StockInServlet.java第 127 行以项目包内代码为准// 错误写法会导致 WHERE 匹配不到 String updateSql UPDATE stock_current SET qty qty ? WHERE goods_name ?; // 正确写法用主键字段 String updateSql UPDATE stock_current SET qty qty ? WHERE goods_code ?;4.5 现象Tomcat 启动后控制台报SEVERE: Error listenerStart项目无法访问原因web.xml中listener配置了ContextLoaderListener但项目未引入 Spring 框架 JAR。解决删除web.xml中以下两行项目本就不含 Springlistener listener-classorg.springframework.web.context.ContextLoaderListener/listener-class /listener5. 毕业答辩前 48 小时一套可演示、可讲解、可扩展的实战技巧5.1 演示脚本设计用 3 分钟讲清“为什么选 JSP 而不是 Vue”答辩时导师常问“现在都用前后端分离为什么还用 JSP” 别背概念用系统里的一个细节回答打开stock_list.jsp找到库存列表的“操作”列里面有“编辑”和“删除”按钮。点击“编辑”弹出模态框里面商品名称、规格、单位都是input typetext且value属性直接绑定 EL 表达式${item.goodsName}。这时说“老师您看这个value${item.goodsName}它不是前端 JS 拼接的字符串而是 JSP 在服务器端渲染时从stock_current表查出数据后直接注入 HTML 的。这意味着——所有敏感操作如库存修改都在服务端完成校验前端只是展示层没有 API 接口暴露风险。对于化妆品仓储这种强事务场景JSP 的服务端渲染反而比前端调 API 更安全、更可控。” 然后现场点击“编辑” → 修改数量 → 提交 → 刷新列表库存实时变化。这比讲 MVC 模式管用十倍。5.2 数据伪造技巧用 SQL 快速生成 100 条测试数据答辩需要演示高并发场景别手动录。在 MySQL 中执行以下脚本10 秒生成 100 条不同批次、不同效期的入库记录-- 生成 100 条入库单含明细 DELIMITER $$ CREATE PROCEDURE GenerateTestData() BEGIN DECLARE i INT DEFAULT 1; WHILE i 100 DO INSERT INTO stock_in_header (in_no, in_date, operator) VALUES (CONCAT(IN, LPAD(i, 6, 0)), DATE_SUB(NOW(), INTERVAL FLOOR(RAND()*30) DAY), TEST); INSERT INTO stock_in_detail (in_no, goods_code, qty, batch_no, expire_date) VALUES ( CONCAT(IN, LPAD(i, 6, 0)), (SELECT goods_code FROM goods_info ORDER BY RAND() LIMIT 1), FLOOR(10 RAND()*90), CONCAT(BATCH, LPAD(i, 4, 0)), DATE_ADD(NOW(), INTERVAL FLOOR(365 RAND()*730) DAY) ); SET i i 1; END WHILE; END$$ DELIMITER ; CALL GenerateTestData(); -- 更新库存表 UPDATE stock_current sc JOIN ( SELECT goods_code, SUM(qty) as total_qty FROM stock_in_detail GROUP BY goods_code ) t ON sc.goods_code t.goods_code SET sc.qty sc.qty t.total_qty;参数说明FLOOR(RAND()*30) DAY随机生成 30 天内的入库日期DATE_ADD(NOW(), INTERVAL FLOOR(365 RAND()*730) DAY)生成 1-3 年后的效期LPAD(i, 6, 0)保证单号格式为IN000001。5.3 拓展接口预留如何在 1 小时内接入微信扫码登录系统login.jsp的表单提交地址是servlet/LoginServlet但LoginServlet.java里留了扩展钩子// LoginServlet.java 第 45 行 if (wechat.equals(request.getParameter(loginType))) { // TODO: 微信授权回调处理 response.sendRedirect(wechat_callback.jsp); } else { // 原有账号密码登录逻辑 }要接入微信只需三步在wechat_callback.jsp中用request.getParameter(code)获取微信授权码调用微信 OAuth2 接口https://api.weixin.qq.com/sns/oauth2/access_token?appidAPPIDsecretAPPSECRETcodeCODEgrant_typeauthorization_code解析返回 JSON提取openid查user表是否存在该 openid存在则登录不存在则跳转注册页关键点微信appid和secret存在config.properties文件中避免硬编码所有微信相关跳转 URL 必须在微信公众号后台配置为白名单。从那以后我每次做毕设演示都强制走一遍“先清空数据库 → 执行测试数据脚本 → 录入一条真实出库单 → 截图库存变化 → 导出 Excel 报表”这个闭环。不是为了炫技而是确保答辩时哪怕导师突然拔网线我也能指着控制台日志说“您看这条 UPDATE 语句执行成功事务已提交数据一致性有保障。” 希望帮到你。本文还有配套的精品资源点击获取