☰
Java进销存管理系统JSP+MSSQL源码:从环境搭建到二次开发全指南
2026/9/29 13:53:28 网站建设 项目流程

简介:这是一套面向高校计算机专业学生与Java Web初学者的进销存管理系统毕业设计资料,基于JSP表现层与MSSQL数据库构建,采用表现层、业务逻辑层、数据访问层的三层架构,通过JDBC完成数据交互。系统覆盖商品管理、供应商管理、进货与销售管理、库存预警及报表分析等核心模块,可作为课程设计、毕设选题或Java Web入门练手项目。压缩包共163个文件,约1.7MB,以105个class编译文件与31个java源码为主,另含jar依赖、png界面截图、mdf与ldf数据库文件及doc设计文档,便于直接部署运行与阅读源码。目前已有248人学习下载。读者可从中获得完整可运行的工程代码、数据库文件与毕业设计文档,理解JSP页面、Servlet与JavaBean如何协同处理前端请求与后端业务,并掌握JDBC操作MSSQL实现增删改查的完整流程,为后续Java编程与数据库管理能力提升提供实践参考。

1. 从一份 JSP+MSSQL 进销存源码说起:它到底能跑通什么

如果你手头正好有一份「java进销存管理系统的设计与实现(jsp+mssql)包含源代码+毕设.zip」,大概率是这几种情况之一:课程设计要交、毕设要过、或者想拿一套能跑的传统 JavaWeb 项目练手。这套东西的技术栈很明确——JSP 做页面、Servlet/JavaBean 做业务、MSSQL 做数据存储,属于典型的「传统 JSP 项目」形态,不是 Spring Boot 那一套。它的价值不在于架构多先进,而在于流程完整:商品、供应商、客户、采购、销售、库存、报表这几条主线基本都覆盖了,拿来改改就能当自己的东西交上去。

适合谁?一是 JavaWeb 入门阶段、需要一套能跑通的完整案例的人;二是要做「基于 JSP 的毕设选题」、缺一个可演示系统的人;三是想复习 JSP+JDBC+SQL Server 这套老组合的从业者。不适合谁?想学微服务、前后端分离、或者指望直接上生产的人——这套代码的定位就是教学和毕设,别拿生产标准去要求它。下面我按「先跑起来、再拆结构、最后避坑」的顺序,把这份资源怎么落地讲清楚。

2. 环境搭建与数据库还原:让项目先跑起来

2.1 技术栈选型与运行环境确认

这套项目是传统 JSP 项目,不是 Maven 工程,所以别指望mvn spring-boot:run一把梭。你需要的是:JDK(建议 8,别上 17,老 JSP 项目对高版本兼容性差)、Tomcat(7 或 8.5 都行,9 也能跑但要注意 Servlet 版本)、SQL Server(2008 R2 到 2019 都可以,看你机器)、以及一个能改编码的 IDE(IDEA 或 Eclipse 都行,IDEA 新建 JSP 项目更顺手)。

为什么强调 JDK 8?因为这类毕设代码里大量用了javax.servlet.*,JDK 高版本配合 Tomcat 10 会变成jakarta.servlet.*,包名对不上直接编译报错。这是新手最容易翻车的地方——代码没错,环境错了。

数据库方面,MSSQL 的还原比 MySQL 麻烦一点,因为涉及.mdf/.ldf附加或者.bak还原。常见做法是:拿到.bak文件后,在 SSMS 里右键「数据库」→「还原数据库」→ 选择源设备 → 指定.bak路径 → 改目标数据库名 → 确定。如果只有.mdf和.ldf,就用「附加」方式,但要注意文件权限,Linux 下用命令登录 MSSQL 再查库会方便些:

# Linux 下用 sqlcmd 登录 MSSQL 并查看数据库列表 /opt/mssql-tools/bin/sqlcmd -S localhost -U sa -P 'YourPassword' # 进入交互后执行 SELECT name FROM sys.databases; GO

