SSM药品售卖系统实战:从环境搭建到下单库存扣减的完整链路

发布时间:2026/10/29 18:02:16
SSM药品售卖系统实战:从环境搭建到下单库存扣减的完整链路 简介本资源是一套基于SSM框架实现的网上药品售卖系统完整项目包面向计算机相关专业学生、Java初学者及需要完成毕业设计或课程设计的人群帮助解决从零搭建电商类Web应用时缺少完整参考案例的问题。压缩包共19.19MB包含项目源码、数据库脚本、答辩PPT与毕业论文等文件源码可直接导入IDEA或Eclipse运行数据库采用MySQL后端基于SpringSpringMVCMyBatisMaven前端使用JSP、CSS与JS技术栈贴合主流企业开发。系统分为管理员与用户两种角色后台涵盖药品分类、药品信息、用户、健康资讯、客服回复、轮播图与订单管理前台支持注册登录、药品推荐与详情、收藏、购物车、立即购买、评论、健康资讯、个人中心、我的订单、地址、收藏、客服及余额充值等功能。已有89人学习适合作为毕设参考或SSM入门练手项目。1. 从一份药品售卖系统源码说起SSM 到底能扛住什么很多 Java 学习者手里都攥着一份「网上药品售卖系统」的源码包SSM 框架、B/S 架构、带数据库脚本和答辩 PPT看起来该有的都有。但真正打开跑一遍十有八九卡在环境配置、依赖冲突或者数据库连不上。问题不在于这份源码有多难而在于大多数人把它当成「下载即用」的成品忽略了 SSM 项目从环境搭建到业务落地的完整链路。这个标题背后真正要解决的问题是如何用 Spring SpringMVC MyBatis 这套经典组合搭出一个能跑通药品浏览、下单、库存扣减、后台管理的 B/S 系统并且理解每一层在干什么。适合正在做课程设计、毕业设计或者想从零手写一个 SSM 项目来巩固 Java Web 基础的开发者。药品售卖这个场景比通用商城更具体——有药品分类、处方药与非处方药的区分、库存批次管理这些业务约束会让你的 SSM 实践比增删改查更有含金量。2. 环境搭建与 SSM 整合从零把架子立起来2.1 为什么选 SSM 而不是 Spring Boot2024 年还在用 SSM 做项目很多人第一反应是「过时了」。但从学习路径看SSM 把 Spring 的 IoC、AOPSpringMVC 的请求映射、参数绑定MyBatis 的 SQL 映射、动态 SQL 全部暴露在你面前没有自动配置帮你兜底。药品售卖系统里药品分类树、订单状态机、库存扣减这些逻辑用 SSM 写一遍你对 Java Web 分层架构的理解会扎实得多。常见做法是 JDK 8 Maven 3.6 Tomcat 8.5 MySQL 5.7这个组合在各类教程和源码包里兼容性最好。如果你用 JDK 17 配 Tomcat 10javax.servlet 包名变成 jakarta.servlet老源码直接编译不过这是第一个翻车点。2.2 Maven 依赖与版本锁定SSM 整合最怕版本打架。Spring 5.3.x 配 MyBatis 3.5.x 是经过大量项目验证的组合别追新。下面是我一般会用的 pom.xml 核心依赖片段!-- Spring 核心 -- dependency groupIdorg.springframework/groupId artifactIdspring-context/artifactId version5.3.30/version /dependency dependency groupIdorg.springframework/groupId artifactIdspring-webmvc/artifactId version5.3.30/version /dependency !-- MyBatis 与 Spring 整合 -- dependency groupIdorg.mybatis/groupId artifactIdmybatis-spring/artifactId version2.1.2/version /dependency dependency groupIdmysql/groupId artifactIdmysql-connector-java/artifactId version8.0.33/version /dependency !-- 连接池 -- dependency groupIdcom.alibaba/groupId artifactIddruid/artifactId version1.2.20/version /dependency逻辑说明spring-webmvc 已经传递依赖了 spring-context 和 spring-web不需要重复声明。mybatis-spring 是 MyBatis 和 Spring 事务管理的桥梁版本必须和 MyBatis 主版本匹配。MySQL 驱动 8.x 对应 com.mysql.cj.jdbc.Driver5.x 对应 com.mysql.jdbc.Driver写错直接报找不到驱动。Druid 连接池在药品系统里有个实际好处它的监控面板能看到慢 SQL库存扣减这种高频操作调优时很有用。2.3 web.xml 与 Spring 配置文件的职责划分SSM 项目通常有三个配置文件applicationContext.xml 管 Service 和 DAO 层spring-mvc.xml 管 Controller 层mybatis-config.xml 管 MyBatis 全局设置。web.xml 里要注册 ContextLoaderListener 加载 applicationContext.xml再注册 DispatcherServlet 加载 spring-mvc.xml。关键点是spring-mvc.xml 只扫描 ControllerapplicationContext.xml 扫描 Service 和 Repository否则事务注解会失效。这个坑我见过太多次——Controller 里调 Service事务死活不回滚就是因为 Service 被 MVC 容器扫描了而 MVC 容器默认不开启事务代理。!-- applicationContext.xml 关键片段 -- context:component-scan base-packagecom.pharmacy context:exclude-filter typeannotation expressionorg.springframework.stereotype.Controller/ /context:component-scan bean idtransactionManager classorg.springframework.jdbc.datasource.DataSourceTransactionManager property namedataSource refdataSource/ /bean tx:annotation-driven transaction-managertransactionManager/参数说明exclude-filter 把 Controller 排除掉让 Controller 只被 spring-mvc.xml 扫描。transactionManager 的 dataSource 必须和 MyBatis 用的是同一个否则事务不生效。tx:annotation-driven 开启 Transactional 注解支持药品下单扣库存的方法上要加这个注解。3. 数据库设计与药品业务建模表结构决定后期改不改得动3.1 药品表、分类表、订单表的核心字段药品售卖系统的数据库设计有几个业务特点药品有批准文号、生产厂家、有效期处方药和非处方药要区分库存要支持批次和效期管理。下面是最小可用的表结构CREATE TABLE drug ( id int NOT NULL AUTO_INCREMENT, drug_name varchar(100) NOT NULL COMMENT 药品名称, drug_code varchar(50) DEFAULT NULL COMMENT 批准文号, category_id int NOT NULL COMMENT 分类ID, price decimal(10,2) NOT NULL, stock int NOT NULL DEFAULT 0, is_prescription tinyint(1) DEFAULT 0 COMMENT 0非处方 1处方, manufacturer varchar(200) DEFAULT NULL, expire_date date DEFAULT NULL, create_time datetime DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (id), KEY idx_category (category_id), KEY idx_name (drug_name) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4;逻辑说明drug_code 存批准文号这是药品唯一标识比自增 ID 更适合做业务查询。is_prescription 用 tinyint 而不是 enumMyBatis 映射到 Java 的 Integer 或 Boolean 都方便。idx_category 和 idx_name 两个索引前者支撑分类浏览后者支撑搜索。utf8mb4 字符集必须显式指定否则药品名里的特殊字符会乱码。3.2 订单与库存的关联设计订单表 order_main 和订单明细 order_detail 是一对多。库存扣减有两种做法下单即扣或者支付后扣。药品系统建议下单即扣因为药品库存通常不多超卖比少卖更麻烦。扣减时用乐观锁UPDATE drug SET stock stock - #{quantity} WHERE id #{drugId} AND stock #{quantity}返回影响行数为 0 就说明库存不足抛异常回滚。这个 SQL 要放在 Service 方法里和插入订单在同一个 Transactional 事务中。注意 MySQL 默认隔离级别是 REPEATABLE READ这个 UPDATE 会加行锁并发下不会超卖。3.3 MyBatis 映射文件与动态 SQL药品列表查询通常带多个筛选条件分类、价格区间、是否处方药、关键词。用 MyBatis 的where和if标签拼动态 SQLselect idselectByCondition resultMapDrugMap SELECT * FROM drug where if testcategoryId ! null AND category_id #{categoryId} /if if testkeyword ! null and keyword ! AND drug_name LIKE CONCAT(%, #{keyword}, %) /if if testisPrescription ! null AND is_prescription #{isPrescription} /if if testminPrice ! null AND price gt; #{minPrice} /if /where ORDER BY create_time DESC LIMIT #{offset}, #{limit} /select参数说明where标签会自动去掉第一个多余的 AND。gt;是 XML 转义直接写在 XML 里会报错。LIMIT 分页参数 offset 和 limit 由 Service 层计算pageNum 从 1 开始时 offset (pageNum - 1) * pageSize。这个查询在药品数量上万时LIKE %keyword% 会全表扫描后期可以换成全文索引或者 Elasticsearch但课程设计阶段够用。4. 避坑与排查SSM 药品系统最常见的五个翻车现场4.1 启动报 NoClassDefFoundError 或 ClassNotFoundException现象Tomcat 启动时控制台刷一堆 NoClassDefFoundError或者访问接口报 500日志里 ClassNotFoundException。原因通常是 Maven 依赖没有打包到 WEB-INF/lib 下或者依赖冲突导致某个类被覆盖。解决在 IDEA 里检查 Project Structure → Artifacts确认 lib 目录下有所有依赖 jar。用mvn dependency:tree看有没有重复依赖比如同时引入了不同版本的 spring-core。药品系统里常见的是 servlet-api 和 jsp-api 被重复引入这两个应该 scope 设为 provided。4.2 数据库连接报 Access denied 或 Public Key Retrieval is not allowed现象启动时 Druid 初始化失败报 Access denied for user rootlocalhost或者 MySQL 8 报 Public Key Retrieval is not allowed。原因前者是密码错或者用户没授权后者是 MySQL 8 默认用 caching_sha2_password 认证插件JDBC 连接串需要加参数。解决连接串改成jdbc:mysql://localhost:3306/pharmacy?useSSLfalseserverTimezoneAsia/ShanghaiallowPublicKeyRetrievaltrue。serverTimezone 不设的话datetime 字段存进去会差 8 小时药品有效期这种日期字段尤其不能错。4.3 事务不回滚库存扣了订单没生成现象下单接口报异常但库存已经扣了订单表没数据。原因Service 类没有被 Spring 事务代理或者异常类型不是 RuntimeExceptionTransactional 默认只回滚运行时异常。解决确认 applicationContext.xml 扫描了 Service 包且开启了 tx:annotation-driven。如果抛的是 checked exception在 Transactional 里加 rollbackFor Exception.class。另外Controller 里 try-catch 把异常吞了事务也感知不到别在 Controller 层捕获 Service 的异常。4.4 中文乱码药品名存进去变成问号现象前端提交的药品名在数据库里显示为 ???。原因三个地方要统一 UTF-8——数据库连接串加 characterEncodingutf8web.xml 里配 CharacterEncodingFilterTomcat 的 server.xml 里 Connector 加 URIEncodingUTF-8。解决CharacterEncodingFilter 的 forceEncoding 设为 true并且要放在所有 Filter 最前面。MySQL 建库时用CREATE DATABASE pharmacy DEFAULT CHARSET utf8mb4别用默认的 latin1。4.5 静态资源 404CSS 和 JS 加载不出来现象页面能打开但没样式F12 看 CSS 和 JS 请求全是 404。原因DispatcherServlet 在 web.xml 里配了/拦截所有请求静态资源也被 SpringMVC 接管了但没有对应的 Handler。解决在 spring-mvc.xml 里加mvc:default-servlet-handler/或者mvc:resources mapping/static/** location/static//。前者把找不到的请求交回给 Tomcat 默认 Servlet 处理后者显式映射静态资源目录。药品系统的图片上传目录也要用 mvc:resources 暴露出来否则上传成功但显示不出来。5. 从能跑到能答辩源码之外你还需要补什么5.1 用 Postman 把核心接口跑一遍源码能启动只是第一步答辩时老师大概率会让你演示下单流程。我一般会先用 Postman 把接口按顺序调一遍登录拿 session → 查询药品列表 → 加入购物车 → 提交订单 → 查看订单详情。这样能快速定位是前端问题还是后端问题。比如下单接口返回 500看日志是库存扣减 SQL 报错还是订单插入字段超长。药品名 varchar(100) 一般够用但生产厂家 varchar(200) 如果填了很长的公司全称可能截断建表时留够余量。5.2 答辩 PPT 里应该放什么图答辩 PPT 不是把源码截图堆上去。老师想看的是你的设计思路。建议放四张图系统架构图B/S 三层结构标注 SSM 各层职责、数据库 ER 图药品、分类、订单、用户四个核心实体及关系、核心业务流程图下单扣库存的时序、接口测试截图Postman 调通的证据。源码包里的 PPT 模板可以参考结构但业务描述要换成你自己项目的药品场景别直接抄商城的。5.3 毕业论文里值得展开的两个技术点论文别写成功能说明书。两个方向可以写出深度一是 SSM 整合过程中的事务管理机制结合库存扣减场景分析 Transactional 的传播行为和隔离级别二是 MyBatis 动态 SQL 在药品多条件查询中的应用对比拼接 SQL 字符串和where标签的差异附上执行计划分析。这两个点既有代码支撑又能体现你对框架的理解比罗列「系统实现了增删改查」强得多。5.4 源码二次开发的入手顺序拿到一份药品售卖系统源码别急着改功能。按这个顺序来先跑通登录确认数据库连接和事务配置没问题再跑通药品列表和详情确认 MyBatis 映射和分页正确然后跑通下单确认库存扣减和订单插入在同一个事务里最后改后台管理加一个药品批量导入或者库存预警。每跑通一个模块在代码里加一行注释记录你改了什么、为什么改。这个习惯在答辩时被问到「你做了哪些工作」时就是你的后悔药。我自己带过的项目中凡是能把 SSM 药品系统从环境搭建到下单流程完整讲清楚的人后面转 Spring Boot 或者看其他框架源码都很快上手。框架会变但分层思想、事务边界、SQL 映射这些底层逻辑不会变。希望帮到你。本文还有配套的精品资源点击获取

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询