ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

Spring Boot茶叶电商系统从零搭建:架构、数据库与部署全攻略

Spring Boot茶叶电商系统从零搭建:架构、数据库与部署全攻略 做茶叶电商系统这个选题其实踩过不少坑。之前接过一个类似的项目客户要的不仅仅是能下单付款还要能管理茶叶的等级、产地、年份这些维度普通的电商模板根本撑不起来。后来基于Spring Boot从零搭了一套把商品属性、库存、订单流程都理顺了这才算真正落地。这篇就把整个系统的设计思路、数据库建模、部署步骤和常见问题整理成文给打算做茶叶商城或者正在做类似电商项目的朋友一个参考。1. 项目整体设计与技术选型1.1 为什么选择Spring Boot做茶叶商城茶叶商城本质上是电商系统但和通用电商相比它的业务属性更重一些。茶叶商品有品类绿茶、红茶、白茶、普洱等、产地不同山头、不同村寨、年份新茶、陈茶、等级特级、一级、二级、工艺炒青、烘青、晒青这些维度订单管理也涉及预售、拼团、礼盒定制等玩法。用Spring Boot来做看中的是它的生态成熟度和快速开发能力。Spring Boot解决了传统SSM框架配置繁琐的问题。以前搭一个SSM项目光配置文件就要写一大堆XML里各种bean定义、事务配置、数据源配置稍不注意就报错。Spring Boot用自动配置加约定大于配置的思路把大部分通用配置都内置了我只需要关注业务代码本身。对于茶叶商城这种业务逻辑复杂、迭代速度快的项目来说开发效率的提升是很明显的。另外一个选它的理由是社区生态。电商场景需要的安全框架Spring Security、缓存Redis、持久层MyBatis Plus、接口文档Swagger都有现成的整合方案不用自己造轮子。再加上它对前后端分离的支持很友好RESTful接口一写前端Vue或者小程序直接对接就行。1.2 系统的整体架构与技术栈构成这个茶叶商城系统采用前后端分离架构后端用Spring Boot作为核心框架前端提供RESTful API接口供Vue后台管理端和用户端调用数据存储使用MySQL缓存层使用Redis。核心技术栈层次技术选型用途说明前端展示Vue.js Element UI后台管理界面商品管理、订单处理、数据统计前端用户端微信小程序 / H5按需集成用户浏览商品、下单、支付、售后后端框架Spring Boot 2.x提供RESTful API业务逻辑处理持久层MyBatis Plus MySQL数据持久化ORM映射通用CRUD缓存Redis购物车数据、验证码、热门商品缓存安全框架Spring Security JWT用户认证与权限控制接口文档Swagger前后端联调接口测试构建工具Maven依赖管理项目构建打包这套架构不是随便选的。MyBatis Plus让我能快速实现大部分单表操作省掉大量写SQL的时间复杂统计查询再用自定义SQL去做。Redis缓存购物车是因为购物车读写频繁放数据库里压力大不说用户没登录时也不好处理放Redis里用设备标识做key体验好很多。Spring Security加JWT的组合是为了保证接口安全的同时兼顾前后端分离的无状态特性。用户登录后拿到token后续请求带上token即可服务端不需要保存session这在分布式部署的场景下很有优势。2. 核心功能模块拆解2.1 商品管理模块的设计要点商品模块是整个茶叶商城的基础设计得好不好直接影响后续的购物车、订单、库存联动。茶叶商品的信息结构比普通商品复杂。普通商品可能就是标题、价格、图片、库存茶叶还需要规格属性。我设计的时候把商品拆成两层商品主表spu和商品规格表sku。spu存的是商品通用信息比如茶叶名称、品类、产地、品牌、主图等sku存的是具体规格比如“500g散装”“200g礼盒装”对应的不同价格和库存。public class TeaProduct { private Long id; private String productName; // 商品名称 private Long categoryId; // 分类ID private String origin; // 产地 private String teaType; // 茶叶品类 private Integer grade; // 等级 private String harvestYear; // 年份 private String description; // 商品详情 private String mainImage; // 主图URL private Integer status; // 上下架状态 1上架 0下架 private Integer weight; // 重量克 }在类设计上TeaProduct是商品主表实体TeaSku是规格实体。分类表用树形结构设计支持二级分类比如“乌龙茶”下面还可以分“铁观音”“大红袍”“凤凰单丛”。后台管理中运营人员可以动态添加分类前端菜单就能自动更新。商品上下架和库存扣减是容易出问题的地方。商品SKU设计时要预留库存字段下单时扣减现货库存如果支持预售则额外设计预售库存字段。很多项目用减库存的方式发布商品时就把库存固定每次购买直接减这种方式并发高时会超卖所以我在下单模块使用了Redis预扣加MySQL最终扣减的双层方案后面订单部分会详细讲。2.2 用户端与后台分离的账户设计商城系统涉及两类用户前台购物的消费者和后台管理的运营人员。这两类人的权限完全不同划分开可以避免越权操作。用户端注册登录我支持手机号验证码和账号密码两种方式JWT生成token后返回给前端前端存到localStorage中每次请求带在Authorization头里。管理端不使用JWT用Spring Security的Session机制管理因为管理端是固定人员使用Session会话更方便强制下线、踢人这类操作。用户实体上有几个字段值得注意userLevel会员等级、points积分、status封禁状态。会员等级和积分为后续做营销活动留了口子比如黄金会员打95折下单送积分这种。权限控制上后台接口统一以/admin/**开头通过拦截器校验管理员token并且支持角色区分例如管理员和运营人员权限不同运营人员只能管理商品和订单管理员才有权限管理用户、查看财务报表。前端菜单根据角色动态渲染后端接口二次校验双保险。2.3 购物车与订单流程的完整闭环购物车模块我用Redis来实现。为什么不用数据库表因为购物车对于未登录用户也要能用。用户没登录时前端在本地生成一个设备ID以cart:{deviceId}为key存购物车数据登录后可以把本地的购物车数据合并到以cart:{userId}为key的缓存中。购物车数据结构用的是Redis的Hash类型field为商品SKU IDvalue为数量。这样一个用户的所有购物车项都在一个key下管理读取方便更新某个商品数量只需hset即可。每次加购时先查一下Redis中的数量和库存做比对保证不能超过库存上限。订单流程是整个系统最核心的部分我的设计如下用户提交订单后端接收到订单请求根据购物车选中的商品SKU在Redis中执行库存预扣decr命令原子操作防止超卖预扣成功则创建订单记录状态为待支付创建订单明细用户在一定时间内完成支付支付回调中更新订单状态为已支付超时未支付则关闭订单回滚Redis中预扣的库存支付完成后通知仓库发货订单状态变更为已发货用户确认收货后订单完成这个流程解决了超卖和僵尸订单两大问题。超卖靠Redis原子扣减解决僵尸订单靠定时任务扫描超时未支付订单自动关单并回滚库存。订单表的设计上我用了orders和order_items两张表。订单主表记录订单号、用户ID、总金额、状态、支付时间、收货信息等订单明细表记录每个SKU的购买数量、单价、快照名称。为什么要有快照名称因为商品名称和价格未来可能调整如果订单明细里不保存当时购买的商品名称和价格快照日后拉取历史订单会看到当前改过的名称引起售后纠纷。CREATE TABLE orders ( id bigint(20) NOT NULL AUTO_INCREMENT, order_sn varchar(64) NOT NULL COMMENT 订单编号, user_id bigint(20) NOT NULL COMMENT 用户ID, total_amount decimal(10,2) NOT NULL COMMENT 订单总金额, status tinyint(4) NOT NULL DEFAULT 0 COMMENT 订单状态 0待支付 1已支付 2已发货 3已完成 4已取消 5售后中, receiver_name varchar(50) DEFAULT NULL COMMENT 收货人, receiver_phone varchar(20) DEFAULT NULL COMMENT 收货电话, receiver_address varchar(255) DEFAULT NULL COMMENT 收货地址, pay_time datetime DEFAULT NULL COMMENT 支付时间, delivery_time datetime DEFAULT NULL COMMENT 发货时间, create_time datetime NOT NULL COMMENT 下单时间, PRIMARY KEY (id), KEY idx_user_id (user_id), KEY idx_order_sn (order_sn) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT订单主表;订单状态我用数字表示枚举值定义在代码里。很多初学者喜欢在数据库里存中文状态比如“待支付”“已支付”这种看着直观但后续做统计查询和状态流转很麻烦。保持数字存储加代码枚举映射是更规范的做法。3. 数据库设计与核心表结构3.1 茶叶商品属性建模的特殊考量数据库设计是整个系统的地基。茶叶商品不同于普通商品它的属性维度复杂如果只用一个商品表把所有字段堆上去扩展性会很差。我在建表时把商品信息拆分成几张表来管理。商品主表存公共属性属性表存茶叶的特定维度。为什么单独抽属性表因为不同品类的属性差异太大——普洱需要存山头和树龄岩茶需要存焙火程度绿茶需要存采摘时间如果都放在商品主表里表结构会变得非常臃肿而且很多字段对特定品类是无意义的空值。实际操作中我用product_attribute表以key-value的形式存储扩展属性每条记录包括商品ID、属性名、属性值。这样添加新属性不需要改表结构运营人员在后台就可以动态维护属性字典。查询时通过GROUP_CONCAT把属性拼成JSON返回给前端前端按需渲染。分类设计上采用父子级联的树形结构最多支持三级。一级分类绿茶、红茶、白茶、乌龙茶、黑茶、黄茶。二级分类比如乌龙茶下面有铁观音、武夷岩茶、凤凰单丛。三级分类用于更细的产地或品种区分比如武夷岩茶下面有大红袍、水仙、肉桂。3.2 订单表和库存表的关系设计库存表单独拆分设计成product_stock表以SKU ID为主键包含total_stock总库存、locked_stock锁定库存、available_stock可用库存三个字段。这里用三段式库存而不是简单的库存字段是为了支撑秒杀和预售场景。三段式库存的逻辑是总库存不变下单时锁定库存增加、可用库存减少支付成功后锁定库存不变因为货物已经确定卖出取消订单时锁定库存减少、可用库存增加。这样任何时候系统里都能清楚知道哪些货被预占了哪些货还能卖。-- 扣减可用库存前先判断是否充足 UPDATE product_stock SET locked_stock locked_stock #{count}, available_stock available_stock - #{count} WHERE sku_id #{skuId} AND available_stock #{count}这条SQL是关键。利用MySQL的行锁和条件判断在数据库层面保证不会出现超卖。虽然前面说了Redis预扣减但最终的库存校验还是要落到数据库这一层双重校验才稳妥。Redis处理高并发瞬间的流量数据库保证最终一致性。订单表与库存表的关联靠订单明细表来串联每个订单明细中都记录SKU ID和购买数量后续发货、退款、售后都要用到这个信息。3.3 数据库索引优化与常见性能坑茶叶商城的访问特点是读多写少用户大部分时间在浏览商品和搜索真正下单的比例很低。所以数据库优化重点在查询性能上。我建索引时遵循了几个原则商品表根据category_id和status建联合索引因为列表页的查询条件基本就是这两个字段加分页订单表根据user_id建索引个人中心查订单列表是最频繁的操作订单表根据status和create_time建联合索引用于后台按状态筛选订单和定时任务扫描超时订单SKU表商品规格表以product_id建索引查某个商品的所有规格时走索引很快商品列表页的分页查询如果数据量大用传统的LIMIT offset, size在深分页时性能会明显下降。我建议使用主键ID游标的方式分页即传入上一页最后一条记录的ID用WHERE id #{lastId} ORDER BY id LIMIT #{size}来查询性能稳定。不过这种方式的代价是只能按ID固定排序不能随意排序实际项目中可以折中处理。慢查询日志一定要开启。上线前把SQL都过一遍EXPLAIN扫全表的查询早点发现早点优化。茶叶商品的搜索功能如果商品数量到了十万级MySQL的LIKE模糊查询会力不从心到时候可以考虑接入Elasticsearch前期小规模时用LIKE就够。4. 环境部署与启动实操4.1 本地开发环境的准备步骤跑起这个项目之前需要把环境准备好。我推荐直接用统一的版本避免出现各种奇怪的兼容性问题。需要安装的工具JDK 1.8及以上Spring Boot 2.x对JDK 1.8支持最稳定不要一上来就装JDK 17跑老项目会有兼容问题MySQL 5.7或8.0RedisWindows下可以用微软移植版或者WSL方式运行生产环境建议用Linux版Maven 3.6IDEA或EclipseIDEA对Spring Boot支持更友好推荐使用环境版本的选择上通过踩坑总结出来的经验MySQL不要用8.0以下的版本5.7和8.0在SQL规范性上有差异项目的SQL是按5.7标准写的如果你用5.6可能有些查询语法不支持。Redis也别装太老的版本3.x的Redis有些指令不支持直接影响项目运行。4.2 数据库初始化和配置修改数据库这块我建议用命令行方式执行SQL脚本不要一上来就用Navicat可视化工具导入。为什么因为大部分SQL脚本是按特定顺序执行的包含建库、建表、插入基础数据Navicat有时候不会严格按脚本里的顺序执行容易报错。初始化步骤mysql -u root -p tea_shop.sql脚本执行完确认一下数据库中出现了预期的表。检查表数量是否和文档中说明的一致重点看看sys_user表里是否有默认管理员账号。接下来修改项目的配置文件application.yml主要改三处数据库连接信息、Redis连接信息、端口号。server: port: 8080 spring: datasource: url: jdbc:mysql://localhost:3306/tea_shop?useUnicodetruecharacterEncodingutf8useSSLfalseserverTimezoneAsia/Shanghai username: root password: your_password driver-class-name: com.mysql.cj.jdbc.Driver redis: host: localhost port: 6379 password: database: 0这里要注意serverTimezoneAsia/Shanghai这个参数一定要加。MySQL 8.0默认时区是UTC不加的话项目里所有时间字段会相差8个小时订单创建时间、支付时间全部不准排查起来很头疼。4.3 启动项目与功能自测清单配置改完之后在项目根目录执行mvn spring-boot:run即可启动或者用IDEA直接运行启动类。启动过程中留意控制台日志看到Started Application in X seconds就说明启动成功了。项目启动成功不代表功能正常我建议按下面的清单逐项自测一遍后台管理员登录是否正常登录后能否看到商品管理菜单添加一个测试商品包含品类、产地、年份、等级等属性确认商品列表能看到前台用户注册一个测试账号用该账号登录将测试商品加入购物车修改购物车数量确认库存联动正确提交订单生成待支付订单用模拟支付接口完成支付后台能看到已支付订单执行发货操作前台确认收货发起一次售后申请走完整个售后流程测试时发现的Bug优先排查后端接口日志Spring Boot的日志信息很完整异常栈打印出来基本能定位到问题行。接口测试推荐用Swagger项目集成了Swagger的话启动后访问http://localhost:8080/swagger-ui.html就能看到所有接口调试起来非常方便。前端如果也有完整代码需要先执行npm install安装依赖再npm run dev启动前端服务然后在浏览器中访问前端地址。前后端联调时注意接口地址配置前端项目的vue.config.js里通常配置了后端接口地址代理如果端口改了要同步修改。4.4 打包部署到服务器的操作记录本地开发完成后要把项目部署到服务器上让其他人能访问。Spring Boot打包极其简单用Maven的package命令项目target目录下会生成一个xxx.jar文件。mvn clean package -DskipTests打包时跳过测试避免因为测试环境配置缺失导致打包失败。jar包生成后使用nohup命令后台启动nohup java -jar tea-shop.jar --spring.profiles.activeprod tea-shop.log 21 生产环境的配置我建议用application-prod.yml单独维护里面使用生产数据库地址日志级别调整为WARN减少日志输出量。--spring.profiles.activeprod指定多环境配置文件的生效这样开发环境、测试环境、生产环境的配置互不干扰。部署到服务器之前还要把安全组规则和防火墙的8080端口开好不然外部访问不到。如果服务器有Nginx建议用Nginx做反向代理转发到Java应用的端口同时处理静态资源的缓存和HTTPS证书的配置。server { listen 80; server_name tea.example.com; location / { proxy_pass http://127.0.0.1:8080; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } }用Nginx代理的好处是将来如果需要扩展多个后端实例做负载均衡只需改Nginx配置即可无需改动应用代码。5. 常见问题与排查技巧实录5.1 数据库连接与中文乱码问题数据库连接报错是Java Web项目最常见的坑。常见的错误无非三种连不上数据库、认证失败、时区问题。连不上数据库先检查MySQL服务是否启动连接地址和端口是否正确然后用命令行mysql -u root -p手动连接一次排除MySQL本身的问题。认证失败检查用户名密码是否输入正确MySQL 8.0的认证插件是caching_sha2_password如果项目里用的是MySQL 5.7风格的驱动可能会有兼容问题。中文乱码这个问题几乎每个做商城项目的都会遇到。乱码通常出现在两个环节写入数据库时乱码和读取展示时乱码。写入乱码的根源是数据库连接参数里缺少characterEncodingutf8加上这个参数之后基本解决。读取乱码往往是页面编码问题开发时把前端所有文件的编码统一成UTF-8。MySQL建表时统一使用utf8mb4字符集它能存储emoji和生僻字比utf8更全面。有时候还会出现一种诡异的现象数据库中看到的中文正常但通过接口返回给前端时变成乱码。这种情况通常是HTTP响应头中没有设置正确的Content-Type造成的。在Spring Boot中只需要在配置文件中确认Spring MVC的编码是UTF-8默认情况下就是UTF-8如果改了配置才可能导致异常。5.2 端口占用和Redis连接失败的处理端口占用这个坑很基础但很常见。启动项目时提示Port 8080 was already in use说明8080端口被其他进程占用了。Windows下用命令行排查netstat -ano | findstr 8080这个命令会显示占用8080端口的进程PID然后在任务管理器中找到对应进程并结束或者改用其他端口启动项目。把application.yml里的server.port改成8081等未被占用的端口即可。不过如果你改了端口前端项目的接口代理也要同步改不然前端访问的还是8080。Redis连接失败报错信息通常是Unable to connect to Redis或者Connection refused。先确认Redis服务是否启动redis-cli ping如果返回PONG说明Redis运行正常问题出在项目配置上。检查配置里的spring.redis.host是否写对如果Redis设置了密码配置里的password字段必须填写不然认证阶段就被拒绝。如果Redis运行在远程服务器上需要确认服务器的6379端口在安全组中放行。5.3 库存超卖与订单状态不一致的排查思路运营一段时间后发现订单状态和库存对不上这是电商系统最头疼的问题。库存超卖的表现是用户下单成功了但最后发货时发现库存不足。这种问题的排查思路要从整个下单链路入手。先查订单创建时的库存日志如果系统里有库存流水表的话看哪个环节扣减库存异常。然后查Redis中的库存数据和MySQL中的product_stock表数据是否一致不一致的情况通常是因为直接修改了数据库导致缓存与数据不同步或者Redis中的key过期导致数据丢失。我经历过的库存不一致问题有一次是定时任务关闭超时订单时没有回滚Redis中的预扣库存导致Redis库存越减越少但MySQL中的可用库存数量没有同步减少。这种问题修复起来不算难但需要补充一条对账定时任务定期比对Redis缓存库存和MySQL库存数据一旦发现不一致就以MySQL为准进行修正。订单状态“卡住”不动比如一直是待支付状态可能是支付回调没有正确处理。支付回调接口需要保证幂等性同样一笔订单的支付回调可能被推送多次如果不做去重处理就可能把已支付的订单又更新一遍。我通常在支付回调处理前先查询订单状态只有当前状态是待支付时才更新为已支付状态已变更的直接忽略。下面把项目中常见的问题、原因和解决办法整理成一张速查表方便遇到问题时快速定位问题现象可能原因排查方法解决方案项目启动端口占用8080端口被其他程序占用netstat -ano | findstr 8080换端口或结束占用进程数据库连接超时URL配置错误、MySQL未启动命令行连接测试核对连接参数启动MySQL中文乱码连接参数缺编码、表字符集不对查看数据库字符集URL加characterEncodingutf8库表用utf8mb4登录后接口返回401Token过期或未携带查看请求Header重新登录获取token前端确保带Authorization库存超卖并发下单未做扣减控制查看库存流水使用Redis预扣减数据库条件更新订单一直待支付支付回调未触发查看支付日志确保回调地址可访问处理逻辑幂等Redis连接失败Redis未启动或密码不对redis-cli ping启动Redis核对密码配置文件上传失败路径配置不存在查看日志报错创建对应目录检查路径权限定时任务没生效未加EnableScheduling检查启动类注解在启动类上加开启定时任务注解5.4 前后端联调中的接口对接经验前后端分离的项目联调阶段是最耗时间的。后端把接口开发完了前端对接时经常因为字段名对不上、返回格式不一致而反复沟通。为了减少这种沟通成本项目中把统一返回格式做成一个类所有接口返回相同结构{ code: 200, message: 操作成功, data: {} }前端拿到统一的Response之后只需要在axios拦截器里处理一次code逻辑不需要对每个接口单独判断成功失败大大减少了重复代码。状态码定义要有语义200表示成功400表示参数错误401表示未登录403表示无权限500表示服务器异常。不要全部返回200然后在data里放一个字段表示成功与否这样前端处理起来非常别扭。接口定义时参数的命名规范也很重要。建议接口参数使用驼峰命名保持一致日期类型统一用时间戳或yyyy-MM-dd HH:mm:ss格式的字符串前端解析省事。接口文档用Swagger自动生成后端把注解写规范Swagger UI上就能直接调试前端开发照着文档调接口效率能提升很多。跨域问题是前后端联调的另一个痛点。前端开发服务器是8081端口后端是8080端口端口不同就存在跨域。解决方式有两种前端在开发环境配代理转发或者后端写一个WebMvcConfigurer实现跨域配置。我建议两种同时做前端代理用于本地开发后端跨域配置用于测试环境直连两边都打通以后部署到Nginx时同域名下就不存在跨域问题了。Configuration public class CorsConfig implements WebMvcConfigurer { Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping(/**) .allowedOriginPatterns(*) .allowedMethods(GET, POST, PUT, DELETE, OPTIONS) .allowedHeaders(*) .allowCredentials(true) .maxAge(3600); } }需要提醒的是allowedOriginPatterns不要直接用*生产环境存在安全风险这篇只是为了联调方便。正式上线时应该把前端域名写进去限制跨域来源。6. 从做项目到理解业务逻辑6.1 模块解耦与扩展预留的设计心得做商城项目最怕的是业务逻辑耦合在一起。举例来说下单要发通知通知要调短信服务如果短信服务的代码直接写在订单模块里以后换了短信服务商或者要改成微信通知就得去改订单模块的代码牵一发而动全身。所以我在设计时把各个功能做成独立的服务类订单模块只管订单通知模块通过同步调用发送站内信和短信两边通过接口通信互不干扰。商品模块同样预留了很多扩展位。茶叶的属性、分类、品牌都支持动态配置运营人员在后台就能加一个新的茶叶品类不需要改代码。促销模块我单独规划了接口支持优惠券和满减活动的扩展现在项目里实现了基础的优惠券功能以后要做秒杀、拼团这些只需要新增活动类型不影响现有订单逻辑。我在项目中实践了几个对长期维护很重要的习惯接口返回的Data对象尽量不用Map而是定义具体的VO类Service层只暴露业务方法事务控制加在Service层的方法上Controller层不写业务逻辑只做参数校验和结果封装。这些习惯让项目在需求不断变更时代码改动的范围始终控制在小范围内。6.2 系统上线后的运维与迭代建议项目开发完只是第一步真正的挑战在系统上线之后。日志管理和监控是运维的重中之重建议日志按照日期切分保留最近30天的日志方便排查问题时回溯。生产环境不要追求打印全部DEBUG日志输出量太大会严重影响系统性能。数据库备份策略要提前定好每天凌晨全量备份每6小时增量备份备份文件保留最近7天同时定期做恢复演练。我见过太多人只做了备份从没试过恢复真到需要恢复数据时才发现备份文件早就损坏了。迭代优化方向上有几件事值得优先做商品搜索引入全文检索购物车从Redis迁移到功能更强的方案订单状态机增加超时自动签收和退款自动审核管理端增加销售数据可视化报表。每一次迭代都要回归测试核心流程确保下单、支付、发货、售后这条主链路不出问题。7. 给新手的实用建议与避坑指南7.1 从运行项目到二次开发如何推进刚拿到这个项目源码先别急着读代码按这样的顺序推进效率最高先把项目跑起来。环境装好数据库初始化启动项目用Swagger把所有接口过一遍感受系统的整体功能。这一步的重点是让你对项目有一个整体的直观认识知道哪些接口对应哪些功能。然后根据前端页面梳理业务流程。从前台界面入手比如点击一个商品加入了购物车就去后端找到对应的Controller接口一路跟到Service实现类看它做了什么操作。通过一个完整的业务链路串起Controller、Service、Mapper三层代码比按包结构一个个类读更有效。最后才是深入细节。比如读订单状态机相关的代码弄清楚各个状态下系统允许执行什么操作不允许执行什么操作。理解了状态机就理解了整个订单模块的精髓。7.2 哪些坑我已经替你踩过了打包时容易踩的坑是把测试代码执行了一遍。项目里自带测试类执行mvn package时测试如果跑不过构建就失败。用-DskipTests参数跳过测试是最快的方式。如果是大型项目打包前可以把测试目录里的临时测试类删除避免打包生成的jar包包含无关代码。还需要特别注意的是项目依赖的本地仓库如果长期未更新Maven构建时可能出现依赖包下载失败的问题。遇到这种情况先把仓库中对应依赖的目录删除让Maven重新下载很多时候能解决问题。另外建议新学者在Spring Boot项目里多用Lombok它能省掉大量getter/setter代码让实体类简洁很多。项目中已经用了Lombok的话IDEA需要先安装Lombok插件否则编译报错找不到方法。这个坑是很多新人第一次跑项目时会遇到的。7.3 核心竞争力不在框架在业务理解最后想聊点个人的感受。刚入门时大家都觉得会用Spring Boot很厉害但工作一段时间后会慢慢体会到框架只是工具真正的竞争力在于对业务的理解。拿这个茶叶商城来说掌握订单流程、库存设计、支付回调这些核心业务逻辑比熟练背诵注解的用法价值高得多。建议把项目完整跑通后自己尝试改造一些功能比如给商品加一个“产地直供”的标签模块或者在后台增加一个销售排行报表。这些改造会倒逼你去理解数据表之间的关系、缓存与数据库的同步、前端与后端的交互等你完成两三次这样的小改造对系统的理解就能上一个台阶。这个茶叶商城项目本身麻雀虽小五脏俱全跑通它吃透它再改造成自己的东西你收获的不仅仅是“会启动一个Spring Boot项目”而是一整套电商系统的设计思维这些东西在以后面对复杂业务时特别受用。
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进