news 2026/5/1 9:28:39

药房管理系统毕业设计:从零实现一个高内聚低耦合的入门级架构

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
药房管理系统毕业设计:从零实现一个高内聚低耦合的入门级架构


药房管理系统毕业设计:从零实现一个高内聚低耦合的入门级架构


1. 背景痛点:为什么“能跑就行”的代码在答辩时总被怼?

做毕业设计时,很多同学把“药房管理系统”当成“药品 CRUD 大合集”:一个DrugController里塞满增删改查,SQL 拼在 Java 字符串里,前端把表格数据一股脑儿v-for出来。结果演示时老师一句“如果药库管理员和售药师权限分开怎么做?”直接原地社死。

典型症状总结如下:

  • 功能堆砌:业务代码、权限判断、数据校验全写在 Controller,方法行数飙到 300+。
  • 硬编码:数据库连接、文件上传路径、角色名称直接static final写死,换环境就崩。
  • 安全裸奔:拼接 SQL、返回全字段实体、未做参数过滤,Postman 一把梭就能删库。
  • 无扩展点:药品字段加个“保质期”要改 5 张表 3 层代码,牵一发动全身。

毕业设计不是“能跑就行”,而是“跑得快、改得动、讲得清”。下面给出一条最小可运行、又足够拆分的架构路线,Spring Boot + MyBatis + Vue,3 天可搭出骨架,1 周能写 PPT。


2. 技术选型:为什么不是 Django / JSP / 纯 SSR?

技术放弃理由选择理由
DjangoPython 语法简洁,但国内药房项目主流是 Java 技术栈,后续二开、接入医保接口时 Java 生态更香
JSP + Servlet模板与后端高耦合,前端同学无法并行开发;IDE 支持弱,调试效率低
Spring Boot自带 IOC、AOP、Starter,一键跑起内嵌 Tomcat,Maven 依赖管理成熟
MyBatis比 JPA 易控 SQL,药房报表字段多且复杂,需要手写多表关联
Vue3 + ElementPlus组件化开发,双向数据绑定,打包后纯静态文件,与后端仅通过 JSON 交互,真正做到前后端分离

一句话:Java 系毕业设计,Spring Boot 是“默认答案”;MyBatis 让你写 SQL 不慌;Vue 让页面不再刷新全屏白。


3. 核心模块拆解:高内聚低耦合从“分包”开始

3.1 项目结构(仅列关键目录)

text com.example.pharmacy ├─ common // 全局异常、分页、常量 ├─ config // MyBatis、Swagger、Cors、RBAC 配置 ├─ controller // 仅接收与校验参数,一行代码不写业务 ├─ service // 接口 + 实现,事务在此层开 ├─ mapper // MyBatis XML 与接口 ├─ domain // PO + DTO + VO,每层只看到自己需要的数据 └─ security // SpringSecurity + JWT,RBAC 模型

3.2 药品库存管理——“只写库存,不管卖”

业务场景:药库管理员做采购入库、盘亏盘盈;售药师做销售出库。两个角色看到的数据一样,但操作按钮不同。

  1. 表设计
    drug(药品字典) ← 1:N →drug_stock(批次库存,含生产日期、有效期、数量)

  2. 关键接口

    • POST /api/stock/in入库
    • PUT /api/stock/check盘点
    • GET /api/stock/page库存列表(带有效期预警 ≤ 90 天)
  3. 代码片段(Java)

@RestController @RequestMapping("/api/stock") @RequiredArgsConstructor public class StockController { private final StockService stockService; @PostMapping("/in") public R<Void> stockIn(@Valid @RequestBody StockInDTO dto){ // 1. 参数校验由 @Valid + DTO 注解完成 // 2. 业务逻辑下沉到 service,Controller 仅做路由 stockService.saveStockIn(dto); return R.ok(); } } @Service public class StockServiceImpl implements StockService { private final DrugStockMapper drugStockMapper; private final DrugMapper drugMapper; @Override @Transactional(rollbackFor = Exception.class) public void saveStockIn(StockInDTO dto){ // 1. 根据药品 ID 查字典,不存在抛 BizException Drug drug = drugMapper.selectById(dto.getDrugId()); if (drug == null) throw new BizException("药品不存在"); // 2. 构造库存记录 DrugStock stock = new DrugStock(); stock.setDrugId(dto.getDrugId()); stock.setBatchNo(dto.getBatchNo()); stock.setQuantity(dto.getQuantity()); stock.setExpireDate(dto.getExpireDate()); drugStockMapper.insert(stock); } }
  1. 前端 Vue 调用
// api/stock.js import request from '@/utils/request' export function stockIn(data) { return request({ url: '/api/stock/in', method: 'post', data }) } // views/stock/In.vue import { stockIn } from '@/api/stock' const submit = async () => { await stockIn(formModel) ElMessage.success('入库成功') }

Controller、Service、Mapper 各管一摊,后期想加“库存预警”只需在 Service 层写定时任务,不动 Controller。


4. 用户权限:RBAC 最简实现

