简介这是一份基于Java技术、SSM框架与MySQL数据库实现的自助购药小程序完整成品面向毕业设计、课程设计及小程序开发者。系统覆盖首页、个人中心、用户管理、商家管理、药品信息管理、药品分类管理、发票信息管理与系统管理等核心模块可支撑药品搜索、浏览、下单及支付等完整业务链路。压缩包共1319个文件包含Java后台源码、Vue前端页面、WXML/WXSS小程序文件、JSON配置以及SQL数据库脚本等体积为22.55MB目录结构清晰便于按模块查阅。已有57人学习或下载适合需要快速搭建同类项目并进行二次开发的读者。资源内置部署运行脚本和数据库文件可帮助使用者省去环境配置与数据初始化环节直接导入工程即可启动验证。1. 需求拆解为什么是“小程序 SSM”而不是单页应用做自助购药类的毕业设计或课程设计时很多同学第一反应是上 Spring Boot 前后端分离再配一个 Vue 管理后台。但真正动手才发现课题要求里写的是 Java 实现演示现场要能跑通从下单到开发票的完整闭环而 Spring Boot Vue 这套组合里任何一个版本漂移都可能把自己卡死在环境问题上。这套方案选择了 SSM 框架 微信小程序 MySQL 5.7 的老牌组合反而是最稳的路线。它适合两类人一类是正在做 Java 方向毕设、课设需要一套能跑通、能讲清、能答辩的完整源码另一类是已经有业务想法、想快速拿一套带管理后台和小程序端的电商底座做二次开发的从业者。本文会从需求背景、技术选型、总体设计、关键实现一直讲到验收答辩把这份自助购药小程序源码项目的完整方案摊开来讲。2. 技术选型SSM 组合、MySQL 5.7 与双端开发环境的分工自助购药小程序本质上是一个垂直领域的电商系统核心链路是「用户搜索药品 → 浏览详情 → 下单 → 支付 → 商家处理 → 发票开具」。要支撑这条链路后端必须处理商品、订单、用户、商家、发票这几类核心数据前端则需要同时覆盖小程序用户端和后台管理端。技术选型时会优先考虑三点课题环境的兼容性、代码结构的可讲解性、部署过程的稳定性。这套项目在这三点上做得非常规矩下面逐个拆解。2.1 SSM 框架为什么这个场景不用 Spring Boot项目后端采用 SSM 框架即 Spring、SpringMVC、MyBatis 三者的整合。很多同学在课设里已经习惯 Spring Boot 的自动配置回到 SSM 会觉得配置繁琐但放在这个场景里SSM 有三个不可替代的优势。第一Spring 负责 Bean 管理和事务控制SpringMVC 负责请求分发和参数绑定MyBatis 负责 SQL 与 Java 对象的映射三层职责边界清晰。答辩时被问到「某个请求进来之后经过了哪些组件」你可以顺着 DispatcherServlet → Controller → Service → Mapper 这条链路完整讲出来这是评委最想听到的经典调用过程。第二MyBatis 的 XML 文件里每条 SQL 都是显式可控的药品按名称模糊查询、按分类筛选、按上下架状态过滤这些条件都写在 mapper XML 里比 JPA 的自动生成 SQL 更好解释。第三SSM 对部署环境的要求低Tomcat 7 加 JDK 1.8 就能稳定跑起来不会碰到 Spring Boot 3.x 要求 JDK 17 这类强制升级的问题。从工程结构上看SSM 项目通常按 controller、service、mapper、entity 四层分包每个层级的职责单一调试时也容易定位问题。对于课程设计答辩来说这种结构比「启动类 一堆注解」的 Spring Boot 项目更容易展开讲。2.2 数据库与连接MySQL 5.7 Navicat 11 的组合逻辑数据库选型直接用了 MySQL 5.7而不是 8.0 或更高版本。这不是保守而是这个项目场景下的务实选择。MySQL 5.7 是过去几年高校实验室和培训机构中使用最广的版本它的 SQL 语法、默认字符集、事务隔离级别与很多现成的课设代码完全兼容。最典型的例子是数据库连接驱动5.7 环境下使用mysql-connector-java5.x 版本连接串里不需要写serverTimezone参数JDK 1.8 也不用处理时区换算问题而一旦换成 MySQL 8.0驱动必须升级到 8.x同时要额外配置时区很多同学翻车就翻在这一步。数据库管理工具选用 Navicat 11它提供图形化的建表、导数据、执行 SQL 功能。项目附带数据库文件可以直接导入导入后能看到完整的表结构和示例数据。这个细节对课设非常重要评委查看数据库时不会只看 ER 图他们会直接打开表看字段设计和数据内容一份带分类、带药品名称、带库存数量的示例数据比空表更有说服力。2.3 前端工具链微信开发者工具与 HBuilderX 的分工小程序端的开发涉及两个工具HBuilderX 和微信开发者工具。HBuilderX 在这里的作用偏向工程管理——它支持 Vue 语法开发小程序可以创建小程序项目结构、编写页面代码和逻辑代码微信开发者工具则承担预览、调试、真机测试的角色。实际工作时存在两种用法一种是完全用微信开发者工具从零创建原生小程序项目另一种是先在 HBuilderX 里维护代码再导入到微信开发者工具里预览。这套项目按后者的思路组织核心页面代码是原生小程序语法兼容性强直接导入微信开发者工具即可运行。要注意的是小程序端的网络请求必须指向后端接口地址由于 Tomcat 部署在本机开发调试时通常把接口地址配置为http://localhost:8080/项目名。如果项目名带中文或特殊字符路径解析会出现问题建议在发布配置里显式设置 context path。2.4 环境参数对照表开发环境是课设项目最容易出问题的地方版本差异会导致各种玄学报错。下面把这份源码的完整环境参数整理成对照表你拿到源码后按这张表逐项核对基本可以避免一半的部署问题。项版本要求说明JDK1.8编译级别必须设为 1.8低于或高于都可能在 Tomcat 7 上报错数据库MySQL 5.7导入项目附带的 .sql 文件注意字符集选 utf8mb4数据库工具Navicat 11用 11 或更高版本均可低版本打不开高版本导出的文件IDEEclipse / IDEA导入为 Maven 项目IDEA 需配置 JDK 1.8 SDKMaven3.3使用阿里云镜像加速依赖下载否则首次构建会等很久部署容器Tomcat 7端口默认 8080如需修改要同步改小程序端的接口地址小程序工具HBuilderX / 微信开发者工具调试时关闭 URL 校验域名选项这套环境中JDK 1.8 和 Tomcat 7 是绑定关系MySQL 5.7 和mysql-connector-java5.x 是绑定关系。只要版本绑定的逻辑不乱拆部署阶段基本顺畅。如果你之前只熟悉 Spring Boot 的自动化部署第一次用 Maven 手动打 war 包可能会不习惯但多跑两次clean package就能理解整个构建链路。3. 总体架构设计七类功能模块与数据库表的映射关系自助购药小程序的业务规模不大但角色区分明确普通用户在小程序端浏览和下单商家在后台管理药品和订单管理员处理用户审核、分类维护和系统配置。如果把三个角色的需求混在一起设计系统会变得臃肿。这套系统的设计思路是先按 B/S 三层结构搭骨架再按角色划分功能模块最后用数据库表把模块串起来。3.1 B/S 三层结构与 Maven 工程目录系统整体采用 B/S 架构表现层、业务层、数据层三层分离。表现层由两部分组成面向用户的微信小程序端和面向管理员/商家的后台管理页面。后台管理页基于 Bootstrap 类的后台模板实现登录后根据角色加载不同菜单。业务层对应 Service 接口及其实现类负责具体业务规则比如用户注册时检查手机号是否重复、下单时校验药品库存、发票申请时校验订单状态。数据层是 MyBatis 的 Mapper 接口和 XML 文件负责与 MySQL 交互。Maven 工程结构一眼看去是标准的 SSM 分层src/main/java ├── controller # 控制层接收请求返回 JSON 或页面 ├── service # 业务层接口 ├── service/impl # 业务层实现 ├── mapper # MyBatis 数据访问接口 ├── entity # 实体类对应数据库表 └── config # Spring 与 SpringMVC 配置 src/main/resources ├── mapper/*.xml # MyBatis SQL 映射文件 ├── spring/ # Spring 核心与 SpringMVC 配置文件 └── jdbc.properties # 数据库连接配置 src/main/webapp ├── admin # 后台管理页面 └── WEB-INF/web.xml # 项目部署描述文件controller 层只做参数接收和结果返回不写业务逻辑service 层处理核心逻辑事务注解加在实现类上mapper 层只做数据读写。这种分层的价值在于答辩时能清晰说出「数据是怎么一层层流转的」。3.2 七个功能模块的职责边界系统功能模块按摘要描述包括首页、个人中心、用户管理、商家管理、药品信息管理、药品分类管理、发票信息管理、系统管理。其中首页和个人中心主要在小程序端呈现其余模块在后台管理端承载管理功能。首页模块负责药品展示、分类导航、搜索入口和轮播图位数据来源于药品信息表和药品分类表。个人中心模块管理用户的登录状态、收货地址、历史订单和发票申请入口。用户管理模块面向管理员负责查看注册用户列表、禁用/启用账号、重置密码。商家管理模块处理商家入驻信息的审核审核通过后商家才能登录后台维护自己的药品。药品信息管理是核心模块支持药品的添加、编辑、上下架、库存调整、价格修改和图片上传。药品分类管理维护药品的一级分类和二级分类前端首页的分类导航直接读取该表。发票信息管理记录用户申请的开票请求包含发票抬头、税号、金额、开票状态等字段。系统管理则配置轮播图、公告、系统参数等信息。七个模块看似各自独立实际上围绕「药品」和「订单」两条主线交织。模块的职责边界划分清楚之后数据库表的设计也就顺理成章了。3.3 数据库设计核心表结构与字段说明数据库设计遵循电商系统的常规做法核心思路是「用户表与商家表分离、药品表与分类表关联、订单表与发票表关联」。实际项目中通常包含以下核心表表名用途关键字段user_info注册用户信息id、username、password、phone、statusmerchant_info商家信息id、merchant_name、contact、audit_statusdrug_category药品分类id、category_name、parent_id、sort_orderdrug_info药品信息id、drug_name、category_id、price、stock、img_url、statusorder_info订单信息id、order_no、user_id、drug_id、quantity、amount、statusinvoice_info发票信息id、order_id、invoice_title、tax_no、amount、statusbanner_info轮播图配置id、img_url、link_url、sort_order药品表通过category_id关联分类表实现前端按分类筛选通过status字段控制上下架下架药品在小程序端不再展示。订单表用order_no做唯一业务编号用status字段标记订单状态流转通常的取值为待付款、已付款、待发货、已发货、已完成、已取消。发票表通过order_id关联订单保证一笔订单只能申请一次发票这个逻辑在 service 层通过唯一性校验实现。3.4 角色权限与页面路由系统的权限控制采用「角色 菜单」的方式。管理员登录后台看到全部菜单商家登录只能看到药品信息管理、订单信息、发票信息普通用户在小程序端没有后台访问权限。这个控制在后台页面路由层面实现登录后把角色标识存入 session每个页面加载时校验权限无权访问时跳回登录页。小程序端的路由则按用户操作流设计落地首页 → 搜索/分类浏览 → 药品详情 → 确认订单 → 支付 → 订单列表 → 申请发票。每一步都有对应的页面和接口路由参数中传递药品 id、订单 id 等关键信息。整体设计对新手很友好因为每个页面只承担一个职责调试时定位问题非常直接。4. 关键实现从后端 Controller 到小程序端的药品查询与下单闭环需求设计和数据库表结构确定之后核心工作落在前后端联调上。这一章选择药品信息查询和下单两条链路做拆解因为它们覆盖了后端接口、数据库操作、小程序端请求封装三个关键环节。完整的业务代码在源码包里这里的实现重点是让你理解代码的组织方式。4.1 后端控制层药品信息的分页查询接口药品列表是首页最高频的接口需要支持分页、名称模糊搜索、分类筛选、上下架状态过滤。Controller 层代码通常写成这样Controller RequestMapping(/drug) public class DrugInfoController { Autowired private DrugInfoService drugInfoService; RequestMapping(/list) ResponseBody public MapString, Object list(DrugInfo drug, Integer page, Integer limit) { PageHelper.startPage(page, limit); ListDrugInfo list drugInfoService.selectByCondition(drug); PageInfoDrugInfo pageInfo new PageInfo(list); MapString, Object result new HashMap(); result.put(code, 0); result.put(msg, success); result.put(count, pageInfo.getTotal()); result.put(data, pageInfo.getList()); return result; } }这段代码用 PageHelper 做分页插件page和limit由前端传入分别代表页码和每页条数。DrugInfo实体对象作为查询条件载体前端传入的drugName、categoryId、status会被自动绑定到对象的对应属性。返回值统一封装为code / msg / count / data结构这是后台管理表格组件和小程序端都能直接解析的通用格式。4.2 MyBatis 条件查询动态 SQL 的写法Service 层在查询时直接把DrugInfo对象传给 MapperMyBatis 在 XML 里动态拼接 SQL。这也是 SSM 项目中最值得在答辩时展开讲的一段select idselectByCondition resultTypecom.example.entity.DrugInfo SELECT * FROM drug_info where if testdrugName ! null and drugName ! AND drug_name LIKE CONCAT(%, #{drugName}, %) /if if testcategoryId ! null AND category_id #{categoryId} /if if teststatus ! null AND status #{status} /if /where ORDER BY create_time DESC /selectwhere标签会自动去除第一个条件前的AND避免 SQL 语法错误。药品名称使用LIKE CONCAT(%, #{drugName}, %)实现模糊匹配CONCAT函数避免了传参时手动拼接百分号造成的 SQL 注入风险。这条 SQL 同时服务了首页搜索框、分类页筛选、后台药品列表三个场景一段 SQL 多处复用符合课设项目的合理抽象。4.3 小程序端请求封装与页面数据绑定小程序端不能直接使用浏览器的 axios 或 fetch所有的网络请求都通过wx.request发出。实际项目中会做一个统一的 request 封装避免每个页面重复写回调const BASE_URL http://localhost:8080/drug-miniapp; const request (url, method GET, data {}) { return new Promise((resolve, reject) { wx.request({ url: BASE_URL url, method, data, header: { Content-Type: application/json }, success: (res) { if (res.data.code 0) { resolve(res.data.data); } else { reject(res.data); } }, fail: reject }); }); }; // 页面中调用搜索“感冒”分类下的药品 request(/drug/list, GET, { page: 1, limit: 10, drugName: 感冒, categoryId: 3 }).then((list) { this.setData({ drugList: list }); });BASE_URL中的端口号必须与 Tomcat 的部署端口一致项目名如果修改了这里也要同步。封装后的 request 返回 Promise页面代码可以用then链式调用避免了回调嵌套的「金字塔」结构。数据绑定方面小程序用setData更新页面数据所有字段拼接在data中一次传入多次调用会触发多次渲染因此要避免在循环里频繁setData。4.4 下单与发票的交互链路下单链路是用户端到后端数据库的完整闭环。用户在药品详情页点击「立即购买」后小程序端携带drugId和quantity请求下单接口后端先查询药品当前库存判断是否大于下单数量库存不足则返回提示库存充足则生成订单号状态置为待付款同时扣减库存。用户支付成功后回调更新订单状态为已付款。这个过程在 Service 层必须加Transactional事务注解保证扣库存和生成订单要么同时成功要么同时回滚避免超卖。发票申请在订单完成后发起用户提交发票抬头和税号后端写入发票表状态初始为待开票商家在后台确认后更新状态。这里有一个常见的设计陷阱发票表没有做订单唯一性约束导致同一笔订单可以重复申请发票。通常的做法是在发票表给order_id加唯一索引并在 Service 层插入前再查一次订单的发票状态。5. 常见问题与避坑部署、版本与中文乱码的排查手册SSM 项目最折磨人的不是写业务代码而是环境问题。这一章的每一条都是实际部署和调试中反复遇到的坑按「现象 → 原因 → 解决」的方式梳理拿到源码后如果跑不起来直接对照排查。5.1 Tomcat 7 启动报错JDK 编译版本不匹配现象项目在 Eclipse 或 IDEA 里编译通过部署到 Tomcat 7 后启动立即报UnsupportedClassVersionError提示版本号 55.0 或 52.0 之类的错误。原因本机 JDK 是 17 或 11而 Tomcat 7 运行时的类加载器无法识别高版本 JDK 编译出的 class 文件。Tomcat 7 最高支持 JDK 8源码里的 JDK 版本配置却可能被 IDE 自动改成了高版本。解决在 IDE 中把项目编译级别统一改为 1.8。IDEA 中打开 Project Structure把 Project SDK 设为 1.8Modules 里的 Language Level 也同步为 8。同时在pom.xml里检查maven.compiler.source和maven.compiler.target是否都是 1.8。改完之后执行 Maven 的clean再重新package不要只点 Tomcat 的重启按钮否则仍会使用旧的 class 文件。5.2 数据库连接失败MySQL 8.0 驱动与时区问题现象项目启动后访问接口后台报Communications link failure或者The server time zone value ... is unrecognized。原因本机安装的是 MySQL 8.0 而不是 5.7但项目用的驱动还是mysql-connector-java5.x。8.x 版本的 MySQL 服务端默认启用了时区校验驱动连接串里如果没有serverTimezone参数就会失败。解决两种方案任选其一。最省事的方案是本机重装或改用 MySQL 5.7并导入项目附带的数据库文件。如果必须使用 MySQL 8.0则把pom.xml中的 mysql 驱动版本改为 8.0.x并在jdbc.properties的连接串末尾追加serverTimezoneAsia/ShanghaiuseSSLfalse。要注意驱动升级后部分tinyInt(1)字段的返回类型可能从 Boolean 变成 Integer检查实体类中的对应属性类型。5.3 中文乱码数据库、页面、Tomcat 三层字符集不一致现象后台管理页面新增药品时输入中文保存后刷新列表变成问号或者页面上显示正常但导出数据后 Excel 里乱码。原因字符集在三个位置不统一。MySQL 数据库表默认字符集可能是latin1项目里jdbc.properties连接串缺少年份的characterEncodingTomcat 对 POST 请求的编码默认不是 UTF-8。解决先确认数据库字符集执行SHOW CREATE TABLE drug_info看到DEFAULT CHARSETlatin1就说明中枪了需要执行ALTER TABLE ... CONVERT TO CHARACTER SET utf8mb4。然后改jdbc.properties连接串追加characterEncodingutf8。最后在 Tomcat 的server.xml的 Connector 节点上加上URIEncodingUTF-8。三处都改完重启 Tomcat乱码问题才会彻底消失。5.4 小程序端请求失败开发者工具域名校验拦截现象小程序页面加载时一直 blank控制台报request:fail或者提示「不在以下 request 合法域名列表中」。原因微信开发者工具默认校验请求域名本地调试时接口地址是http://localhost:8080既不是 HTTPS 也不在合法域名列表中所以请求被拦截。解决开发调试阶段在微信开发者工具的详情设置里勾选「不校验合法域名、web-view业务域名、TLS 版本以及 HTTPS 证书」。这个选项只影响本地调试真机预览时如果关闭了调试模式同样会被拦截。真实上线必须把后端接口部署到配置了 HTTPS 证书的服务器上并且在微信公众平台配置 request 合法域名。课设演示通常只需要局域网内真机调试打开调试模式即可。5.5 Maven 依赖下载缓慢或失败镜像与本地仓库现象首次导入项目时 Eclipse 或 IDEA 一直卡在 Maven loading或者报Cannot resolve symbol PageHelper等依赖缺失错误。原因默认 Maven 中央仓库在国内访问速度慢某些依赖版本被限速或连接超时导致本地仓库里只有残缺的 jar 包。解决修改 Maven 的settings.xml配置阿里云镜像同时把本地仓库默认路径改为非 C 盘位置。改完后在 IDEA 里执行 Maven 的reimport按钮强制重新解析依赖。如果某个依赖始终解析不了可以直接到本地仓库找到对应文件夹删除.lastUpdated结尾的文件后重新下载。这是 Maven 依赖问题的标准「后悔药」操作。6. 验收与答辩按角色走查的演示脚本与高频提问课设答辩的验收环节评委不关心你写了多少行代码他们只关心两件事系统能不能按需求完整跑通以及你能不能讲清楚关键设计的理由。提前准备一份按角色走查的演示脚本比临时翻代码有效得多。6.1 按角色走查的演示脚本演示路径建议按照业务链路推进而不是按菜单顺序挨个点击。推荐顺序是先以普通用户身份在小程序端完成一次完整购药流程再切换到管理后台查看订单和发票状态最后用管理员账号演示审核和配置功能。角色操作步骤演示要点用户注册登录 → 首页搜索药品 → 分类筛选 → 查看详情 → 下单支付搜索关键字能匹配、库存充足可下单、订单状态变化可见商家登录后台 → 药品上下架 → 修改库存价格 → 处理订单 → 开具发票下架药品在小程序端立即不可见、订单状态可流转管理员用户管理 → 商家审核 → 药品分类维护 → 轮播图配置账号可禁用、审核通过后商家才可登录每完成一步口头说明对应的数据库变化。比如用户下单后你在 Navicat 里刷新订单表展示新增记录商家上下架药品后刷新药品表展示status字段变化。评委最喜欢看到数据层面的实时联动这比停留在页面截图有说服力得多。6.2 答辩高频问题与回答思路答辩时有三个几乎必问的问题值得提前准备。问「为什么用 SSM 而不是 Spring Boot」时可以回答课题环境要求 Java 传统企业级架构SSM 对 Spring、SpringMVC、MyBatis 各层职责拆分清晰更容易展示事务控制、SQL 映射等核心知识同时 Tomcat 7 与 JDK 1.8 的搭配保证了部署环境的稳定性。问「为什么选 MySQL 5.7」时回答重点是版本兼容性和低成本运维5.7 与项目使用的驱动版本完全匹配数据导入导出工具链成熟适合课程设计场景。问「下单时怎么防止库存超卖」时直接讲 Service 层的实现逻辑先查询库存再扣减两条操作放在同一个事务里扣减库存的 SQL 使用UPDATE drug_info SET stock stock - #{num} WHERE id #{id} AND stock #{num}受影响行数为 0 则说明库存不足这种原子操作能避免并发下的超卖问题。答辩演示前把所有环境项检查一遍这是我做课设项目以来吃过亏后的固定习惯。有一次直接在评委的电脑上插入 U 盘跑项目结果对方机器装的是 MySQL 8.0连接参数不匹配当场报错后来我每次演示都强制走一遍环境清单JDK 1.8 是否就位、MySQL 5.7 是否启动、端口是否被占用、数据库文件是否已导入、微信开发者工具是否勾选了域名校验。检查一遍只需要两分钟但能避免的尴尬远超这两分钟的价值。希望这份完整的自助购药小程序方案能帮你顺利跑通项目答辩时也能稳稳接住评委的每一个提问。本文还有配套的精品资源点击获取
阅读完成 · 觉得有帮助?