资讯动态

基于SpringBoot的药店管理系统:Java毕设实战与部署指南

发布时间:2026/8/21 13:19:05 来源:尧图企业网站定制
如果你正在为计算机专业的毕业设计选题而焦虑尤其是想找一个既能体现技术深度、又具备完整业务逻辑、还能顺利通过答辩的Java项目那么这篇文章就是为你准备的。市面上很多“毕设项目”要么是功能简陋的玩具要么是代码混乱、难以二次开发的“黑盒”导致学生从选题到部署调试步步维艰最终答辩时被问得哑口无言。今天我们将深入剖析一个非常经典且实用的选题——基于SpringBoot的药店管理系统。这篇文章的目的不是简单地给你一份源码而是带你从零开始彻底理解这个项目的核心价值、技术选型、完整部署流程、关键代码逻辑以及答辩时的应对策略。你将获得一个“开箱即用”但“深度可调”的项目既能快速搭建完成基础要求又能根据你的理解进行个性化扩展从而在毕业设计中脱颖而出。我们将重点关注三个核心痛点第一如何从零开始在本地和服务器上成功运行这个系统第二如何读懂源码理解SpringBoot、MyBatis、Thymeleaf等技术是如何协同工作的第三如何基于现有代码进行二次开发或功能扩展以满足更高的毕设要求。下面我们就从项目最核心的价值开始。1. 这个毕设项目真正解决了什么问题很多同学选择“XX管理系统”作为毕设往往只是看中了它的普遍性却忽略了其内在的技术复杂度和业务深度。一个合格的药店管理系统远不止是简单的增删改查CRUD。它本质上是一个融合了进销存管理、会员营销、财务统计和权限控制的小型ERP系统。选择它作为毕设你能接触到以下多个维度的实战技术复杂的业务逻辑药品的批次管理同一药品不同进货批次、库存预警、有效期管理、会员折扣与积分体系、销售与采购对账。这些业务远比学生信息管理复杂能充分体现你的系统设计能力。完整的技术栈整合项目通常会用到SpringBoot快速构建、MyBatis-Plus高效数据操作、Thymeleaf模板引擎、MySQL数据存储、Maven依赖管理、Bootstrap前端框架。这正是企业级Java Web开发的标配。典型的分层架构你会清晰地看到Controller控制层、Service业务逻辑层、Mapper数据访问层和Entity实体层的分离这是理解MVC和三层架构的绝佳案例。可扩展性与答辩优势由于业务场景真实你可以很容易地提出扩展点例如集成Redis缓存药品信息、使用ECharts实现销售数据可视化、添加药品扫码入库功能、或设计简单的推荐算法如“购买了A药的顾客也买了B药”。在答辩时这些深入的思考能让你从容应对老师的提问。因此这个项目的价值在于它提供了一个真实的业务场景让你能将所学的Java Web、数据库、软件工程等理论知识串联起来完成一次从设计、编码、测试到部署的完整项目实践。2. 核心技术与环境准备在动手之前我们需要明确项目依赖的核心技术栈和必须准备好的开发环境。这是项目能否成功运行的第一步。2.1 核心技术栈介绍SpringBoot 2.x: 项目的基石。它简化了Spring应用的初始搭建和开发过程采用“约定大于配置”的理念让我们免除了繁琐的XML配置。本项目中它负责整合所有其他组件、提供内嵌Web服务器如Tomcat并管理应用的生命周期。MyBatis-Plus: 一个强大的MyBatis增强工具。它在MyBatis的基础上只做增强不做改变提供了通用的Mapper和Service封装可以极大减少单表CRUD操作的代码量。你会看到通过继承BaseMapper就能获得大部分数据操作方法。Thymeleaf: 现代服务端的Java模板引擎。它允许我们将动态数据从Controller传递的Model渲染到HTML页面中。它的语法自然HTML标签属性友好适合作为毕设项目的前后端不分离架构选择。MySQL 5.7/8.0: 关系型数据库。用于存储药品、用户、订单、库存等所有结构化数据。你需要提前设计好数据库表结构项目源码通常会提供SQL脚本。Maven 3.6: 项目构建和依赖管理工具。通过pom.xml文件声明项目依赖Maven会自动从中央仓库下载所需的Jar包解决令人头疼的依赖冲突问题。前端技术: HTML5, CSS3, JavaScript以及前端框架如Bootstrap、jQuery、Layui等。它们负责构建用户界面和实现交互逻辑。毕设项目通常使用这些成熟框架来快速搭建美观的管理后台界面。2.2 开发环境与工具准备请确保你的电脑上已安装并配置好以下环境JDK: 版本1.8或11推荐1.8兼容性最好。安装后配置JAVA_HOME环境变量。# 在终端或CMD中验证 java -versionMaven: 版本3.6.3或以上。安装后配置MAVEN_HOME并将bin目录加入PATH。# 验证Maven mvn -vMySQL: 版本5.7或8.0。安装后记住root用户的密码。建议使用图形化工具如Navicat、MySQL Workbench或IDEA内置的数据库工具来管理。IDE (集成开发环境):IntelliJ IDEA Ultimate/Community版或Eclipse。IDEA对SpringBoot和Maven的支持更友好强烈推荐。确保安装了Lombok插件用于简化实体类代码。浏览器: Chrome 或 Firefox用于测试系统。项目源码: 从可靠的渠道获取完整的SpringBoot药店管理系统源码包。3. 项目初始化与数据库搭建拿到源码后第一步不是直接运行而是先理解项目结构并建立数据库。3.1 项目结构解析用IDEA打开项目后你会看到类似如下的标准Maven项目结构pharmacy-management-system/ ├── src/ │ ├── main/ │ │ ├── java/ │ │ │ └── com/ │ │ │ └── pharmacy/ │ │ │ ├── PharmacyApplication.java # SpringBoot主启动类 │ │ │ ├── config/ # 配置类如WebMvcConfig │ │ │ ├── controller/ # 控制层处理HTTP请求 │ │ │ ├── entity/ # 实体类对应数据库表 │ │ │ ├── mapper/ # 数据访问层MyBatis Mapper接口 │ │ │ ├── service/ # 业务逻辑层接口 │ │ │ │ └── impl/ # 业务逻辑层实现类 │ │ │ └── dto/ # 数据传输对象可选 │ │ └── resources/ │ │ ├── static/ # 静态资源css, js, images │ │ ├── templates/ # Thymeleaf模板文件.html │ │ ├── application.yml # 主配置文件 │ │ └── mapper/ # MyBatis的XML映射文件如果使用 │ └── test/ # 单元测试目录 ├── pom.xml # Maven项目对象模型管理依赖 └── pharmacy.sql # 数据库初始化SQL脚本通常在根目录或resources下理解这个结构是阅读和修改代码的基础。3.2 数据库创建与导入打开MySQL客户端使用root用户登录。创建专属数据库避免与现有数据库混淆。CREATE DATABASE IF NOT EXISTS pharmacy_db DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; USE pharmacy_db;执行SQL脚本。在项目根目录或src/main/resources下找到pharmacy.sql文件将其中的SQL语句在pharmacy_db数据库中全部执行。这个脚本会创建所有必要的表如user,drug,supplier,purchase_order,sale_order,stock等并插入一些初始测试数据。验证执行SHOW TABLES;命令查看表是否创建成功。3.3 关键配置文件修改接下来需要修改SpringBoot的配置文件告诉应用如何连接我们刚创建的数据库。配置文件通常是src/main/resources/application.yml或application.properties。这里以更清晰的YAML格式为例# application.yml server: port: 8080 # 应用启动端口可自定义 spring: datasource: driver-class-name: com.mysql.cj.jdbc.Driver # 修改为你自己的数据库连接信息地址、库名、用户名、密码 url: jdbc:mysql://localhost:3306/pharmacy_db?useUnicodetruecharacterEncodingutf-8useSSLfalseserverTimezoneAsia/Shanghai username: root password: your_mysql_password # 替换为你的MySQL密码 thymeleaf: cache: false # 开发阶段关闭模板缓存修改HTML后立即生效 prefix: classpath:/templates/ suffix: .html mode: HTML encoding: UTF-8 # MyBatis-Plus 配置 mybatis-plus: mapper-locations: classpath*:/mapper/**/*.xml # XML映射文件位置 type-aliases-package: com.pharmacy.entity # 实体类别名包 configuration: map-underscore-to-camel-case: true # 自动将下划线命名转为驼峰命名 log-impl: org.apache.ibatis.logging.stdout.StdOutImpl # 控制台打印SQL语句调试用重点务必把url中的数据库名、username和password修改成你自己环境的信息。serverTimezoneAsia/Shanghai是为了避免时区错误。4. 项目启动与核心模块代码讲解环境配置好后我们就可以启动项目并深入核心代码了。4.1 启动项目在IDEA中找到主启动类PharmacyApplication.java其内容通常非常简单package com.pharmacy; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; SpringBootApplication // 核心注解标识这是一个SpringBoot应用 public class PharmacyApplication { public static void main(String[] args) { SpringApplication.run(PharmacyApplication.class, args); } }右键点击这个类选择Run ‘PharmacyApplication.main()‘。观察控制台日志如果没有报错最后出现类似Started PharmacyApplication in 5.123 seconds (JVM running for 6.456)的提示并且Tomcat在8080端口启动成功说明项目启动成功。打开浏览器访问http://localhost:8080或http://localhost:8080/login应该能看到系统的登录页面。4.2 用户登录与权限控制模块代码解析登录是系统的入口也是理解SpringBoot Web开发的一个经典案例。1. Entity (实体类 -User.java):package com.pharmacy.entity; import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import lombok.Data; import java.util.Date; Data // Lombok注解自动生成getter, setter, toString等方法 TableName(user) // MyBatis-Plus注解指定对应数据库表名 public class User { TableId(type IdType.AUTO) // 主键自增 private Integer id; private String username; // 用户名 private String password; // 密码存储密文 private String realName; // 真实姓名 private String role; // 角色admin管理员staff店员 private String phone; private Date createTime; // ... 其他字段和getter/setter (已被Data覆盖) }2. Controller (控制层 -LoginController.java):Controller负责接收前端的HTTP请求调用Service处理业务然后返回视图或数据。package com.pharmacy.controller; import com.pharmacy.entity.User; import com.pharmacy.service.UserService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestParam; import javax.servlet.http.HttpSession; Controller // 声明这是一个控制器 public class LoginController { Autowired // 自动注入UserService private UserService userService; // 处理GET请求跳转到登录页面 GetMapping(/login) public String loginPage() { return login; // 对应 resources/templates/login.html } // 处理POST请求验证登录 PostMapping(/doLogin) public String doLogin(RequestParam String username, RequestParam String password, HttpSession session, Model model) { // Model用于向页面传递数据 // 调用Service进行登录验证 User user userService.login(username, password); if (user ! null) { // 登录成功将用户信息存入Session session.setAttribute(loginUser, user); // 根据角色跳转到不同主页 if (admin.equals(user.getRole())) { return redirect:/admin/index; } else { return redirect:/staff/index; } } else { // 登录失败返回错误信息到登录页 model.addAttribute(msg, 用户名或密码错误); return login; } } // 退出登录 GetMapping(/logout) public String logout(HttpSession session) { session.invalidate(); // 清空Session return redirect:/login; } }3. Service (业务层 -UserService.java及其实现):Service层封装核心业务逻辑。这里以接口和实现类的形式展示。package com.pharmacy.service; import com.pharmacy.entity.User; public interface UserService { User login(String username, String password); // ... 其他业务方法如用户增删改查 }package com.pharmacy.service.impl; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.pharmacy.entity.User; import com.pharmacy.mapper.UserMapper; import com.pharmacy.service.UserService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.util.DigestUtils; import java.nio.charset.StandardCharsets; Service // 声明这是一个Spring管理的Service Bean public class UserServiceImpl implements UserService { Autowired private UserMapper userMapper; // 注入Mapper进行数据库操作 Override public User login(String username, String password) { // 1. 根据用户名查询用户MyBatis-Plus写法 QueryWrapperUser wrapper new QueryWrapper(); wrapper.eq(username, username); User user userMapper.selectOne(wrapper); // 2. 用户存在且密码匹配实际项目中密码应加密存储这里演示MD5 if (user ! null) { String encryptedInputPwd DigestUtils.md5DigestAsHex(password.getBytes(StandardCharsets.UTF_8)); if (encryptedInputPwd.equals(user.getPassword())) { // 登录成功注意返回前最好清除密码字段 user.setPassword(null); return user; } } return null; // 登录失败 } }关键点实际项目中密码不应明文存储。这里使用了Spring自带的DigestUtils进行MD5加密。更安全的做法是使用BCrypt或PBKDF2等加盐哈希算法。4. Mapper (数据访问层 -UserMapper.java):MyBatis-Plus的强大之处在于对于单表操作你只需要一个继承自BaseMapper的接口无需编写XML或实现类。package com.pharmacy.mapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.pharmacy.entity.User; import org.apache.ibatis.annotations.Mapper; Mapper // 标识为MyBatis的MapperSpringBoot会自动扫描并创建其代理实现类 public interface UserMapper extends BaseMapperUser { // 无需编写任何方法BaseMapper已提供了insert, deleteById, updateById, selectById, selectList等通用方法 // 如果需要复杂查询可以在这里定义方法并在resources/mapper/UserMapper.xml中编写SQL }4.3 药品管理模块核心逻辑药品管理是系统的核心涉及库存联动逻辑更复杂。1. 药品入库采购流程当采购员录入一批新药品时系统需要在purchase_order采购单表插入一条记录。在purchase_order_detail采购明细表插入药品详情药品ID、数量、进价。更新或插入stock库存表。这是关键业务逻辑如果该药品已存在则增加库存数量如果不存在则创建新的库存记录。// 在 PurchaseService 中 Service public class PurchaseServiceImpl implements PurchaseService { Autowired private PurchaseOrderMapper orderMapper; Autowired private PurchaseOrderDetailMapper detailMapper; Autowired private StockMapper stockMapper; Autowired private DrugMapper drugMapper; Transactional // 声明事务保证以下操作要么全成功要么全失败 public boolean addPurchaseOrder(PurchaseOrder order, ListPurchaseOrderDetail details) { // 1. 保存采购单主表 orderMapper.insert(order); // 2. 循环保存采购明细 for (PurchaseOrderDetail detail : details) { detail.setOrderId(order.getId()); detailMapper.insert(detail); // 3. 更新库存 updateStock(detail.getDrugId(), detail.getQuantity(), detail.getPurchasePrice()); } return true; } private void updateStock(Integer drugId, Integer quantity, BigDecimal purchasePrice) { QueryWrapperStock wrapper new QueryWrapper(); wrapper.eq(drug_id, drugId); Stock stock stockMapper.selectOne(wrapper); if (stock ! null) { // 库存存在更新数量和平均成本简化计算 stock.setQuantity(stock.getQuantity() quantity); // 实际业务中库存成本计算更复杂可能采用移动加权平均法 stockMapper.updateById(stock); } else { // 库存不存在创建新记录 Drug drug drugMapper.selectById(drugId); Stock newStock new Stock(); newStock.setDrugId(drugId); newStock.setDrugName(drug.getName()); newStock.setQuantity(quantity); newStock.setCostPrice(purchasePrice); // 初次入库成本 stockMapper.insert(newStock); } } }2. 药品销售流程销售时需要检查库存是否充足然后扣减库存并生成销售记录。// 在 SaleService 中 Transactional public boolean addSaleOrder(SaleOrder order, ListSaleOrderDetail details) { // 1. 预检查库存 for (SaleOrderDetail detail : details) { Stock stock stockMapper.selectById(detail.getDrugId()); if (stock null || stock.getQuantity() detail.getQuantity()) { throw new RuntimeException(药品【 detail.getDrugName() 】库存不足); } } // 2. 保存销售单和明细 saleOrderMapper.insert(order); for (SaleOrderDetail detail : details) { detail.setOrderId(order.getId()); saleOrderDetailMapper.insert(detail); // 3. 扣减库存 deductStock(detail.getDrugId(), detail.getQuantity()); } return true; } private void deductStock(Integer drugId, Integer quantity) { // 使用MyBatis-Plus的UpdateWrapper进行原子操作避免并发问题 UpdateWrapperStock wrapper new UpdateWrapper(); wrapper.setSql(quantity quantity - quantity) // 直接使用SQL表达式 .eq(drug_id, drugId) .ge(quantity, quantity); // 乐观锁确保扣减后库存不为负 int rows stockMapper.update(null, wrapper); if (rows 0) { throw new RuntimeException(扣减库存失败可能库存不足或数据不一致); } }关键点Transactional注解确保了业务的原子性。库存扣减使用了UpdateWrapper进行原子更新并在where条件中检查库存余量这是一种简单的乐观锁思想能在一定程度上应对并发场景。5. 项目部署与上线安装调试本地运行成功只是第一步让项目在服务器上跑起来才是完整的毕设体验。这里以最常见的Linux服务器如阿里云ECS为例介绍两种部署方式。5.1 传统JAR包部署项目打包在IDEA的Maven工具栏或项目根目录下执行命令生成可执行的JAR包。# 在项目根目录下执行 mvn clean package -DskipTests执行成功后在target/目录下会生成pharmacy-management-system-0.0.1-SNAPSHOT.jar名称可能不同。上传服务器使用FTP工具如FileZilla或SCP命令将JAR包和数据库SQL脚本上传到服务器的某个目录例如/home/app/。服务器环境准备确保服务器已安装JDK版本与本地一致和MySQL。# 连接服务器后检查 java -version mysql --version导入数据库在服务器MySQL中创建数据库并导入SQL脚本步骤同3.2。修改配置并运行修改JAR包内的配置比较麻烦更推荐在运行命令时指定外部配置文件或将application.yml放在JAR包同级目录下SpringBoot会优先读取外部配置。创建一个外部application.yml修改其中的数据库连接地址localhost改为服务器内网IP或127.0.0.1、用户名和密码。在服务器上运行项目cd /home/app # 方式一使用外部配置文件 java -jar pharmacy-management-system-0.0.1-SNAPSHOT.jar --spring.config.locationapplication.yml # 方式二后台运行并将日志输出到文件 nohup java -jar pharmacy-management-system-0.0.1-SNAPSHOT.jar app.log 21 nohup和使进程在后台运行 app.log 21将标准输出和错误输出都重定向到app.log文件。访问测试服务器安全组开放8080端口或你配置的端口在浏览器通过http://服务器公网IP:8080访问系统。5.2 Docker容器化部署进阶Docker部署更规范环境隔离更好是现在更流行的方式。编写Dockerfile在项目根目录创建Dockerfile文件。# 使用官方Java 8运行环境作为基础镜像 FROM openjdk:8-jdk-alpine # 在镜像中创建一个目录来存放应用 RUN mkdir -p /app # 设置工作目录 WORKDIR /app # 将Maven打包好的可执行Jar包复制到镜像中 COPY target/pharmacy-management-system-*.jar /app/app.jar # 暴露应用运行的端口 EXPOSE 8080 # 指定容器启动时执行的命令 ENTRYPOINT [java, -jar, /app/app.jar]构建Docker镜像在服务器上或本地安装了Docker的环境进入项目根目录。# 确保已执行 mvn clean package docker build -t pharmacy-system:1.0 .运行Docker容器需要将外部配置文件挂载到容器内并连接宿主机的MySQL。# 假设外部配置文件在 /home/app/config/application.yml # 运行容器映射端口挂载配置并连接到宿主机的网络方便访问宿主机MySQL docker run -d \ --name pharmacy-app \ -p 8080:8080 \ -v /home/app/config:/config \ --network host \ # 简单起见使用host网络容器直接使用localhost访问宿主机MySQL pharmacy-system:1.0 \ --spring.config.location/config/application.yml注意application.yml中的数据库url需要改为jdbc:mysql://localhost:3306/pharmacy_db?...因为容器使用了host网络。6. 常见问题与排查思路安装调试核心在部署和运行过程中你几乎一定会遇到以下问题。不要慌按照这个思路排查。问题现象可能原因排查方式解决方案启动报错APPLICATION FAILED TO START1. 数据库连接失败用户名/密码错、地址错、数据库不存在2. 端口被占用3. 依赖包下载不全或冲突1. 检查控制台错误日志通常有详细描述。2. 检查application.yml配置。3. 运行netstat -anp | grep 8080(Linux)或netstat -ano | findstr 8080(Windows)查端口。1. 核对数据库配置确保数据库服务已启动。2. 修改server.port或停止占用端口的进程。3. 删除本地Maven仓库(~/.m2/repository)中相关依赖重新mvn clean compile。访问登录页空白或4041. 静态资源路径错误2. Thymeleaf模板解析失败3. 控制器请求映射路径不对1. 检查浏览器开发者工具Console和Network标签。2. 检查templates和static目录位置是否正确。3. 检查LoginController的GetMapping(/login)注解。1. 确保静态资源在src/main/resources/static/下。2. 确保HTML文件在src/main/resources/templates/下。3. 重启应用确保Thymeleaf缓存关闭(spring.thymeleaf.cachefalse)。登录失败但数据库用户存在1. 密码加密方式不匹配2. Session未正确配置3. 数据库字符集问题导致查询不到1. 在Service的login方法中打印加密前后的密码对比。2. 检查用户表中存储的密码是否是MD5密文。1. 统一密码加密逻辑。初次可尝试在数据库手动插入一条MD5加密的密码记录用于测试。2. 检查数据库和连接字符串的字符集是否为utf8mb4。新增/修改数据后页面没变化1. 数据库事务未提交开发环境2. MyBatis一级/二级缓存少见3. 前端JS错误导致请求未发出1. 直接在数据库客户端查询确认数据是否插入。2. 查看浏览器Network请求是否成功状态码200。1. Service方法确保添加了Transactional。2. 在Mapper方法上使用Options(flushCache FlushCachePolicy.TRUE)如需。3. 修复前端JS代码。服务器部署后无法访问1. 服务器安全组/防火墙未开放端口2. 应用启动失败3. 数据库连接地址错误用了localhost1. 在服务器内用curl localhost:8080测试。2. 查看应用日志tail -f app.log。3. 检查服务器MySQL是否允许远程连接。1. 阿里云/腾讯云控制台安全组规则添加入站规则允许8080端口。2. 将数据库url中的localhost改为127.0.0.1或内网IP。3. 修改MySQL的bind-address为0.0.0.0并授权远程用户生产环境慎用。7. 代码讲解与二次开发建议读懂代码是修改和扩展的基础。除了前面讲解的模块这里再提供几个关键的代码阅读和修改切入点供你答辩时展示或进行功能扩展。7.1 如何添加一个新的管理模块例如“供应商管理”这是一个标准的CRUD开发流程可以帮你巩固MVC分层思想设计数据库表在pharmacy.sql中增加supplier表。创建实体类在entity包下创建Supplier.java定义字段并用Lombok的Data注解。创建Mapper接口在mapper包下创建SupplierMapper.java继承BaseMapperSupplier。创建Service接口和实现类在service包下创建SupplierService接口在service.impl包下创建SupplierServiceImpl实现类注入SupplierMapper实现增删改查方法。创建Controller在controller包下创建SupplierController.java使用RestController如果前后端分离返回JSON或Controller如果用Thymeleaf返回页面。定义/supplier/**相关的请求映射方法调用SupplierService。创建前端页面在resources/templates下创建supplier.html列表页、supplier_form.html表单页使用Thymeleaf语法和JS调用Controller接口。7.2 集成Redis缓存药品分类信息如果药品分类如处方药、非处方药不常变化可以缓存到Redis提升查询速度。添加依赖在pom.xml中加入Spring Boot Redis Starter。dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-data-redis/artifactId /dependency配置Redis在application.yml中配置Redis连接。spring: redis: host: localhost port: 6379 password: # 如果有 database: 0使用缓存在DrugCategoryService的方法上添加注解。Service public class DrugCategoryServiceImpl implements DrugCategoryService { Autowired private DrugCategoryMapper categoryMapper; Cacheable(value categoryCache, key allCategories) // 缓存结果 Override public ListDrugCategory getAllCategories() { return categoryMapper.selectList(null); // 模拟耗时查询 } CacheEvict(value categoryCache, key allCategories) // 更新数据时清除缓存 Override public boolean updateCategory(DrugCategory category) { return categoryMapper.updateById(category) 0; } }7.3 使用ECharts实现销售数据统计图表这是一个能极大提升毕设视觉效果的扩展点。引入ECharts在HTML页面中通过CDN引入ECharts JS库。创建数据接口在SaleController中创建一个新的接口返回指定时间段的销售统计数据JSON格式。GetMapping(/api/sale/statistics) ResponseBody // 返回JSON数据 public MapString, Object getSaleStatistics(RequestParam String startDate, RequestParam String endDate) { // 调用Service查询startDate到endDate之间的每日销售额 ListSaleStatisticVO list saleService.getSaleStatisticByDate(startDate, endDate); MapString, Object result new HashMap(); result.put(dates, list.stream().map(SaleStatisticVO::getDate).collect(Collectors.toList())); result.put(amounts, list.stream().map(SaleStatisticVO::getTotalAmount).collect(Collectors.toList())); return result; }前端调用并渲染在管理后台的仪表盘页面使用JavaScript调用上面的接口获取数据并用ECharts绘制折线图或柱状图。8. 毕业设计答辩要点与最佳实践基于这个项目进行答辩你需要注意以下几点这能让你从众多同学中脱颖而出吃透自己的代码老师可能会随机指着一行代码问你“这是做什么的”、“为什么这么写”。你必须能解释清楚每一层的作用、每一个注解的含义、关键的业务逻辑如库存扣减的并发处理。清晰阐述架构能画出一个简单的系统架构图说明前端、Controller、Service、Mapper、数据库是如何交互的。能说出为什么用SpringBoot、MyBatis-Plus它们带来了什么好处。突出业务复杂性不要只说“实现了增删改查”。重点讲解库存管理中的批次与有效期、销售与采购对账、会员折扣体系等体现你思考深度的业务点。展示扩展功能如果你按照7.2或7.3做了扩展一定要重点演示和讲解。这证明了你的学习能力和工程能力。准备部署文档准备一份简洁的README.md放在项目根目录说明如何配置、构建和运行项目。在答辩时展示显得非常专业。诚实面对不足如果被问到没实现的功能或已知的缺陷如高并发下库存超卖不要回避。可以坦诚说明这是课程设计的简化版本并给出可行的改进思路如使用数据库悲观锁、Redis分布式锁、消息队列削峰等。这个基于SpringBoot的药店管理系统项目为你提供了一个绝佳的Java Web全栈实践机会。它涵盖了从技术选型、数据库设计、后端开发、前端展示到服务器部署的完整链路。希望这篇超过5000字的详细解析不仅能帮你顺利运行这个项目更能引导你深入理解每一行代码背后的设计思想最终交出一份令自己满意的毕业设计。建议你将本文作为开发手册收藏在遇到问题时随时回顾排查思路。

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

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

免费获取报价