news 2026/10/22 9:28:26

Spring Boot药房网上订购管理系统:从数据库设计到答辩全流程解析

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Spring Boot药房网上订购管理系统:从数据库设计到答辩全流程解析

带过不少学生的毕业设计,也评审过很多类似的商城类项目,说句实话,“恒爱药房网上订购管理系统”这种题目在每年的计算机毕业设计里出现频率非常高,但它恰恰是最容易被做砸、也最容易做得出彩的一类。很多同学一听“药房管理系统”就下意识觉得是普通的电商项目,把药品当成普通商品来做,结果答辩的时候被老师追问“处方药怎么处理”“库存和有效期怎么联动”就问住了。

这篇文章我不打算给你贴一堆没用的源码截图,而是以这套基于 Spring Boot 的药房网上订购管理系统为例,把从课题拆解、数据库设计、核心代码逻辑、联调部署到答辩准备这条完整链路讲透。项目本身用的是 Spring Boot + MySQL + MyBatis Plus + Vue 这套国内毕设最主流的技术栈,业务上覆盖了用户端浏览购药、购物车结算、订单管理,以及管理员端的药品上下架、库存管理、订单处理等模块。适合正在选题、已经开题但心里没底的计算机专业学生,也适合想快速复现一个完整 web 项目来充实简历的开发者,看完你能直接照着搭出一套能跑通、能答辩、敢写进简历的系统。

1. 项目整体定位与设计思路拆解

1.1 先想清楚:药房系统和普通电商系统的本质区别在哪

很多同学拿到题目第一反应是“照猫画虎做个商品列表加购物车”,但药房系统和卖衣服、卖数码产品的电商平台在业务逻辑上有几个要命的差异点,这些差异恰恰是你答辩时能站住脚的地方。

第一是商品属性的复杂度。药品除了名称、价格、图片这些常规字段之外,还必须有生产厂家、批准文号、生产日期、有效期、药品类型(处方药/非处方药)、剂型、规格、用法用量、禁忌、存储条件等一长串专业字段。这些字段不是摆着好看的,它们直接决定了管理系统里搜索、筛选、库存预警、订单校验等功能的实现方式。比如非处方药(OTC)可以直接下单购买,处方药就必须提示“需凭处方购买”,甚至要做上传处方单的功能——哪怕毕设里这个功能是模拟的,你也得把流程设计出来。

第二是库存和效期的联动管理。普通商品库存没了就是没货,药品库存还需要考虑有效期。同一批次临近过期的药和刚入库的药,在业务层面应该有不同的处理策略。毕设阶段你可以做一个简化版的预警:在库存表里记录每个批次的到期时间,后台首页显示“近效期药品列表”,系统自动标记距离到期不足三个月的批次。

第三是角色权限的多维性。这不是简单的“用户和管理员”两级权限,更合理的划分是三到四个角色:普通用户(买药)、药店管理员(管理药品和库存)、订单审核员(处理处方类订单),如果加上系统超级管理员就更完善了。每个角色看到的功能菜单、能执行的请求接口,都需要在后端做权限控制。

想清楚这三点再动手画原型,你的数据库表设计和接口设计才不会返工。

1.2 技术选型为什么要选 Spring Boot 全家桶

这套系统技术栈选型完全可以作为毕设答辩中“为什么这么选”的经典回答案例。核心选型如下:

后端:Spring Boot 2.7.x + MyBatis Plus + Spring Security(或 JWT 独立鉴权)前端:Vue 2 + Element UI 后台管理端,用户端可以用 Thymeleaf 服务端渲染,也可以直接用 Vue 页面数据库:MySQL 8.0构建工具:Maven开发环境:JDK 1.8 或 11

为什么这个组合是毕设黄金组合?我给你实在的分析。Spring Boot 的优势在于零配置起步、内嵌 Tomcat、自动装配,你不需要像 SSH 时代那样写一堆 XML 配置文件,一个注解就搞定一个服务,这对时间紧张的毕设阶段来说极其友好。MyBatis Plus 就更不必说了,它对单表 CRUD 几乎是零 SQL 开发,内置分页插件、条件构造器、代码生成器,写个基础增删改查就是几分钟的事。