  1. 五张表
    userrolepermission,中间表user_rolerole_permission
    用户表存usernamepassword(BCrypt)、enabled

  2. SpringSecurity 配置要点

@Configuration @EnableGlobalMethodSecurity(prePostEnabled = true) public class SecurityConfig { @Bean public PasswordEncoder passwordEncoder(){ return new BCryptPasswordEncoder(); } }
  1. 方法级鉴权——售药师不能入库
@PreAuthorize("hasAuthority('stock:in')") @PostMapping("/in") public R<Void> stockIn(@Valid @RequestBody StockInDTO dto){ ... }
  1. Vue 侧动态菜单
    登录后GET /api/user/info返回permissions: ['stock:in','drug:sale'],前端根据权限过滤路由表,按钮级用v-has自定义指令。

5. 安全性三板斧

  • 参数校验:DTO +javax.validation注解,拒绝 SQL 拼接。
  • SQL 注入:MyBatis#{}占位,杜绝${}拼接。
  • 越权访问:RBAC +@PreAuthorize,并在 XML 层加tenant_id等字段隔离数据。

6. 生产环境避坑指南

  1. 数据库连接池
    默认HikariCP足够,毕业设计并发低,但一定把minimum-idle设 5 以上,避免 MySQL 8 小时自动断开。

  2. 静态资源缓存
    Vue 打包后dist/放 Nginx,location ~* \.(js|css|png)$ { expires 30d; },回锅肉式提速。

  3. 配置外置
    application.ymlspring.datasource.url${DB_URL},服务器启动脚本加-DDB_URL=xxx,防止账号密码提交到 GitHub。

  4. 日志分级
    logback-spring.xmlcom.example.pharmacy.mapper=DEBUG,生产环境改为 INFO,避免控制台刷 SQL 暴露字段。


7. 进阶思考:把“毕业”做成“产品”

  1. 处方审核流
    医生端开方 → 药师端审核(状态机:待审核/已驳回/已通过)→ 售药出库。可引入 Flowable 轻量级工作流。

  2. 库存预警
    定时任务扫drug_stock表,近效期 ≤ 30 天自动发邮件给管理员;低于安全库存时钉钉 Webhook 提醒采购。

  3. 批次追溯
    给每盒药贴二维码,出库扫码记录sale_itemdrug_stock_id,实现“一批次一去向”,方便召回。

  4. 接入医保
    国家医保接口基于 HTTPS + 数字签名,先把签名工具类封装好,后续直接插拔。



写在最后

整套代码不到 2k 行,却能把“药品字典—库存—销售—权限”串成闭环。答辩时老师若问“如果以后增加连锁门店怎么改?”你可以指着 Service 层说:“门店当租户字段下沉到各表,加一层 Mapper 拦截即可,Controller 不用动。”——这就是低耦合带来的底气。

毕业设计不是终点,把代码推到云服务器,真刀真枪地让家人朋友的药店试用,才是把“学分”升级成“作品”的开始。祝你一次过答辩,早日把项目写进简历,面试时谈笑风生。


版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/1 6:26:26

CARLA自定义模型导入实战:从Blender到仿真环境的完整流程解析

CARLA .co n CARLA 原生车库里的那几十辆车&#xff0c;对日常调试感知算法或许够用&#xff0c;可一旦你想验证快递小车、园区清扫车&#xff0c;或者自己设计的异形无人艇&#xff0c;就会发现“官方套餐”根本不够用。更糟的是&#xff0c;同一辆车跑在 0.9.14 与 0.9.15 里…

作者头像 李华
网站建设 2026/5/1 6:22:50

在Eclipse上基于JavaWeb的毕业设计:新手入门实战与避坑指南

在Eclipse上基于JavaWeb的毕业设计&#xff1a;新手入门实战与避坑指南 背景痛点&#xff1a;为什么第一步总是卡住 做毕设最怕“Hello World”都跑不起来。我帮学弟们远程调过最多的问题&#xff0c;总结下来就三句话&#xff1a; 环境配置像拆盲盒——JDK、Tomcat、MySQL、…

作者头像 李华
网站建设 2026/5/1 6:29:04

基于Coze工作流构建高可用智能客服系统的AI辅助开发实践

背景痛点&#xff1a;规则客服的“三座大山” 过去两年&#xff0c;我先后维护过两套“祖传”规则客服&#xff1a;关键词 if-else 堆成山&#xff0c;意图识别准确率不到 65%&#xff0c;一旦用户换种说法就“已读不回”&#xff1b;多轮对话靠 session 里硬编码字段&#xf…

作者头像 李华
网站建设 2026/5/1 8:29:56

Python Chatbot开发实战:从零构建智能对话系统

1. 为什么你的 Chatbot 总被用户吐槽&#xff1f; 上线第一周&#xff0c;DAU 蹭蹭涨&#xff0c;可后台工单也同步飞涨&#xff1a; 情况 A——用户刚说完“帮我订张票”&#xff0c;下一秒追问“能改到明天吗&#xff1f;”&#xff0c;Bot 却反问“订什么票&#xff1f;”&…

作者头像 李华