资讯动态

SpringBoot药店管理系统开发实战与架构解析

发布时间:2026/8/9 1:39:50 来源:尧图企业网站定制
1. 项目概述药店管理系统的核心价值这个基于SpringBoot的药店管理系统是我去年指导的一个本科毕业设计项目经过多次迭代现在已经发展成一个功能完善的商业级应用。它完美解决了中小型药店在药品进销存、会员管理、线上销售等环节的痛点。相比市面上动辄上万的商业软件这个系统不仅开源免费还采用了当前最主流的Java技术栈特别适合计算机专业学生作为毕业设计选题。系统最核心的优势在于将传统药店业务全面数字化。我见过太多药店还在用Excel表格记录库存用纸质会员卡管理客户这不仅效率低下还容易出错。而这个系统实现了从药品采购、入库、销售到财务统计的全流程自动化管理药店老板通过一个后台就能掌握所有经营数据。2. 技术架构解析2.1 SpringBoot框架选型考量选择SpringBoot作为基础框架是经过深思熟虑的。首先它对新手友好自动配置特性让初学者不用花费大量时间在环境搭建上。我们团队实测从零开始到第一个接口跑通用SpringBoot只需要15分钟而用传统SSM框架至少需要半天。其次SpringBoot的starter机制完美支持了我们需要的所有功能模块spring-boot-starter-data-jpa 用于药品数据持久化spring-boot-starter-security 处理权限控制spring-boot-starter-thymeleaf 实现管理后台页面spring-boot-starter-mail 用于发送订单通知提示在pom.xml中引入这些starter时建议统一管理版本号。我们使用spring-boot-dependencies作为父项目确保所有依赖版本兼容。2.2 数据库设计要点药品管理系统的数据库设计有几个关键点需要注意药品表(medicine)需要包含特殊字段CREATE TABLE medicine ( id bigint NOT NULL AUTO_INCREMENT, name varchar(100) NOT NULL COMMENT 药品通用名, spec varchar(50) NOT NULL COMMENT 规格, batch_number varchar(50) COMMENT 批号, approval_number varchar(100) COMMENT 批准文号, production_date date COMMENT 生产日期, expiry_date date NOT NULL COMMENT 有效期至, stock int NOT NULL DEFAULT 0 COMMENT 库存数量, price decimal(10,2) NOT NULL COMMENT 售价, PRIMARY KEY (id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4;特别注意药品有效期管理Scheduled(cron 0 0 0 * * ?) // 每天凌晨检查 public void checkExpiryMedicine() { LocalDate warningDate LocalDate.now().plusMonths(3); ListMedicine medicines medicineRepository.findByExpiryDateBefore(warningDate); medicines.forEach(med - { String msg String.format(药品%s(批号:%s)将在%s过期, med.getName(), med.getBatchNumber(), med.getExpiryDate()); emailService.sendExpiryWarning(msg); }); }3. 核心功能实现细节3.1 药品进销存管理药品管理是系统的核心模块我们实现了完整的CRUD操作和几个特色功能智能预警机制库存低于安全值时自动提醒补货近效期药品提前3个月预警滞销药品分析30天无销售自动标记批次管理实现public void addStock(Long medicineId, String batchNumber, LocalDate productionDate, LocalDate expiryDate, int quantity) { Medicine medicine medicineRepository.findById(medicineId) .orElseThrow(() - new BusinessException(药品不存在)); MedicineBatch batch batchRepository.findByMedicineIdAndBatchNumber(medicineId, batchNumber) .orElseGet(() - { MedicineBatch newBatch new MedicineBatch(); newBatch.setMedicineId(medicineId); newBatch.setBatchNumber(batchNumber); newBatch.setProductionDate(productionDate); newBatch.setExpiryDate(expiryDate); return batchRepository.save(newBatch); }); batch.setQuantity(batch.getQuantity() quantity); batchRepository.save(batch); medicine.setStock(medicine.getStock() quantity); medicineRepository.save(medicine); }3.2 会员管理系统我们设计了多层次的会员体系普通会员基础信息管理、消费记录查询VIP会员专属折扣、生日优惠处方药会员特殊购药权限管理会员积分算法实现public int calculatePoints(BigDecimal amount, MemberLevel level) { int basePoints amount.multiply(BigDecimal.TEN).intValue(); switch (level) { case VIP: return (int)(basePoints * 1.5); case NORMAL: default: return basePoints; } }4. 典型问题解决方案4.1 药品名称模糊搜索优化初期使用JPA的like查询性能很差我们通过以下方案优化添加数据库索引ALTER TABLE medicine ADD FULLTEXT INDEX idx_name_spec (name, spec);使用原生SQL查询Query(value SELECT * FROM medicine WHERE MATCH(name,spec) AGAINST(?1 IN BOOLEAN MODE), nativeQuery true) ListMedicine fullTextSearch(String keyword);4.2 高并发库存扣减解决超卖问题的三种方案对比方案实现复杂度性能适用场景乐观锁中高冲突较少时悲观锁低中强一致性要求Redis原子操作高极高秒杀场景我们最终选择乐观锁实现Transactional public boolean reduceStock(Long medicineId, int quantity) { Medicine medicine medicineRepository.findById(medicineId) .orElseThrow(() - new BusinessException(药品不存在)); if (medicine.getStock() quantity) { return false; } int updated medicineRepository.reduceStockWithVersion( medicineId, quantity, medicine.getVersion()); return updated 0; }5. 系统部署与扩展5.1 多环境配置SpringBoot的profile特性让我们可以轻松管理不同环境配置# application-dev.yml spring: datasource: url: jdbc:mysql://localhost:3306/pharmacy_dev username: devuser password: dev123 # application-prod.yml spring: datasource: url: jdbc:mysql://prod-db:3306/pharmacy_prod username: ${DB_USER} password: ${DB_PASSWORD} mail: host: smtp.exmail.qq.com properties: mail.smtp.ssl.enable: true5.2 前后端分离方案虽然系统默认使用Thymeleaf模板引擎但我们预留了API扩展点添加统一响应封装RestControllerAdvice public class ResponseAdvice implements ResponseBodyAdviceObject { Override public boolean supports(MethodParameter returnType, Class? extends HttpMessageConverter? converterType) { return true; } Override public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class? extends HttpMessageConverter? selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) { if (body instanceof ApiResponse) { return body; } return ApiResponse.success(body); } }配置Swagger文档Bean public Docket api() { return new Docket(DocumentationType.SWAGGER_2) .select() .apis(RequestHandlerSelectors.basePackage(com.pharmacy.controller.api)) .paths(PathSelectors.any()) .build() .apiInfo(apiInfo()); }这个项目从毕业设计起步现在已经发展成一个功能完善的商业系统。我在开发过程中最大的体会是一个好的管理系统不在于功能有多复杂而在于能否真正解决用户的痛点。药店老板最关心的是库存是否准确、销售数据是否直观我们的系统正是围绕这些核心需求展开的。

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

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

免费获取报价