这段命令的逻辑是:-S指定服务器地址,-U和-P是账号密码,进去之后用系统视图sys.databases列出所有库,确认你的进销存库有没有还原成功。参数上,如果端口不是默认 1433,要写成localhost,1433这种形式。

2.2 数据库连接配置与项目导入

数据库还原好之后,下一步是改连接配置。这类项目通常不会用连接池框架,而是直接写 JDBC,配置文件可能叫db.properties、DBUtil.java或者干脆硬编码在某个BaseDao里。你要做的是全局搜jdbc:、sa、password这几个关键词,把连接串改成你自己的。

// 典型的 JDBC 连接工具类,注意驱动名和 URL 格式 public class DBUtil { private static final String DRIVER = "com.microsoft.sqlserver.jdbc.SQLServerDriver"; private static final String URL = "jdbc:sqlserver://localhost:1433;databaseName=JXC;encrypt=false"; private static final String USER = "sa"; private static final String PASSWORD = "your_password"; public static Connection getConnection() throws Exception { Class.forName(DRIVER); // 加载驱动,MSSQL 新版驱动必须显式加载 return DriverManager.getConnection(URL, USER, PASSWORD); } }

逻辑说明:Class.forName加载 SQL Server 驱动,DriverManager.getConnection拿连接。参数上,databaseName必须和你还原的库名一致,encrypt=false是给新版驱动加的,老驱动不需要。如果你的驱动是sqljdbc4.jar,URL 里不用encrypt;如果是mssql-jdbc-9.x,不加这个参数会报 SSL 错误。

导入项目时,IDEA 里选「New Project from Existing Sources」,指向源码目录,识别成普通 Java 项目,然后手动把lib下的 jar 加到模块依赖里。Tomcat 配置里注意两点:一是 Deployment 里要加 Artifact,二是 Application context 设成/jxc之类的短路径,别用默认的_war_exploded长串。

2.3 首次启动的验证路径

启动后别急着点所有菜单,按这个顺序验证:先访问登录页,用数据库里user表或admin表的账号登录(密码可能是明文也可能是 MD5,看代码);登录成功后进主页,看左侧菜单能不能加载;然后依次点商品管理、供应商管理,确认列表能查出数据。如果列表空白但数据库有数据,八成是编码问题——JSP 页面pageEncoding和数据库排序规则不一致,中文变问号。

提示:首次跑通之前,先把 Tomcat 日志级别调到 INFO,控制台能看到 SQL 异常堆栈,比在页面上瞎猜快得多。

3. 代码结构拆解:JSP+Servlet+JDBC 三层怎么分工

3.1 目录结构与各层职责

这类项目的目录结构基本固定:src下按包分dao、service、servlet、entity、util;WebContent或web下放jsp页面、css、js、WEB-INF。WEB-INF里的web.xml是 Servlet 映射的核心,老项目可能用注解@WebServlet,也可能全写在web.xml里。

层次包名示例职责常见文件
实体层com.jxc.entity对应数据库表的 JavaBeanProduct.java、Supplier.java
DAO 层com.jxc.dao拼 SQL、执行增删改查ProductDao.java
服务层com.jxc.service业务逻辑、事务控制StockService.java
控制层com.jxc.servlet接收请求、调服务、转发页面ProductServlet.java
视图层/jsp/展示数据、表单提交productList.jsp

理解这张表,你就知道改功能该动哪一层。比如加一个「商品分类」字段,实体加属性、DAO 改 SQL、JSP 加输入框,三处联动,漏一处就报错。

3.2 一个完整的请求链路:以商品列表为例

从浏览器输入/product?action=list开始,Servlet 的doGet拿到action参数,判断走list分支,调ProductDao.findAll(),DAO 里执行SELECT * FROM product,结果集映射成List<Product>,Servlet 把 list 塞进request.setAttribute,然后forward到productList.jsp,JSP 用 JSTL 的<c:forEach>遍历渲染。