Spring Security 和 JWT 二选一的话,我更推荐直接走 JWT + 拦截器这种轻量方案。原因很简单:你能在答辩时把 token 生成、校验、刷新这套流程讲清楚,比背 Spring Security 的过滤器链要容易得多,而且也更贴近企业里前后端分离项目的实际做法。当然,如果你想展示自己对安全框架的掌握,用 Spring Security + 自定义认证逻辑也是加分项。

数据库用 MySQL 的理由不用多讲,关系型数据库在处理订单、药品这种强一致性数据上是最稳的。表结构设计合理的话,后期扩展也方便。

我还要特意提醒一点:不要为了“显示技术含量”硬上微服务、中间件队列这类东西。毕设的核心是完整性和逻辑自洽,一个单体 Spring Boot 应用把业务做扎实,比搞一个分布式空壳要强十倍。真想在简历上写技术亮点,把 Redis 缓存、接口幂等性设计加进去就足够出彩了。

1.3 核心业务流的完整梳理

这套系统的业务流可以从两条主线来看,一条是用户购药主流程,一条是管理员运营管理流程。

用户主流程:注册登录 → 浏览药品分类/搜索关键字 → 查看药品详情 → 加入购物车 → 生成订单(选择收货地址、填写备注)→ 模拟支付 → 订单状态流转(待发货 → 已发货 → 已完成)→ 对订单进行确认收货和评价。

管理员主流程:登录后台 → 药品管理(新增、编辑、上下架、批量导入)→ 库存管理(入库登记、批次维护、效期预警)→ 订单管理(查看订单列表、处理发货、处理售后)→ 用户管理 → 数据统计(销量排行、销售趋势)。

这条流程梳理清楚之后,你再去划分前后端页面,功能清单就非常明确了。用户端核心页面包括:首页、药品列表页、药品详情页、购物车页、订单确认页、个人中心页(订单列表、收货地址、个人信息)。后台管理端核心页面包括:登录页、工作台(统计面板)、药品管理页、库存管理页、订单管理页、用户管理页、系统设置页。

2. 数据库设计与核心表结构剖析

2.1 药品表的设计:别把字段想简单了

药品模块是整个系统数据设计的重中之重。我见过很多同学上来就建一张drug表,字段就写id, name, price, stock, img五个,结果做到订单模块的时候发现不知道药品规格怎么写、不知道详情页放什么内容,又回头加字段——这就是典型的没想清楚就动手。

一张能支撑起药房业务的核心药品表,至少应该包含这些字段:

字段名类型说明
idbigint主键
drug_namevarchar(100)药品通用名
drug_codevarchar(50)药品编码(可用于扫码/检索)
category_idbigint关联分类表
approval_numbervarchar(50)批准文号
manufacturervarchar(100)生产厂家
drug_typetinyint1=处方药 2=OTC甲类 3=OTC乙类
dosage_formvarchar(20)剂型(片剂/胶囊/口服液等)
specvarchar(50)规格(如 0.25g*24片)
unitvarchar(10)计量单位(盒/瓶/袋)
pricedecimal(10,2)售价
stockint总库存量
descriptiontext药品描述
usage_tipvarchar(500)用法用量
taboovarchar(500)禁忌/注意事项
statustinyint1=上架 0=下架
imagevarchar(255)药品图片URL
create_timedatetime创建时间
update_timedatetime修改时间

注意几点。第一,price必须用 decimal 而不是 float,这个我之前带的学生里踩过坑,float 做金额计算会有精度问题,答辩时老师问到这一点你能答上来就是加分项。第二,drug_type单独用字段存,不要写到描述文本里,因为后面订单模块要根据这个字段做不同的处理逻辑。第三,stock字段代表的是汇总库存,但它不能替代批次库存表的功能,效期管理需要单独设计批次表。

2.2 商品分类与药品关联

分类表设计得灵活一点,这里有个小技巧:用自关联实现无限级分类。表结构很简单,id, parent_id, name, sort四个字段,后台管理分类时通过 parent_id 维护层级关系,查询时用递归或 MyBatis Plus 的 wrapper 逐级查询。

