资讯动态

JSP进销存管理系统实战:环境搭建、数据库导入与二次开发指南

发布时间:2026/10/1 12:15:20 来源:尧图企业网站定制
简介这是一套面向Java Web初学者与课程设计开发者的JSP进销存管理系统完整源码包针对商品种类繁多、进货出货与库存管理流程复杂、手工操作易出错等痛点用计算机全程管理进货、销售与库存环节帮助读者理解并实践一套流程清晰的进销存业务系统。压缩包共183个文件约6.68MB以77个jsp页面为主体配合12个java源文件与12个class编译文件、6个jar依赖包另有26个txt说明、4个xml配置及gif、jpg、png等界面素材并附带数据库文件与项目文档结构完整、层次分明。目前已有245人学习下载。读者可从中获得可直接部署运行的源码工程、配套数据库脚本与说明文档借助JSP页面与JavaBean分层设计快速掌握商品、供应商、客户等模块的数据增删改查与库存联动逻辑适合作为毕业设计、课程实训或二次开发的基础模板。1. 拿到一个 jsp 进销存管理系统压缩包先别急着双击运行你从课程设计选题、毕设参考或者二手资源站拿到一个名为「jsp进销存管理系统源码数据库文档.rar」的压缩包解压后大概率看到三个东西一个 Eclipse/IDEA 工程目录、一个.sql数据库脚本、一份 Word 或 PDF 说明文档。很多人第一反应是找index.jsp双击打开然后浏览器报 404 或者一片空白接着就开始怀疑人生。这个标题背后真正要解决的问题不是「怎么打开它」而是「怎么让一套十几年前技术栈的 JavaWeb 项目在你本机的 Tomcat 里跑起来并且能登录、能增删改查」。进销存管理系统本质上是「进货、销售、库存」三条业务线的 CRUD 集合核心表无非是商品表、供应商表、客户表、采购单、销售单、库存流水。JSP 在这里承担的是视图层Servlet 或 JavaBean 承担控制与业务逻辑MySQL 存数据。它适合谁适合正在做 JavaWeb 课程设计、需要一套能跑通、能改、能写进论文的参考实现的人。不适合谁不适合想直接拿它上线做生意的因为这类项目的权限控制、并发扣库存、事务边界通常都很粗糙。下面我按「环境怎么搭 → 数据库怎么导 → 工程怎么配 → 怎么改才不翻车」的顺序把一套可复现的落地路径讲清楚。2. 把 JSP 进销存项目跑起来环境、数据库与工程配置2.1 JDK、Tomcat、MySQL 的版本选择与验证这类老项目的血泪经验第一条就是版本。JSP 进销存管理系统大多基于 Servlet 2.5/3.0 规范配套 JDK 6/7/8Tomcat 6/7/8。你如果直接上 JDK 17 Tomcat 10javax.servlet包名已经变成jakarta.servlet项目里的% page %和web.xml会大面积报错。我一般会这样配组件推荐版本原因JDK1.8兼容javax.servlet编译不报Unsupported class file major versionTomcat8.5.x支持 Servlet 3.1对老web.xml宽容MySQL5.7老项目 SQL 语法多为ENGINEInnoDB DEFAULT CHARSETutf88.0 的caching_sha2_password容易连不上IDEIDEA 或 Eclipse能识别 Web Facet方便配 Artifact验证环境是否就绪用命令行确认不要只信 IDE 的绿勾java -version # 期望输出 java version 1.8.0_xxx mysql --version # 期望输出 mysql Ver 14.14 Distrib 5.7.xx # 启动 Tomcat 后访问 curl -I http://localhost:8080/ # 期望返回 HTTP/1.1 200 或 404说明 Tomcat 活着逻辑说明java -version确认 JDK 主版本mysql --version确认数据库客户端可用curl -I只取响应头避免把 Tomcat 首页整页拉下来。参数上Tomcat 默认端口 8080如果被占用改conf/server.xml里的Connector port8080别去改项目代码里的硬编码端口否则后面部署 war 又会踩坑。2.2 导入 .sql 脚本字符集与建库顺序解压后找到db_xxx.sql或jxc.sql先别直接source。用文本编辑器打开前 50 行确认三件事有没有CREATE DATABASE、有没有USE、字符集是不是utf8。很多脚本只建表不建库你直接导入会报No database selected。# 1. 登录 MySQL mysql -uroot -p # 2. 手动建库字符集必须和脚本一致 CREATE DATABASE jsp_jxc DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci; # 3. 退出后用命令行导入避免 source 路径问题 mysql -uroot -p jsp_jxc /path/to/jxc.sql # 4. 验证表是否进来 mysql -uroot -p -e USE jsp_jxc; SHOW TABLES;逻辑说明第 2 步显式建库是为了控制字符集老脚本里如果写utf8而你建库用utf8mb4某些字段长度会超限。第 3 步用重定向导入比进 MySQL 再source更稳因为source的工作目录是 MySQL 进程的目录不是你的当前目录。参数上utf8_general_ci是排序规则对中文检索够用如果脚本里有 emoji 或生僻字才需要换utf8mb4但老项目基本不会。导入后如果SHOW TABLES少了几张去看导入时的报错行号常见原因是外键依赖顺序先导主表再导从表或者临时SET FOREIGN_KEY_CHECKS0;。2.3 在 IDEA 里配置 Web 工程与数据库连接把工程目录用 IDEA 打开识别为 Maven 或普通 Web 项目。如果是普通项目去File → Project Structure → Modules加 Web Facetweb.xml路径指向src/main/webapp/WEB-INF/web.xmlWeb 资源目录指向src/main/webapp。然后配 ArtifactArtifacts → → Web Application: Exploded → From Modules这样 Tomcat 才能部署。数据库连接通常写在src/db/DBUtil.java或src/com/util/DBHelper.java找DriverManager.getConnection或jdbc:mysql://// 典型的老项目连接代码 public static Connection getConnection() throws Exception { Class.forName(com.mysql.jdbc.Driver); // MySQL 5.7 用这个8.0 要换 com.mysql.cj.jdbc.Driver String url jdbc:mysql://localhost:3306/jsp_jxc?useUnicodetruecharacterEncodingutf8; return DriverManager.getConnection(url, root, 你的密码); }逻辑说明Class.forName是 JDBC 4.0 之前的显式加载驱动写法老项目保留着不写也能跑但会警告。useUnicodetruecharacterEncodingutf8是防止中文乱码的关键少了它商品名里的中文进库变问号。参数上3306是 MySQL 默认端口jsp_jxc换成你实际建的库名。如果报Access denied检查密码如果报Unknown database回 2.2 确认库名如果报Communications link failure看 MySQL 服务是否启动、端口是否被防火墙拦。把改好的连接信息保存然后在 IDEA 里Run → Edit Configurations → → Tomcat Server → LocalDeployment 里加上刚才的 ArtifactApplication context 设成/jxc。启动后访问http://localhost:8080/jxc/应该能看到登录页。默认账号密码通常在文档里或者去user表里看密码可能是明文也可能是 MD5明文就直接用MD5 就去搜一个在线工具反查或者直接改表。3. 进销存核心业务表的字段设计与增删改查落地3.1 商品、供应商、库存三张主表的字段取舍进销存系统的骨架就是几张表。你拿到源码后别急着改页面先把表结构看明白因为后面所有 JSP 页面里的${product.name}这种 EL 表达式都对应表字段。常见设计如下表名关键字段说明productid, name, category, unit, purchase_price, sale_price, stock商品基础信息与当前库存supplierid, name, contact, phone, address供应商信息stock_recordid, product_id, type, quantity, record_time出入库流水type 区分进货/销售这里有个设计边界很多老项目把stock直接放在product表里每次进货销售都UPDATE product SET stock stock ?。这在单机、低并发下没问题但如果你要做「库存不能为负」的校验必须把UPDATE和SELECT放在同一个事务里否则两个销售单同时扣同一商品会超卖。我一般会建议在stock_record里记流水product.stock只作为冗余快照对账时以流水为准。3.2 用 JSP Servlet 写一个商品列表与新增的最小闭环看源码不如自己写一遍。下面是一个最小可运行的商品列表 新增流程你可以对照原项目改。先写 Servlet// ProductServlet.java WebServlet(/product) public class ProductServlet extends HttpServlet { protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String action req.getParameter(action); if (list.equals(action)) { ListProduct list ProductDao.findAll(); // 查全部商品 req.setAttribute(products, list); req.getRequestDispatcher(/product_list.jsp).forward(req, resp); } } protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { req.setCharacterEncoding(UTF-8); // 必须否则中文商品名乱码 String name req.getParameter(name); double price Double.parseDouble(req.getParameter(sale_price)); int stock Integer.parseInt(req.getParameter(stock)); ProductDao.insert(new Product(name, price, stock)); resp.sendRedirect(product?actionlist); // 重定向防止刷新重复提交 } }逻辑说明doGet处理列表查询doPost处理新增。req.setCharacterEncoding(UTF-8)必须放在取参数之前否则 POST 中文乱码。sendRedirect而不是forward是为了避免用户按 F5 重复插入。参数上sale_price用Double.parseDouble如果用户输入非数字会抛NumberFormatException生产环境要 try-catch 并回显错误。对应 JSP 页面% page contentTypetext/html;charsetUTF-8 languagejava % % taglib prefixc urihttp://java.sun.com/jsp/jstl/core % html body table border1 trthID/thth名称/thth售价/thth库存/th/tr c:forEach items${products} varp tr td${p.id}/td td${p.name}/td td${p.salePrice}/td td${p.stock}/td /tr /c:forEach /table form actionproduct methodpost 名称input namenamebr 售价input namesale_pricebr 库存input namestockbr button typesubmit新增/button /form /body /html逻辑说明c:forEach是 JSTL 标签需要jstl.jar和standard.jar在WEB-INF/lib下否则报The absolute uri: http://java.sun.com/jsp/jstl/core cannot be resolved。${p.salePrice}对应 Product 类的 getter 方法名如果类里是getSale_price()EL 要写${p.sale_price}大小写和驼峰必须对上。参数上contentTypetext/html;charsetUTF-8控制响应编码和 Servlet 里的setCharacterEncoding一个管响应一个管请求两个都要。3.3 采购入库与销售出库的事务边界进销存最核心的不是增删改查是「入库加库存、出库减库存」这两步必须原子。老项目常见写法是// 错误示范两条独立 SQL中间可能失败 productDao.updateStock(productId, qty); stockRecordDao.insert(new StockRecord(productId, in, qty));如果第一条成功第二条失败库存加了但没流水对账就成黑匣子。正确做法是包在一个 Connection 事务里Connection conn null; try { conn DBUtil.getConnection(); conn.setAutoCommit(false); // 关闭自动提交 productDao.updateStock(conn, productId, qty); stockRecordDao.insert(conn, new StockRecord(productId, in, qty)); conn.commit(); // 两步都成功才提交 } catch (Exception e) { if (conn ! null) conn.rollback(); // 任一步失败全回滚 throw e; } finally { if (conn ! null) conn.close(); }逻辑说明setAutoCommit(false)开启事务commit提交rollback回滚。参数上conn必须一路传下去不能 DAO 内部各自getConnection否则不在同一个事务里。这是老项目改造时最容易忽略的点很多源码里 DAO 方法无参你需要在方法签名里加Connection conn改动量不小但这是让系统从「能跑」到「能用」的关键一步。4. 部署与排错JSP 进销存项目最常见的 5 个翻车现场4.1 现象访问页面报 404Tomcat 日志无异常原因Application context 配错或者 Artifact 没部署。IDEA 里 Tomcat 的 Deployment 页签如果只有war没有war exploded访问路径会多一层。解决确认 Deployment 里有xxx:war explodedApplication context 填/jxc访问http://localhost:8080/jxc/不要访问http://localhost:8080/。4.2 现象登录后所有中文变问号原因数据库连接串缺characterEncodingutf8或者 JSP 页面pageEncoding没写。解决改DBUtil里的 URL 加useUnicodetruecharacterEncodingutf8每个 JSP 头部加% page contentTypetext/html;charsetUTF-8 pageEncodingUTF-8 %MySQL 建库时确认SHOW CREATE DATABASE jsp_jxc输出是utf8。4.3 现象报java.lang.ClassNotFoundException: com.mysql.jdbc.Driver原因WEB-INF/lib下没有 MySQL 驱动 jar或者驱动版本和 MySQL 不匹配。解决MySQL 5.7 用mysql-connector-java-5.1.x.jar8.0 用mysql-connector-java-8.0.x.jar且驱动类名改com.mysql.cj.jdbc.Driver。把 jar 放进WEB-INF/libIDEA 里Project Structure → Libraries也加上然后重新部署。4.4 现象新增商品后列表不刷新或者刷新后重复插入原因Servlet 里用了forward而不是sendRedirect或者表单提交后直接out.print没跳转。解决POST 处理完统一resp.sendRedirect(product?actionlist)让浏览器发新 GET 请求这样 F5 不会重复提交。4.5 现象库存扣成负数或者两个销售单同时扣同一商品超卖原因UPDATE product SET stock stock - ?没有加WHERE stock ?条件或者没在事务里。解决SQL 改成UPDATE product SET stock stock - ? WHERE id ? AND stock ?根据executeUpdate返回的影响行数判断是否成功返回 0 说明库存不足抛异常回滚。这是进销存系统从「课程设计」到「能演示」的分水岭。5. 从能跑到能改二次开发与文档结构化的实用技巧跑通之后你大概率要改点东西交差。改哪里最划算我一般按「先改页面文案 → 再加一个查询条件 → 最后动业务逻辑」的顺序因为动逻辑最容易引入 bug。比如给商品列表加一个按名称模糊查询只需要在ProductServlet的list分支里加String keyword req.getParameter(keyword); ListProduct list (keyword null || keyword.isEmpty()) ? ProductDao.findAll() : ProductDao.findByNameLike(% keyword %); req.setAttribute(products, list);逻辑说明keyword为空走全量查询不为空走LIKE。参数上%是 SQL 通配符拼在 Java 字符串里传给 DAODAO 里用PreparedStatement的?占位不要直接拼 SQL否则有注入风险。JSP 里加一个input namekeyword和提交按钮即可。再说文档。压缩包里的 Word 文档通常是需求分析和 E-R 图但格式混乱复制到论文里排版会崩。我习惯把文档里的表结构、字段说明、业务流程抽成 Markdown 表格这样版本可控、检索方便。比如把「商品表字段说明」整理成字段类型允许空说明idint(11)否主键自增namevarchar(100)否商品名称stockint(11)否当前库存默认 0这样你在写论文或者给同事交接时直接贴表格比截图 Word 清晰得多。文档结构化解析这个热词落到这里就是把非结构化的 Word 内容转成可检索、可 diff 的文本。最后一个技巧把项目打成 war 包部署到独立 Tomcat而不是一直用 IDEA 内置的。因为 IDEA 内置 Tomcat 的类加载顺序和独立 Tomcat 有差异有些ClassNotFoundException只在独立部署时出现。打包命令# 在项目根目录假设是 Maven 项目 mvn clean package -DskipTests # 产物在 target/xxx.war复制到 Tomcat 的 webapps 下 cp target/jxc.war $TOMCAT_HOME/webapps/ # 启动 Tomcat $TOMCAT_HOME/bin/startup.sh逻辑说明mvn package会编译并打包-DskipTests跳过测试加快速度。war 包放进webapps后 Tomcat 会自动解压部署访问路径是http://localhost:8080/jxc/war 文件名即 context path。参数上$TOMCAT_HOME换成你的实际路径Windows 下用startup.bat。我自己踩过最深的坑是改完 Java 代码只重启 Tomcat 没重新编译结果跑的还是旧 class排查了半天以为是数据库问题。后来养成习惯改完代码先mvn compile或者 IDEA 里Build → Rebuild Project再重启。这个习惯帮我省了至少几十次无谓的排查。希望帮到你。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