1. 项目背景与业务架构
- 业务定位:天机学堂是一个基于微服务架构的B2C模式的生产级在线教育项目,主要面向成年人的非学历职业技能培训 。相比于简单的单体项目,它的业务完整度和复杂度都非常接近企业真实场景 。
- 开发起点:模拟真实的企业入职场景,目前项目已经完成了1.0.0版本约60%的开发(如基础的课程管理、购买流程),我们的任务是继续开发课程学习、优惠促销等核心微服务 。
2. 企业级开发环境与部署
在大型企业中,微服务数量庞大,无法全部在本地启动,因此需要掌握企业级的联调方式。
-
环境基建:通过虚拟机搭建了一套公共开发环境,其中部署了Nacos、MySQL、Redis、MQ(RabbitMQ)、ES、XXL-JOB 等中间件,以及Git私服(gogs)和持续集成工具(Jenkins) 。
-
本地开发与联调:
- 域名映射:需要在本地配置hosts,将
api.tianji.com等域名映射到虚拟机IP(192.168.150.101),由Nginx进行反向代理转发 。 - 请求路由:访问网关时,请求会根据路径前缀路由到对应的微服务,例如前端请求
/ts开头的路径会被路由到交易微服务(trade-service) 。
- 域名映射:需要在本地配置hosts,将
-
自动化部署:项目配置了Git钩子,代码推送到私服后会自动触发Jenkins进行编译和部署,实现持续集成 。
3. 项目编码规范(重点关注,这是企业级开发的基础)
-
实体类隔离:项目对实体类进行了严格分层 。
- PO:持久层对象,与数据库表结构一一对应 。
- DTO:数据传输对象,用于微服务之间或前后端之间传递参数 。
- VO:视图对象,专门用于封装返回给前端页面展示的数据 。
- QUERY:查询对象,封装前端传来的复杂查询条件 。
-
依赖注入:Spring官方不推荐使用
@Autowired进行字段注入。项目中统一采用构造函数注入,并利用Lombok的@RequiredArgsConstructor注解来极大简化代码 。 -
统一异常处理:为了规范响应格式,项目中定义了如
DbException、CommonException等自定义异常,并通过带有@RestControllerAdvice的CommonExceptionAdvice类进行全局异常的统一捕获和处理 。 -
Nacos配置中心:利用Nacos管理共享配置(如
shared-mybatis.yaml、shared-redis.yaml),各微服务只需引入对应配置即可,避免了多环境下重复配置的问题 。
4. 实战:修复删除订单Bug
入职的第一个任务通常是熟悉代码,项目中通过预留一个Bug来帮助你梳理业务请求链路。
- 问题重现:用户Jack(ID为2)可以成功删除订单,但用户Rose(ID为129)删除失败 。
- 排查过程:因为微服务部署在公共环境,无法直接本地Debug。这里需要利用IDEA的**远程调试(Remote Debug)**功能,通过监听5005端口连接到虚拟机上的服务进行排查 。
- 根本原因(需熟练掌握的底层原理) :代码在校验当前用户ID与订单所属用户ID时,错误地使用了
!=进行比较。因为用户ID是Long包装类,而Java对Long类型采用了享元模式,提前缓存了-128 ~ 127范围内的对象。Jack的ID是2,比较的是缓存池中同一个对象的地址,因此判断成立;Rose的ID是129,超出了缓存范围,底层创建了新的对象,导致地址不同,判断失效 。 - 修复与分支规范:将
!=替换为.equals()比较值即可 。同时在企业开发中需遵循GitFlow规范,不在开发分支直改,而是从dev分支切出hotfix热修复分支,修复测试后再合并 。
5. Day 01 课后作业思考
在正式进入第二天的开发前,可以先思考一下项目中给出的原型图问题:
- “我的课程”页面展示的用户课程,从购买到学习完结,大概会经历哪些状态变化?
- 如果要设计一张表示《我的课程》的数据库表,应该包含哪些核心字段?