// Servlet 中处理列表请求的典型写法 protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String action = request.getParameter("action"); if ("list".equals(action)) { List<Product> list = productDao.findAll(); // 调 DAO 拿数据 request.setAttribute("productList", list); // 存入请求域 request.getRequestDispatcher("/jsp/productList.jsp").forward(request, response); // 转发 } }

逻辑说明:getParameter取 URL 参数,findAll返回集合,setAttribute把数据传给 JSP,forward是服务器内部跳转,URL 不变。参数上,action是这类项目的惯用分发字段,一个 Servlet 处理多个操作。如果你看到response.sendRedirect,那是重定向,URL 会变,数据不共享,别混用。

3.3 库存扣减与事务处理

进销存的核心逻辑在库存:采购入库加库存,销售出库减库存。这部分代码如果写得糙,就会出现「销售单保存了但库存没减」或者「库存减成负数」。合格的写法是在 Service 层开事务,把「插入销售单明细」和「更新库存」放在一个Connection里,要么全成功,要么全回滚。

// Service 层事务控制示例 public boolean addSale(Sale sale, List<SaleItem> items) { Connection conn = null; try { conn = DBUtil.getConnection(); conn.setAutoCommit(false); // 关闭自动提交,开启事务 saleDao.insert(conn, sale); // 插入主单 for (SaleItem item : items) { saleItemDao.insert(conn, item); // 插入明细 stockDao.decrease(conn, item.getProductId(), item.getQty()); // 扣库存 } conn.commit(); // 全部成功才提交 return true; } catch (Exception e) { try { if (conn != null) conn.rollback(); } catch (SQLException ex) { ex.printStackTrace(); } return false; } finally { try { if (conn != null) conn.close(); } catch (SQLException ex) { ex.printStackTrace(); } } }

逻辑说明:setAutoCommit(false)是事务的起点,所有 DAO 方法必须接收同一个conn,否则事务不生效。commit提交,rollback回滚。参数上,decrease方法里最好加WHERE stock >= ?条件,防止超卖。这段代码是判断一套进销存是否「能用」的分水岭——没有事务的版本,数据一致性全靠运气。

4. 避坑与常见问题排查:血泪经验五条

4.1 中文乱码:页面、数据库、连接串三处都要管

现象:商品名称存进去变成???,或者页面显示乱码。原因:JSP 的pageEncoding、数据库字段排序规则、JDBC URL 编码三者不一致。解决:JSP 顶部写<%@ page contentType="text/html;charset=UTF-8" pageEncoding="UTF-8" %>,数据库字段用nvarchar而不是varchar,JDBC URL 加;sendStringParametersAsUnicode=true。三处对齐,乱码基本消失。

4.2 驱动版本不匹配:ClassNotFound 或 SSL 报错

现象:启动报ClassNotFoundException: com.microsoft.sqlserver.jdbc.SQLServerDriver,或者连接时报 SSL 握手失败。原因:用了老版sqljdbc.jar或新版驱动没加encrypt=false。解决:统一换成mssql-jdbc-9.4.1.jre8.jar,URL 里加encrypt=false;trustServerCertificate=true。别在 lib 里同时放两个版本的驱动,冲突起来很难查。

4.3 Tomcat 部署后 404:路径和 Artifact 没对上

现象:IDEA 里跑正常,导出 war 丢到 Tomcat 就 404。原因:web.xml里的url-pattern和访问路径不一致,或者 war 包名和 context 不匹配。解决:访问时带上 war 包名,比如http://localhost:8080/jxc/login.jsp。传统 JSP 项目打包 war 时,确认WEB-INF/lib下所有 jar 都打进去了,漏一个就报类找不到。

4.4 库存对不上:事务没生效或并发没锁

