ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

SSM+JSP超市进销存系统:从原理剖析到环境部署避坑指南

SSM+JSP超市进销存系统:从原理剖析到环境部署避坑指南 简介面向毕业设计与超市管理场景的进销存管理系统采用Java语言开发基于Spring、SpringMVC、MyBatis整合框架搭配MySQL数据库以B/S结构实现。系统划分管理员、员工、前台三类角色管理员可管理用户、员工、商品分类、商品信息、商品维护、入库出库记录、销售统计、留言板及订单员工处理商品与出入库记录前台首页提供商品浏览、新闻资讯、留言反馈与购物入口覆盖超市进销存的完整业务链路。压缩包内共1390个文件以JSP动态页面、Java业务源码、JavaScript脚本、CSS样式表为主辅以PNG/GIF图片、XML配置文件、SQL数据库脚本、Word论文和PPT答辩材料整体约31.22MB目录结构清晰便于定位代码与文档。已有110人学习下载适合需要完成毕业设计或课程设计的计算机专业学生可参考其多角色权限设计、进销存流程实现及SSM整合思路。1. 从课设到简历为什么一套 SSMJSP 的超市进销存管理系统到今天还有人做每年临近毕业季「基于 SSMJSP 的 XX 超市进销存管理系统」都是 Java 方向课程设计和毕业设计里出现频率极高的选题。家百利超市进销存管理系统就是这类项目的典型代表技术栈固定为 Spring SpringMVC MyBatis页面层用 JSP业务范围圈定在超市的进货、销售和库存管理三条主线上。很多同学觉得这套技术栈「老」但恰恰是这种老而稳的组合把 Java Web 开发里最核心的东西——对象管理、请求流转、SQL 操作、事务控制——完整地串了一遍。这套系统解决的不是什么高并发难题而是让中小型超市的进销存数据从 Excel 表格和手写单据变成能对得上账的数据库记录。适合正在做毕设或课设的学生也适合想快速补一套完整 SSM 项目经验的初级工程师照着源码捋一遍业务闭环。2. 技术选型拆解SSMJSP 这套组合的边界与合理性2.1 三个框架的分工Spring 管对象、SpringMVC 管请求、MyBatis 管 SQL在做任何一个 SSM 项目之前先把三个框架的边界画清楚后面读源码才不会迷路。Spring 负责对象管理也就是把 Service、Mapper 这些类交给容器统一创建和注入同时承担事务管理和 AOP 切面SpringMVC 负责请求分发从浏览器进来的 URL 经过 DispatcherServlet 找到对应的 Controller 方法再返回视图或数据MyBatis 负责数据库访问把 SQL 写在 XML 映射文件或注解里返回的对象自动映射成 Java 实体。三者各管一段出了问题排查范围天然被切开了。在源码工程里这三个框架的协作关系可以从两个配置文件里看出来。一个典型的 Spring 配置片段长这样!-- 开启注解扫描Controller 之外的所有 Bean 都从这里注册 -- context:component-scan base-packagecom.jiabaili.service / context:component-scan base-packagecom.jiabaili.dao / !-- 数据源配置驱动、地址、账号、密码 -- bean iddataSource classorg.springframework.jdbc.datasource.DriverManagerDataSource property namedriverClassName valuecom.mysql.jdbc.Driver / property nameurl valuejdbc:mysql://localhost:3306/jbl_supermarket?characterEncodingutf8 / property nameusername valueroot / property namepassword value123456 / /bean !-- 把数据源交给 MyBatis 的 SqlSessionFactory -- bean idsqlSessionFactory classorg.mybatis.spring.SqlSessionFactoryBean property namedataSource refdataSource / property namemapperLocations valueclasspath:com/jiabaili/mapper/*.xml / /bean !-- 扫描 Mapper 接口动态生成实现类 -- bean classorg.mybatis.spring.mapper.MapperScannerConfigurer property namebasePackage valuecom.jiabaili.dao / /bean这段配置的逻辑是先扫描 Service 和 DAO 接口再把数据源注入 MyBatis 的会话工厂最后通过 MapperScannerConfigurer 把 DAO 接口和 XML 里的 SQL 绑定起来。参数里有三个地方需要根据实际环境改数据库地址、账号密码、mapper XML 的扫描路径。不少源码工程的坑就出在 mapperLocations 的路径写错导致启动时报Invalid bound statement (not found)。这个报错的意思是接口方法找到了但对应的 SQL 没加载进来优先检查路径和 XML 文件名是否和接口名一一对应。2.2 JSP 不过时只是被用错了地方页面层为什么不适合无脑前后端分离近几年前后端分离成了默认姿势但 SSMJSP 这套组合并没有被淘汰。JSP 的核心优势是服务端渲染Java 代码和 HTML 可以混编数据从 Controller 塞进 Model 之后直接在页面上用 EL 表达式和 JSTL 标签取出来不需要额外起 Node.js 服务也不需要解决跨域问题。对于超市进销存这种以表单和表格为主的后台管理系统页面交互不复杂JSP 的开发效率反而高于 VueAxios 那一套。看一下源码里典型的进货单 JSP 页面片段感受一下数据是怎么从后端流到页面的% page contentTypetext/html;charsetUTF-8 languagejava % % taglib prefixc urihttp://java.sun.com/jsp/jstl/core % html head title进货单列表/title /head body table border1 tr th进货单号/th th供应商/th th进货日期/th th总金额/th /tr c:forEach items${purchaseList} varpurchase tr td${purchase.purchaseNo}/td td${purchase.supplierName}/td td${purchase.purchaseDate}/td td${purchase.totalAmount}/td /tr /c:forEach /table /body /html这里最需要注意的是${purchase.purchaseNo}这种 EL 表达式它背后对应的是 Purchase 实体类的getPurchaseNo()方法。如果实体类没有生成 getter页面上会直接空白而且不报错。新手最容易在这里翻车MySQL 里字段是purchase_noJava 实体属性是purchaseNoMyBatis 开启了驼峰映射就能对上没开启就要在 XML 里写resultMap做手动映射。JSP 页面取值取不到的时候先回 Mapper XML 里看 resultMap 或 resultType 配的是什么再回实体类里看 getter 是否存在不要第一反应去改页面。2.3 源码工程的目录结构三个包和一个 resources 目录拿到家百利进销存系统的源码工程第一件事不是急着运行而是先看目录结构。传统的 SSM 项目按 MVC 分层源码里一般会有一个顶级包名比如com.jiabaili下面按 controller、service、dao、entity 四个子包组织。entity 里放和数据库表对应的实体类dao 里写接口service 里写业务逻辑controller 里写请求映射。resources 目录下放着 Spring 配置文件、MyBatis 映射文件和 MyBatis 全局配置。src/main/java/com/jiabaili/ ├── controller/ # 页面跳转和请求参数接收 │ ├── LoginController.java │ ├── PurchaseController.java │ └── SaleController.java ├── service/ # 业务逻辑层事务边界在这里 │ ├── PurchaseService.java │ └── SaleService.java ├── dao/ # MyBatis Mapper 接口 │ ├── PurchaseDao.java │ └── SaleDao.java └── entity/ # 数据库表对应的实体 ├── Purchase.java └── Product.java src/main/resources/ ├── spring/ # Spring 和 SpringMVC 配置文件 ├── mapper/ # MyBatis 的 XML 映射文件 └── mybatis-config.xml # MyBatis 全局配置拿到源码先核对这个结构。很多从网盘下载的源码工程包名和实际目录对不上或者少了 mapper 文件夹运行起来全是「找不到符号」。我一般会先全局搜索RequestMapping把所有 Controller 里的 URL 路径列出来和数据库表名对照一遍就能大概猜出这个系统的功能模块划分。超市进销存系统的功能通常围绕六个模块转登录、商品管理、供应商管理、进货管理、销售管理、库存查询源码里的 Controller 类基本和这六个模块一一对应。3. 数据库设计与业务闭环进销存的核心不只是三张表3.1 七张核心表从商品表到库存流水表的设计逻辑进销存系统听起来就是「进货、卖货、查库存」但表结构不能只设计三张表。如果进货单和销售单不拆主表和明细表一条进货记录里多个商品就无法存储如果库存只存当前数量不记录每次变动出了问题根本没法追溯。常见的做法是设计七张表商品表、供应商表、进货单表、进货明细表、销售单表、销售明细表、库存表。有的系统还会加一张库存流水表每次入库出库都追加一条记录。表名核心字段作用t_productid, product_no, product_name, spec, unit, price商品主数据t_supplierid, supplier_name, contact, phone, address供应商档案t_purchaseid, purchase_no, supplier_id, purchase_date, total_amount, operator进货单主表t_purchase_itemid, purchase_id, product_id, quantity, price, amount进货单明细t_saleid, sale_no, sale_date, total_amount, operator销售单主表t_sale_itemid, sale_id, product_id, quantity, price, amount销售单明细t_stockid, product_id, quantity, last_update_time实时库存两个主表各自挂一个明细表这是进销存系统里最核心的表结构设计。主表存一笔单据的公共信息单号、日期、总金额、操作人明细表存这一笔单据里每个商品的数量和金额。以进货为例一次采购 10 种商品t_purchase 表只多一条记录而 t_purchase_item 表多 10 条。这样设计的好处是两个维度都能查按单号查整个进货批次按商品查这个商品在不同批次里的进货价。3.2 一次进货动作背后的三次写操作事务边界的经典示范看一个进销存系统的源码质量最有效的办法是看进货逻辑的 Service 实现。一次进货不是单纯的 insert而是三个动作往进货主表和明细表插入单据数据同时还要更新库存表里的商品数量。这三个动作必须在一个数据库事务里任何一个失败都要全部回滚。下面是一个简化版的进货 Service 代码Service public class PurchaseService { Autowired private PurchaseDao purchaseDao; Autowired private PurchaseItemDao purchaseItemDao; Autowired private StockDao stockDao; Transactional(rollbackFor Exception.class) public void addPurchase(Purchase purchase, ListPurchaseItem items) { // 动作一插入进货单主表返回主键 ID purchaseDao.insertPurchase(purchase); // 动作二遍历明细列表逐条插入进货明细表 for (PurchaseItem item : items) { item.setPurchaseId(purchase.getId()); purchaseItemDao.insertItem(item); // 动作三更新库存表商品存在则加数量不存在则插入 int affected stockDao.increaseStock(item.getProductId(), item.getQuantity()); if (affected 0) { Stock stock new Stock(); stock.setProductId(item.getProductId()); stock.setQuantity(item.getQuantity()); stockDao.insertStock(stock); } } } }这段代码值得注意的地方有两个。第一是Transactional(rollbackFor Exception.class)这个参数不是默认值——Spring 的事务默认只在抛出 RuntimeException 时回滚如果业务代码抛的是自定义的 checked exception不指定 rollbackFor 的话库存已经更新了但单据没插进去数据就永远对不上了。第二是increaseStock返回受影响行数的写法用affected 0来判断是更新还是插入本质上是一个简单的「有则改、无则加」逻辑。这个写法在并发场景下会有问题但对于课设和中小型超市的并发量来说足够了。3.3 论文里的 E-R 图和数据字典和代码怎么对照着写这套源码附带的论文里数据库设计章节一般是重头戏E-R 图和数据字典加起来能占去十几页。写论文时有一个常见误区E-R 图画得很大很全但和数据字典里的字段对不上或者数据字典里的表和代码里的建表 SQL 不一致。拿到源码后我建议把三样东西放在一起核对——论文中的 E-R 图、数据字典、resources 目录下的建表 SQL 文件。很多版本的源码里论文里写了 12 张表实际 SQL 脚本只建了 7 张写着写着功能就缺了。数据字典的写法也有套路每张表一个表格字段名、数据类型、是否主键、是否为空、默认值、说明。写的时候不要照抄字段名就完事要把业务含义写清楚。比如 t_stock 表的quantity字段说明不能只写「数量」应该写「当前实时库存数量每次入库加、出库减由 Service 层事务保证一致性」。论文答辩时老师喜欢追问的就是这种细节——「你这个库存表的更新策略是什么」「进货单删除的时候库存要不要回滚」回答得上来说明系统真的是你写的回答不上来代码是不是自己写的就不好说了。4. 在本地跑通源码环境版本组合、配置修改和启动步骤4.1 版本组合把 JDK、Tomcat、MySQL、Maven 的兼容矩阵先定下来SSMJSP 项目最容易翻车的地方不在代码而在环境。网上流传的源码工程很多是在不同版本的 JDK、Tomcat、MySQL 下写的直接拿自己机器上最新的环境去跑经常出现各种玄学报错。先给一组经过验证的兼容组合JDK 1.8、Tomcat 8.5、MySQL 5.7、Maven 3.6.3。这套组合和绝大部分 SSMJSP 课设源码的编写环境一致也是我建议优先尝试的组合。组件推荐版本说明JDK1.8SSM 项目基本都在 Java 8 上开发避免直接用 JDK 11Tomcat8.5支持 JSP 2.3 和 Servlet 3.1兼容性最好MySQL5.75.x 版本对 JDBC 驱动的兼容性比 8.x 省心Maven3.6.3依赖管理用3.8 有时会因中央仓库策略报错JDK 和 Maven 的环境变量配置是老生常谈但要检查是否真的生效可以在命令行执行java -version和mvn -v确认输出的版本号不是系统预装的其他版本。MySQL 要注意 root 账号的密码是否和源码里的jdbc.properties配置一致这是连接失败的第一大原因。另外不建议一上来就用最新的 MySQL 8.0 和 Tomcat 10——Tomcat 10 的包名从javax.servlet改成了jakarta.servlet老 SSM 项目里的javax导入全会报 ClassNotFoundException不是改一行配置能解决的。4.2 从导入到启动的七步操作以命令行方式跑通整个工程拿到源码后按下面这几步操作能避开大多数坑。先检查 JDK 和 Maven 版本再导入数据库脚本然后修改三个配置文件最后启动 Tomcat。我用命令行的方式来写因为很多网上下的源码工程并不带 IDE 配置直接用 Maven 命令验证最靠谱。# 第一步确认 JDK 版本 java -version # 期望看到 1.8 字样 # 第二步确认 Maven 版本 mvn -v # 期望看到 Apache Maven 3.x # 第三步创建数据库并导入 SQL 脚本 mysql -u root -p # 在 MySQL 里执行CREATE DATABASE jbl_supermarket DEFAULT CHARSET utf8mb4; # 然后退出 mysql 命令行回到系统命令行执行下面这行 mysql -u root -p jbl_supermarket sql/jbl_supermarket.sql # 第四步编译并打包工程 mvn clean package -DskipTests # 看到 BUILD SUCCESS 说明编译通过 # 第五步部署到 Tomcat cp target/jbl-supermarket.war /path/to/tomcat/webapps/ # 第六步启动 Tomcat /path/to/tomcat/bin/startup.sh # 第七步查看启动日志 tail -f /path/to/tomcat/logs/catalina.out # 看到 Deployment of web application archive ... has finished 说明部署成功第三步里的 SQL 脚本是源码自带的建表和初始数据文件一般在项目根目录的sql/或db/文件夹下。导入前先打开看一下确认里面有没有CREATE DATABASE语句——如果有就不需要手动创建数据库直接全量导入即可如果没有就先建库再指定库名导入。第五步里部署 war 包之前我习惯把 Tomcat 的webapps目录下原来自带的ROOT、docs等文件夹清掉避免访问 8080 端口时跳到 Tomcat 默认首页让人误以为项目没部署成功。4.3 三个必须改的配置数据库连接、根路径和字符编码工程跑起来之前有三个配置项要逐个核对。第一个是数据库连接信息通常在src/main/resources下的jdbc.properties里把jdbc.url、jdbc.username、jdbc.password改成自己本机的值。第二个是项目的上下文根路径如果 war 包名是jbl-supermarket访问地址就是http://localhost:8080/jbl-supermarket/登录页面的 URL 如果写死了/login会跳转到 Tomcat 根路径下找不到资源。第三个是字符编码JSP 页面、Servlet 过滤器、数据库连接串三处都要统一成 UTF-8缺一个就会出现中文乱码。!-- web.xml 里配置 Spring MVC 的字符编码过滤器必须在所有过滤器最前面 -- filter filter-nameencodingFilter/filter-name filter-classorg.springframework.web.filter.CharacterEncodingFilter/filter-class init-param param-nameencoding/param-name param-valueUTF-8/param-value /init-param init-param param-nameforceEncoding/param-name param-valuetrue/param-value /init-param /filter filter-mapping filter-nameencodingFilter/filter-name url-pattern/*/url-pattern /filter-mapping这段过滤器的forceEncoding参数很容易被忽略。如果不设成 trueSpring 只会在请求参数里带有编码信息时才会覆盖默认编码设了 true则强制所有请求和响应都使用 UTF-8。很多本地开发环境没问题、部署到服务器就乱码的情况都是因为这台服务器上的容器默认编码不是 UTF-8。把这段配置加进去之后JSP 页面头部的contentTypetext/html;charsetUTF-8和数据库连接串里的characterEncodingutf8三处对齐中文显示问题基本就根治了。5. 避坑指南SSMJSP 项目最容易翻车的 5 个检查点5.1 分页查询失效返回全表数据现象在商品列表页点击第二页结果页面把全部商品一次性列出来了或者点下一页没反应SQL 日志里查出来的数据量是全部记录数。原因SSM 项目里分页通常用 PageHelper 插件但 PageHelper 的版本必须和 MyBatis 版本兼容。另一个常见原因是 MyBatis 全局配置里没有注册 PageHelper 的拦截器导致调用PageHelper.startPage()后没有任何拦截效果。还有一种情况是startPage()后面紧接着的不是第一条查询语句中间多了一条别的 SQLPageHelper 会把分页参数作用到错误的查询上。解决先确认 Maven 依赖里引入的是com.github.pagehelper:pagehelper再在mybatis-config.xml中注册拦截器plugins plugin interceptorcom.github.pagehelper.PageInterceptor property namehelperDialect valuemysql / property namereasonable valuetrue / /plugin /pluginsreasonabletrue这个参数的作用是当页码超出总页数时自动跳到第一页或最后一页而不是报错。排查时还要注意PageHelper.startPage( pageNum, pageSize )后面必须紧跟第一条select查询中间不能有其他 SQL 或逻辑判断。血泪经验是有人在一行日志输出语句放在中间分页就神秘失效了这不是玄学是 PageHelper 基于 ThreadLocal 的实现机制决定的。5.2 中文乱码JSP 页面改了 charset 也没用现象登录后首页全是问号商品名称显示成「???」或者页面能显示中文但插入到数据库里的值变成了乱码。原因乱码的传播链条是「浏览器 → Tomcat → Servlet 过滤器 → 数据库连接 → MySQL 表结构」五个环节。只改 JSP 页面的charsetUTF-8解决的是响应方向的问题请求方向如果 Tomcat 的 URIEncoding 没配置POST 请求体是 UTF-8 但 Tomcat 默认按 ISO-8859-1 解码到 Java 代码里就已经是乱码了。数据库连接串没加characterEncodingutf8从 Java 到 MySQL 也会乱码。解决按顺序检查三处。第一处是jdbc.properties里的连接串确保包含useUnicodetruecharacterEncodingutf8第二处是web.xml里的 CharacterEncodingFilter已在上文给出第三处是 MySQL 建表语句里的字符集如果表结构本身是 latin1代码层全是 UTF-8 也救不回来。检查已存在的表用这条 SQLSHOW TABLE STATUS FROM jbl_supermarket;看到latin1的行执行ALTER TABLE t_product CONVERT TO CHARACTER SET utf8mb4;把整张表转过来。记住一点UTF-8 和 utf8mb4 的差别在于 emoji 和生僻字不要省钱用 utf8直接上 utf8mb4 最稳妥。5.3 Service 层两个数据库操作一个成功一个失败没回滚现象进货时报了「明细不能为空」的异常但重新登录系统发现库存数量已经增加了或者销售单没插入成功库存却被扣减了。原因最常见的两个原因一是Transactional注解加在了类上但类的扫描路径没覆盖到Spring 容器里这个 Service 根本不是一个代理对象二是事务方法内部 catch 了异常并吞掉Spring 感知不到异常就不会回滚。还有一个隐蔽的原因Transactional默认只对 RuntimeException 回滚业务抛出的 checked exception比如自定义的BizException不会触发回滚。解决把注解写成Transactional(rollbackFor Exception.class)并且不要在大事务方法里用 try-catch 吞异常。如果确实需要捕获异常做逻辑处理处理完之后要重新抛出或手动调用TransactionAspectSupport.currentTransactionStatus().setRollbackOnly()。通过 Spring 的声明式事务别自己手动写回滚逻辑那是把简单问题复杂化。5.4 Tomcat 部署后 ClassNotFoundException但 Maven 编译是成功的现象mvn package顺利打出 war 包部署到 Tomcat 后却报ClassNotFoundException: com.mysql.jdbc.Driver或者报找不到某个 Mapper 类。原因Maven 打包时依赖没有打进去或者打进了重复的 jar。SSM 项目要在pom.xml里把 Spring、MyBatis、MySQL 驱动等依赖连同一同打进 war 包如果某个依赖被标记为provided作用域打包时会跳过它。另一个常见情况是 Tomcat 的lib目录里放了一份老版本的 Servlet API和项目里引入的版本冲突。解决在项目根目录执行mvn dependency:tree看 MySQL 驱动和 MyBatis 的依赖树上有没有provided或compile标签。然后在 Tomcat 的webapps目录找到布署的 war 包解压目录进入WEB-INF/lib用ls | grep mysql确认驱动 jar 确实在。不推荐手动往 Tomcatlib目录里扔 jar那样会把所有部署在这个 Tomcat 上的项目都影响属于扩大了排查范围。5.5 JSP 页面上 EL 表达式原样输出取不到值现象页面上显示的是${product.productName}这一串字符串而不是商品名称本身浏览器里查看源码能看到 EL 表达式没被解析。原因JSP 页面的isELIgnored被设成了 true或者 web.xml 的 Servlet 版本声明太低JSP 2.0 以下默认不解析 EL。还有一种情况是 Controller 里往 Model 塞数据的 key 和页面上取的 key 不一致比如 Controller 里写model.addAttribute(productList, ...)页面里取的是product。解决在 JSP 页面头部显式声明% page isELIgnoredfalse %同时检查 web.xml 的命名空间是不是 Servlet 3.0 及以上版本。如果页面确认要使用 JSTL 的${}表达式页面顶部要加上% taglib prefixc urihttp://java.sun.com/jsp/jstl/core %。排查顺序是先看 JSP 顶部有没有声明再看 web.xml 版本最后看 Controller 里的 key 名和页面是否一致。EL 表达式取不到值不像 Java 编译错误有明确报错页面静默空白很多人卡在这里半小时发现只是 key 少写了一个字母。6. 给进销存系统加统计报表从 JSP 表格到可视化图表的升级路径6.1 用 JFreeChart 在服务端生成图片还是前端用 ECharts 拿 JSON 画图进销存系统的论文里通常会提到「统计报表」模块但很多源码实现只是用 JSP 再画一个表格把进货总额、销售总额列出来谈不上可视化。做这个模块的升级时有两种方案。方案一是在 Java 端用 JFreeChart 生成柱状图或饼图图片直接把图片路径塞给 JSP 的img标签展示优点是纯 Java 实现不需要前端引入第三方库但图表交互能力弱调整样式得重新生成图片。方案二是在 Controller 里把统计数据封装成 JSON 返回给 JSPJSP 里用 ECharts 渲染灵活性和美观度都更好。我倾向方案二因为它把前后端职责分得更清楚而且这套 JSON 接口将来改造前后端分离时可以无缝迁移。JSP 页面里只需要加一段 JavaScriptscript src${pageContext.request.contextPath}/static/js/echarts.min.js/script script // 从后端接口取统计数据接口返回 [{name: 牛奶, value: 120}, ...] fetch(${pageContext.request.contextPath}/statistics/saleRank) .then(response response.json()) .then(data { const chart echarts.init(document.getElementById(saleChart)); chart.setOption({ title: { text: 本月商品销量 TOP10 }, tooltip: {}, xAxis: { data: data.map(item item.name) }, yAxis: {}, series: [{ type: bar, data: data.map(item item.value) }] }); }); /script这段代码用 fetch 调后端接口取 JSON然后喂给 ECharts逻辑很直白。需要说明的是Controller 里对应的接口方法要返回ResponseBody并且把统计 SQL 的结果映射成Map或ListMap的格式ECharts 拿到后才能正确渲染。自己动手升级这个模块时重点不在代码本身而是统计口径——销量是按销售明细表的 quantity 汇总销售额是按 amount 汇总两个 SQL 都要GROUP BY product_id后用ORDER BY SUM(...) DESC LIMIT 10控制返回条数。6.2 三个值得动手的改造方向Spring Boot 化、数据权限、缓存如果这套 SSMJSP 系统是用来找工作面试的项目不建议停留在「跑通即可」建议往三个方向动手改一改。第一个方向是 Spring Boot 化把 XML 配置改成application.yml启动方式从 Tomcat 部署变成mvn spring-boot:run这个改造过程能把 Servlet 和 Spring 的底层理解再夯实一遍。第二个方向是数据权限给不同角色的登录用户配置不同的数据范围——普通员工只能看到自己的操作记录店长能看到全店数据这个功能在面试时很加分。第三个方向是首页库存预警加一层缓存把库存低于阈值的商品列表缓存起来改数据库时主动清缓存不涉及 Redis 的话先用ConcurrentHashMap手动实现一个简单的 CacheUtil 类理解清楚缓存穿透和缓存一致性的概念后再上 Redis。我自己做这个课设题目时踩过最深的坑是事务回滚——当时进货单插入成功但明细插入时主键冲突没抛异常导致库存更新了两次。后来养成了一个习惯写完一个涉及多表更新的 Service 方法先故意制造一个错误跑一遍确认数据没变再写正常的业务逻辑。这个习惯帮我避免了好几次线上事故。做课设和毕设也是一样的道理代码跑通只是起点把每个边界情况都验证过一遍答辩时才硬气。希望帮到你。本文还有配套的精品资源点击获取
返回列表