在实际开发中可能涉及的关联关系:一个分类下可以有多个药品,一个药品只能归属一个主分类。在药品列表页按分类筛选时,要处理“查一级分类时需要包含其所有子分类下的药品”这种情况。这个需求虽然不复杂,但是很多同学第一次做都会懵,建议直接在 SQL 里用where category_id in (select id from category where parent_id = xxx or id = xxx)解决,简单直接。

2.3 订单表与订单明细表的主从设计

订单相关表是整个系统里最需要讲清楚逻辑的部分,这部分你要能画出状态流转图并在答辩时直接讲出来。

订单主表orders的核心字段:

字段名类型说明
idbigint主键
order_novarchar(32)订单号(全局唯一)
user_idbigint下单用户
total_amountdecimal(10,2)订单总金额
pay_amountdecimal(10,2)实付金额
statustinyint0=待支付 1=待发货 2=已发货 3=已完成 4=已取消
receiver_namevarchar(50)收货人
receiver_phonevarchar(20)收货电话
receiver_addressvarchar(200)收货地址
remarkvarchar(500)订单备注
create_time / pay_time / ship_time / finish_timedatetime各节点时间

订单项明细表order_item:

字段名类型说明
idbigint主键
order_idbigint关联订单主表
drug_idbigint药品id
drug_namevarchar(100)药品名称(冗余存储,防止药品信息变更)
pricedecimal(10,2)下单时单价快照
countint购买数量
total_pricedecimal(10,2)小计

主从设计最重要的意义在于:订单一旦生成,订单项里的所有信息必须是快照。用户后续把药品改了名、改了价,甚至删除了,历史订单依然要能正确展示,这就是快照字段存在的意义。这个细节在答辩中非常加分,因为不是所有学生都能意识到。

2.4 购物车表设计

购物车表设计相对简单,id, user_id, drug_id, count, checked, create_time即可。但这里有一个需要提前想清楚的逻辑:购物车表里的药品数量和价格,在下单那一刻要以数据库实时数据为准,不能用前端传过来的价格瞎算。正确做法是后端根据购物车记录的 drug_id 重新查询药品最新价格和库存,再计算总金额。这一点既是为了数据一致性,也是安全性的要求——所有的价格都必须在后端计算,这是做电商类项目最基本的一条规矩。

2.5 库存批次与效期预警表

为了让系统在答辩时有“亮点”,我建议你再加上一张药品入库批次表drug_batch,字段包含id, drug_id, batch_no, expire_date, quantity, remain_quantity, create_time。每次入库登记一批药品,填写有效期。查询药品详情时,可以显示该药品各批次库存情况;后台可以写一个定时任务或者简单的接口,查询剩余有效期不足90天的批次,在首页以列表形式展示预警。

不要觉得这个功能是画蛇添足。对药房业务来说,效期管理是真实业务场景里的刚需,你在毕设里做了这个点,答辩时老师会觉得你不是在纯教科书式地写代码,而是真的理解了行业需求。

3. 核心功能模块实现与实操要点

3.1 JWT 登录鉴权:其实没你想的那么复杂

前后端分离项目里,JWT 鉴权是目前最普遍的做法。整个链路我用文字给你捋一遍:用户端输入用户名密码 → 后端验证通过后生成一个携带用户id、角色、过期时间的 token 返回给前端 → 前端把 token 存到 localStorage 或 sessionStorage → 每次请求在请求头里带上Authorization: Bearer token→ 后端写一个拦截器,对所有需要登录才能访问的接口做校验,解析 token,拿到当前用户信息,继续放行。

关键代码其实就那么几段。

用户登录接口的核心逻辑:

public Result login(String username, String password) { // 1. 根据用户名查用户 User user = userMapper.selectOne( new LambdaQueryWrapper<User>() .eq(User::getUsername, username)); // 2. 判断密码(MD5加盐或BCrypt) if (user == null || !bcryptPasswordEncoder.matches(password, user.getPassword())) { return Result.error("用户名或密码错误"); } // 3. 生成token String token = JwtUtil.createToken(user.getId(), user.getRole()); // 4. 返回给前端 return Result.success(token); }

自定义拦截器里校验 token:

public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { String token = request.getHeader("Authorization"); if (token != null && token.startsWith("Bearer ")) { token = token.substring(7); try { Claims claims = JwtUtil.parseToken(token); request.setAttribute("userId", claims.get("userId")); request.setAttribute("role", claims.get("role")); return true; } catch (Exception e) { // token 过期或非法 } } response.setStatus(401); return false; }

这段代码里隐含了几个值得在答辩时展开的点:为什么密码存 BCrypt 而不是明文、token 里放了什么信息、token 过期时间怎么设置、前端 token 没了怎么处理。每个点你都能延伸讲半分钟,整个答辩的节奏就带起来了。

3.2 药品模块:CRUD 不是重点,检索和筛选才是

药品管理模块表面上就是增删改查,但你真正需要花心思的是列表页的检索设计。用户端药品列表要支持三种检索方式:按分类浏览、按关键字搜索(名称/厂家/批准文号)、按价格或销量排序。用 MyBatis Plus 的 LambdaQueryWrapper 写起来非常流畅:

LambdaQueryWrapper<Drug> wrapper = new LambdaQueryWrapper<>(); if (StringUtils.hasText(keyword)) { wrapper.and(w -> w.like(Drug::getDrugName, keyword) .or().like(Drug::getManufacturer, keyword) .or().like(Drug::getApprovalNumber, keyword)); } if (categoryId != null) { wrapper.eq(Drug::getCategoryId, categoryId); } wrapper.eq(Drug::getStatus, 1); // 只查上架药品 wrapper.orderByDesc(Drug::getCreateTime); Page<Drug> page = drugMapper.selectPage(new Page<>(pageNum, pageSize), wrapper);

这段逻辑你最好能闭着眼写出来,因为它的扩展性很强。比如后续要加“按剂型筛选”“按处方类型筛选”,就是在现有 wrapper 上加一个 eq 条件而已。答辩时被问到“你的检索是怎么实现的”,你就从 LambdaQueryWrapper 的防注入机制开始讲,到组合条件构造,再到分页插件,一气呵成。

3.3 购物车与下单:状态管理的核心战场

购物车操作本身不复杂,无非是加购、修改数量、勾选、删除。真正的难点在结算下单这步,这里面涉及事务和并发。

我给一个完整的下单方法设计思路,每一步都有明确的业务意义:

@Transactional(rollbackFor = Exception.class) public Result createOrder(OrderCreateRequest req) { // 1. 根据用户id查出勾选的购物车记录 List<Cart> cartList = cartMapper.selectList( new LambdaQueryWrapper<Cart>() .eq(Cart::getUserId, userId) .eq(Cart::getChecked, 1)); if (cartList.isEmpty()) { return Result.error("购物车为空"); } // 2. 计算总金额,并逐项校验库存 BigDecimal totalAmount = BigDecimal.ZERO; List<OrderItem> itemList = new ArrayList<>(); for (Cart cart : cartList) { Drug drug = drugMapper.selectById(cart.getDrugId()); if (drug == null || drug.getStatus() == 0) { return Result.error("药品已下架:" + cart.getDrugName()); } if (drug.getStock() < cart.getCount()) { return Result.error("库存不足:" + drug.getDrugName()); } // 价格以后端实时查询为准 totalAmount = totalAmount.add(drug.getPrice().multiply(BigDecimal.valueOf(cart.getCount()))); // 组装订单明细快照 OrderItem item = new OrderItem(); item.setDrugId(drug.getId()); item.setDrugName(drug.getDrugName()); item.setPrice(drug.getPrice()); item.setCount(cart.getCount()); itemList.add(item); } // 3. 生成订单号 String orderNo = generateOrderNo(); // 4. 保存订单主表和明细 Orders order = new Orders(); order.setOrderNo(orderNo); // ... 设置收货人信息、金额 orderMapper.insert(order); orderItemMapper.batchInsert(order.getId(), itemList); // 5. 扣减库存 for (Cart cart : cartList) { drugMapper.reduceStock(cart.getDrugId(), cart.getCount()); } // 6. 清空购物车 cartMapper.deleteByIds(cartList.stream().map(Cart::getId).toList()); return Result.success(orderNo); }

这里我特别要强调两个坑。第一是事务注解@Transactional必须加上,否则订单创建到一半出异常,库存扣了订单没生成,这种脏数据被老师查出来会非常难看。第二是库存扣减不要用“先查后 set”的乐观更新方式,正确做法是写一条带条件的 SQL:update drug set stock = stock - #{count} where id = #{id} and stock >= #{count},通过影响行数判断是否扣减成功。这是防超卖的标准做法之一,你把这个写在代码注释里,老师一眼就看出你懂并发。

订单号生成也不要简单用时间戳,推荐格式是“日期 + 随机数 + 用户id后四位”,保证唯一性,也方便后续按订单号搜索。例如202406011532000123456。

3.4 订单状态的流转实现

订单状态的变更建议在后端定义一个状态机逻辑,不要允许前端随便传状态。所有状态变更都通过后端接口触发,比如用户点击取消订单、管理员点击发货、用户确认收货,各自对应独立的接口,接口里校验当前状态是否允许跳转。

举例:只有状态为“待发货”的订单,管理员才能执行发货操作;只有“已发货”的订单,用户才能确认收货。这种显式的状态校验,能有效避免数据错乱,也是你在代码规范上加分的地方。

3.5 后台管理模块的统计面板

后台首页的统计面板建议放这几个核心指标:今日订单数、今日销售额、累计用户数、药品总数、库存预警数量。利用 MyBatis Plus 写聚合查询很轻松,比如今日销售额就是查订单表中pay_time在今天的已完成或已发货订单,sum 金额字段。

如果想做得更有“深度”,可以再加一个近七日销售趋势的折线图,后端返回每日销售额列表,前端用 ECharts 渲染。这个方法数据量小、接口简单,但视觉效果非常能打,答辩演示的时候打开后台首页,直观的图表比文字描述强太多了。

4. 前后端联调与部署上线的实操记录

4.1 接口设计规范:少走弯路的统一约定

前后端联调阶段最容易出的问题是接口路径不统一、返回结构各写各的。我强烈建议你在写后端的时候就从第一个接口开始统一一个Result返回类,里面至少包含三个字段:code(状态码,200成功,400参数错误,401未登录,500服务器错误)、msg(提示信息)、data(业务数据)。前端每个请求都按这个结构解包,代码写起来极度省心。

接口路径也建议按模块统一前缀,比如所有用户端接口/api/user/**,所有后台管理接口/api/admin/**,所有药品和分类的查询接口/api/drug/**。这样的好处是拦截器配置时可以直接按前缀区分哪些接口需要登录、哪些接口需要管理员权限。

4.2 本地开发和打包部署

整个工程拆分两个项目:前端frontend(Vue 工程)和后端backend(Spring Boot 工程),本地开发时前端通过 Vite 代理把/api转发到后端 8080 端口,这样就避开了跨域问题。生产环境打包时用 Nginx 托管前端静态文件,同时把/api反向代理到后端服务。

Spring Boot 打包直接mvn clean package得到 jar 包,然后:

java -jar pharmacy-server.jar --spring.profiles.active=prod

数据库初始化脚本要写好,建库建表语句、测试数据、管理员账号都必须在 README 里写清楚。这一点特别提醒:答辩演示用的那台机器上,数据库连接地址、账号密码要提前确认,不然现场连不上库,整套演示直接崩盘,这种事故我每年都能见到。

4.3 演示数据的准备是门学问

别等到答辩前一天才想起来系统里没数据。提前准备好一套“看起来真实”的演示数据:20 种左右的药品,覆盖处方药和非处方药,每种药品配好图片(去图片网站找对应的药盒图)、规格、价格、库存;3 个测试用户账号;一批覆盖不同状态的订单(待支付、待发货、已发货、已完成各一两单);近效期预警数据也准备好两条。

演示的时候节奏也很关键。先走用户端完整闭环:注册/登录 → 检索药品 → 加购 → 下单 → 模拟支付。再切到管理员端:登录后台 → 看到首页统计面板的数据变化 → 处理发货 → 查看药品管理 → 展示新增药品 → 展示效期预警。整个流程 5 分钟内走完,核心功能全覆盖,老师问什么你都能现场操作演示,心里完全不慌。

5. 常见问题与排查技巧实录

这部分我把过去学生在做类似项目时踩过的坑集中整理一下,按问题现象、原因分析、解决思路列成速查表:

现象原因分析解决思路
启动报Failed to configure a DataSource数据库连接配置没写对,或者 MySQL 服务没启动检查application.yml的 url、账号密码,先试用数据库图形工具连接测试
前端请求接口 404拦截器把请求拦了,或接口路径和前端请求路径不一致浏览器 F12 看 Network 里实际请求路径,比对 Controller 的 RequestMapping
跨域请求失败前后端端口不一致且未配置代理或跨域开发环境首选 Vite 代理,不用额外配 CORS;如果非要配,后端加CorsFilter或在 Controller 类上标@CrossOrigin
登录后接口报 401token 没传到后端,或拦截器解析失败检查前端 axios 拦截器里是否统一附加了Authorization头;检查 JWT 解析的 key 是否一致
下单提示库存不足,但数据库里库存明明够扣减库存的 SQL 中条件写错,或事务内先查缓存后更新打印 SQL 日志,检查where条件,确认查库连接和更新连接是不是同一个事务
密码明文存在数据库被人吐槽没加密用 BCrypt 或 MD5 + 盐对密码加密,登录时用匹配函数校验
中文乱码数据库连接 url 缺少characterEncoding=utf8配置,或前端页面没设 charset数据库 url 加?useUnicode=true&characterEncoding=utf8,前端 html head 里加<meta charset="utf-8">

再补充两个我特别想强调的实战经验。

排查接口问题有一个万能套路:先看后端控制台日志,再看数据库里数据变没变,最后看前端控制台的请求返回。这个顺序不要反。很多同学上来就去改前端代码,折腾半天最后发现是后端接口路径写错了。用二分法缩小范围:浏览器直接访问后端接口地址(比如http://localhost:8080/api/user/login),如果后端返回 JSON 正常,说明接口没问题,问题在前后端之间的代理或请求封装上;如果后端直接访问也报错,那就从 Controller → Service → Mapper 一层层往下查日志。

另外,MyBatis Plus 的 SQL 日志一定要打开。在application.yml里配置:

mybatis-plus: configuration: log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

开了这个之后,所有执行 SQL 的场景都会在控制台打印出完整 SQL 和参数。这一步能帮你定位 90% 的数据库相关 bug,我至今没遇到过比这更高效的排错手段。

6. 从毕业设计到简历项目:心态与扩展建议

6.1 简历上如何描述这个项目

很多同学做完项目不知道怎么往简历上写,要么只写一句“开发了一个药房管理系统”,要么把 Spring Boot 全家桶的所有技术名词全堆上去,这两种都很吃亏。

一个比较有效的写法是把项目拆成三块:业务上写清楚解决了什么问题(“实现药品线上选购、库存批次管理与效期预警”),技术上写清楚用了什么方案解决什么难点(“基于 JWT 实现前后端分离的无状态鉴权”“通过数据库乐观锁与事务保证订单库存一致性”),工程上写清楚你做了什么额外的东西(“统一封装 Result 返回体与全局异常处理”“编写数据库初始化脚本与管理端统计图表”)。

我建议沟通表达时,主动把并发扣减库存、订单快照、角色权限这些细节讲出来。面试官问“你这个项目遇到的最大难点是什么”,这套系统里你能讲的东西太多了,完全不怕没话聊——前提是你真的自己动手写过,而不是纯抄代码。

6.2 值得扩展的三个方向

如果时间充裕,或者你想把项目做成一个可以长期挂在简历上的作品,下面几个方向投入产出比很高。

第一个方向是接入 Redis。用 Redis 缓存热门药品列表、药品详情,减轻数据库查询压力;用 Redis 实现购物车的临时存储。这个扩展在技术上很成熟,写起来也不难,但讲出来非常加分,因为缓存几乎是企业级后端开发的标配话题。

第二个方向是文件上传与图片管理。药品图片如果现在还走本地静态资源托管,可以升级成统一的文件上传接口,上传后返回 URL 存入数据库。涉及前端 formData 上传、后端 MultipartFile 处理、静态资源映射,一整套流程学下来很值。

第三个方向是数据的定期备份与导出。后台增加一个“订单数据导出 Excel”功能,用 EasyExcel 导出订单列表,这个功能看着简单,却能在未来工作场景中直接用上。写过一次你就知道 Excel 模板填充、数据转换、响应头设置这些细节是怎么回事了。

我个人在做类似项目时的体会是:毕设的价值不在于题目本身新不新,而在于你有没有把一条业务线从头到尾走通。药房这件事虽然听起来不“高大上”,但里面涉及的权限体系、库存一致性、快照语义、状态机流转,全是工程实战中反复出现的问题。把这套系统真正做扎实了,你收获的远远不止一个“通过”的答辩,而是一次完整的、能复用的业务系统建设经验。

如果后面你还想在这套系统上加微信小程序端,或者把订单配送对接上第三方快递查询接口,欢迎在评论区聊,我后续可以单独出一篇扩展实战。

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

RAG与Agent实战:流式输出原理、实现与避坑指南

1. 这周我们聊什么&#xff1a;RAG链路里的流式输出到底解决什么问题先给还没跟上系列进度的朋友交代一下背景。前两周我们分别把RAG&#xff08;检索增强生成&#xff09;的文档切分、向量化、召回排序过了一遍&#xff0c;也把Agent的工具调用、记忆机制捋了个大概。这周内容…

作者头像 李华
网站建设 2026/10/22 9:26:33

Ubuntu系统盘制作与安装全攻略:从启动盘到双系统避坑指南

1. 为什么还要折腾系统盘制作这件事 很多人第一次接触 Ubuntu 安装&#xff0c;脑子里冒出来的第一个念头是“我直接下载个 ISO 双击不就行了吗”。如果你只是想在虚拟机里跑一下&#xff0c;那确实可以这么干&#xff0c;但一旦涉及到真机安装、系统重装、给旧电脑续命、或者给…

作者头像 李华
网站建设 2026/10/22 9:26:31

微服务IM消息存储子服务重构实践:分表、幂等与压测全解析

1. 项目背景与核心需求拆解 前阵子我把一套微服务即时通讯系统里的消息存储子服务完整重构了一遍&#xff0c;顺带把功能测试和性能压测也重新理了一轮。这个子服务看着不起眼&#xff0c;但在整个IM架构里属于那种“平时没人夸、出故障全组遭殃”的基础设施。这篇文章就把我当…

作者头像 李华
网站建设 2026/10/22 9:23:58

从零搭建Harbor私有镜像仓库:容器部署与运维实战指南

去年我把旧服务器淘汰的时候&#xff0c;第一反应就是把上面的Harbor私有仓库完整备份下来。那台机器上堆着我这三年攒的各种容器镜像&#xff0c;有编译缓存用的小基础镜像、不同版本的中间件、还有一堆标签写着"测试勿删"的自制包。不是说我有多爱折腾&#xff0c;…

作者头像 李华
网站建设 2026/10/22 9:23:12

Windows消息循环三剑客:GetMessage、TranslateMessage、DispatchMessage详解

1. 消息循环三剑客到底在干什么很多刚接触 Windows 桌面开发的朋友&#xff0c;第一次看到GetMessage、TranslateMessage、DispatchMessage这三个函数排成一排出现在WinMain里&#xff0c;脑子里基本是一片空白。教程告诉你“照抄就行”&#xff0c;但没人告诉你为什么非得是这…

作者头像 李华
网站建设 2026/10/22 9:23:02

AI编程助手失控?用技能框架+TDD契约+工程纪律终结代码雪崩

1. 先看看“氛围编程”翻车现场&#xff1a;代码雪崩到底从哪儿开始先说明一下&#xff0c;我这里的“氛围编程”不是贬低任何人&#xff0c;我也天天用 AI 编程助手写代码。但你必须承认&#xff0c;很多人已经把“让模型自动写代码”当成了默认工作方式&#xff1a;需求丢进去…

作者头像 李华