现象:销售单保存成功,但库存没变,或者两个操作同时扣减导致负数。原因:DAO 各自拿连接,事务没串起来;或者UPDATE没加条件。解决:Service 层统一传conn,UPDATE stock SET qty = qty - ? WHERE product_id = ? AND qty >= ?,用返回的影响行数判断是否成功。这是「java怎么保证数据一致性」在传统项目里最朴素的答案。

4.5 登录后跳转空白:session 丢失或转发路径错

现象:登录成功但主页空白,或者刷新后又要重新登录。原因:session没设或超时时间太短;forward路径写成相对路径导致找不到 JSP。解决:登录成功后request.getSession().setAttribute("user", user),转发用/jsp/main.jsp这种以/开头的绝对路径。检查web.xml里<session-config>的session-timeout,默认 30 分钟够用。

5. 二次开发与毕设加分:从能跑到能讲

5.1 改造方向:报表导出与图表展示

一套裸的进销存只能算及格,想拿高分得加东西。最常见的加分项是报表导出——用 Java POI 把销售明细导成 Excel。很多人问「java poi word能生成图表吗」,答案是 POI 对 Word 图表支持有限,但 Excel 图表可以,不过毕设里更稳的做法是导出数据后用 ECharts 在前端画。后端只负责把 JSON 吐出来。

// 用 POI 导出销售明细到 Excel 的核心片段 XSSFWorkbook workbook = new XSSFWorkbook(); XSSFSheet sheet = workbook.createSheet("销售明细"); String[] headers = {"单号", "商品", "数量", "金额", "日期"}; Row headerRow = sheet.createRow(0); for (int i = 0; i < headers.length; i++) { headerRow.createCell(i).setCellValue(headers[i]); // 写表头 } int rowNum = 1; for (SaleItem item : items) { Row row = sheet.createRow(rowNum++); row.createCell(0).setCellValue(item.getSaleNo()); row.createCell(1).setCellValue(item.getProductName()); row.createCell(2).setCellValue(item.getQty()); row.createCell(3).setCellValue(item.getAmount().doubleValue()); row.createCell(4).setCellValue(item.getSaleDate().toString()); } FileOutputStream fos = new FileOutputStream("d:/sale_report.xlsx"); workbook.write(fos); // 写出文件 fos.close(); workbook.close();

逻辑说明:XSSFWorkbook对应.xlsx格式,createSheet建表,createRow建行,createCell建单元格。参数上,setCellValue重载了多种类型,数字用double,日期建议先格式化成字符串避免格式错乱。这段代码放在 Servlet 里,前端一个<a>链接触发下载即可。

5.2 验证方法:怎么确认你的改动没破坏原有逻辑

改完代码别只看新功能,要回归。我的习惯是:先跑一遍采购入库→库存增加→销售出库→库存减少→报表数字对得上,这条主链路走通,基本盘就稳了。然后查数据库,看stock表的数量和sale_item的汇总是否一致。最后看异常日志,有没有吞掉的SQLException。

注意:改 DAO 层 SQL 时,先在 SSMS 里把 SQL 单独跑一遍,确认语法和结果正确,再贴回 Java 代码。直接改 Java 再启动调试,效率低一半。

5.3 毕设答辩时怎么讲这套系统

答辩老师不会关心你用了多新的框架,他们关心的是:数据一致性怎么保证的、事务边界在哪、有没有并发问题、报表数据怎么来的。你就按第 3 章的事务那段讲,把setAutoCommit(false)和rollback说清楚,再补一句「库存扣减用了条件更新防止超卖」,基本就稳了。如果被问到「为什么不用 Spring」,就答「课程设计聚焦 JavaWeb 基础,用原生 JDBC 更能体现对底层流程的掌握」——这话不虚,也是事实。

从那以后我每次拿到这类传统 JSP 项目,都强制先跑通「登录→列表→新增→库存变动」这条最小闭环,再动任何一行代码。希望帮到你。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询