当前位置: 首页 > web >正文

软件架构风格系列(1):分层架构如何让系统“稳如泰山”?


文章目录

  • 引言
    • 一、分层架构的核心:用“职责分离”驯服复杂性
      • (一)什么是分层架构?
      • (二)为什么需要分层?
    • 二、架构设计图:三层架构的“标准姿势”
    • 三、Java实战:从0搭建一个分层的订单系统
      • (一)技术选型
      • (二)实体层(Entity)
      • (三)数据访问层(Repository)
      • (四)业务逻辑层(Service)
      • (五)表示层(Controller)
      • (六)分层调用流程
    • 四、适用场景与避坑指南
      • (一)这些场景请优先选择分层架构
      • (二)踩坑预警:这3个陷阱别掉进去
    • 五、总结:分层架构的“生存法则”

引言

在电商大促的峰值时刻,当千万级订单请求如潮水般涌来,你是否想过:为什么有的系统能有条不紊地处理库存、支付、物流等复杂逻辑,而有的系统却像一团乱麻般陷入崩溃?答案往往藏在一个看似基础却至关重要的架构风格里——分层架构。作为一个经历过十余个大型项目的老架构师,今天就来聊聊这个“化繁为简”的架构法宝,帮你从原理到落地全面掌握。

一、分层架构的核心:用“职责分离”驯服复杂性

(一)什么是分层架构?

简单来说,它是一种“分而治之”的设计哲学:将系统按功能划分为若干独立的“层”,每层只负责单一领域的职责,层与层之间通过定义清晰的接口通信。

最经典的是三层架构

  1. 表示层(Presentation Layer)
    • 职责:与用户直接交互,处理输入输出(如Web页面、API接口)
    • 例子:接收前端传来的JSON请求,返回处理后的响应数据
  2. 业务逻辑层(Business Logic Layer)
    • 职责:封装核心业务规则,如订单计算、库存校验、权限控制
    • 例子:计算订单总价时,调用商品服务获取价格,结合促销规则计算最终金额
  3. 数据访问层(Data Access Layer)
    • 职责:与数据库/缓存交互,实现数据的增删改查
    • 例子:将订单数据持久化到MySQL,或从Redis读取用户缓存信息

(二)为什么需要分层?

想象一个没有分层的系统:前端代码直接操作数据库,业务逻辑混杂在API接口中,修改一个字段可能需要牵动整个调用链。

而分层架构带来三大核心价值:

  • 职责清晰:每个团队(前端、后端、DBA)可专注于自己的层,降低协作成本
  • 可维护性强:修改表示层UI时,不影响底层数据库逻辑
  • 技术栈隔离:数据层用MySQL或MongoDB,业务层无需关心,只需调用统一接口。

二、架构设计图:三层架构的“标准姿势”

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  • 层间依赖规则:上层只能调用下层接口,禁止反向依赖(如业务层不能直接操作前端组件)
  • 接口标准化:层间通过POJO(Plain Old Java Object)或DTO(Data Transfer Object)传递数据,例如订单创建时,前端传递CreateOrderDTO,经业务层转换为领域模型Order,再由数据层保存为数据库实体OrderEntity

三、Java实战:从0搭建一个分层的订单系统

(一)技术选型

  • 框架:Spring Boot(简化分层实现)
  • 数据层:Spring Data JPA(操作MySQL)
  • 接口:RESTful API(通过Controller暴露接口)

(二)实体层(Entity)

定义数据库映射实体,注意只包含数据字段,不包含业务逻辑:

@Entity
@Table(name = "orders")
@Data
public class OrderEntity {@Id@GeneratedValue(strategy = GenerationType.IDENTITY)private Long id;private String orderNo;private Long userId;private BigDecimal totalPrice;...
}

(三)数据访问层(Repository)

封装数据库操作,继承Spring Data JPA的JpaRepository

public interface OrderRepository extends JpaRepository<OrderEntity, Long> {// 自定义查询:根据订单号查询订单OrderEntity findByOrderNo(String orderNo);
}

(四)业务逻辑层(Service)

处理核心业务,调用数据层并添加校验逻辑:

@Service
public class OrderService {private final OrderRepository orderRepository;@Autowiredpublic OrderService(OrderRepository orderRepository) {this.orderRepository = orderRepository;}// 创建订单public OrderDTO createOrder(CreateOrderRequest request) {// 1. 校验业务规则if (request.getProductIds().isEmpty()) {throw new IllegalArgumentException("订单中必须包含商品!");}// 2. 计算总价BigDecimal totalPrice = calculateTotalPrice(request.getProductIds());// 3. 持久化订单OrderEntity entity = new OrderEntity();entity.setOrderNo(UUID.randomUUID().toString());entity.setUserId(request.getUserId());entity.setTotalPrice(totalPrice);...OrderEntity savedEntity = orderRepository.save(entity);// 4. 返回DTO(隐藏数据库字段)return OrderDTO.builder().orderId(savedEntity.getId()).orderNo(savedEntity.getOrderNo()).totalPrice(savedEntity.getTotalPrice())....build();}//计算订单价格private BigDecimal calculateTotalPrice(List<Long> productIds) {// 实际应调用商品服务获取价格并计算,mock数据return BigDecimal.valueOf(199.9);}
}

(五)表示层(Controller)

处理HTTP请求,转换输入输出格式:

@RestController
@RequestMapping("/orders")
public class OrderController {private final OrderService orderService;@Autowiredpublic OrderController(OrderService orderService) {this.orderService = orderService;}@PostMappingpublic ResponseEntity<OrderDTO> createOrder(@RequestBody CreateOrderRequest request) {OrderDTO orderDTO = orderService.createOrder(request);return ResponseEntity.ok(orderDTO);}
}

(六)分层调用流程

  1. 前端发送POST请求到/orders,携带订单商品ID和用户ID
  2. Controller接收请求,将JSON反序列化为CreateOrderRequest
  3. 调用OrderService.createOrder(),触发业务逻辑(校验、计算、持久化)
  4. Service层调用Repository保存数据到数据库
  5. 数据库返回主键ID,Service层封装为OrderDTO(不含敏感字段如数据库自增ID)
  6. Controller将OrderDTO序列化为JSON,返回给前端

四、适用场景与避坑指南

(一)这些场景请优先选择分层架构

  1. 企业级Web应用:如ERP、OA系统,业务逻辑复杂且需要多人协作开发
  2. 微服务中的单体模块:每个微服务内部可采用分层,如订单服务、商品服务各自分层
  3. 需要技术栈隔离的系统:例如数据层从MySQL迁移到PostgreSQL时,只需修改Repository层代码

(二)踩坑预警:这3个陷阱别掉进去

  1. 过度分层:四层、五层架构看似“高大上”,实则增加调用链路耗时。中小型项目建议从标准三层开始,避免“为了分层而分层”
  2. 循环依赖:业务层A调用数据层B,数据层B又调用业务层A的工具类,导致编译错误。解决方案:严格遵循单向依赖,工具类放公共模块
  3. 业务逻辑泄露:将价格计算、库存扣减等逻辑写在Controller或Repository中,违背分层原则。正确做法:所有业务规则集中在Service层,必要时拆分为独立的领域服务

五、总结:分层架构的“生存法则”

分层架构的本质,是承认软件系统的复杂性,并通过“分而治之”让每个部分都“各司其职”。它就像建筑中的楼层规划:

  • 表示层是“前台”,负责接待用户;
  • 业务逻辑层是“核心处理区”,决定系统能做什么;
  • 数据访问层是“地基”,保障数据可靠存储与高效读取。

从单体应用到微服务,分层架构始终是最基础却最稳固的选择。下次当你面对复杂业务时,不妨先画一张分层图:哪些属于表示层的交互逻辑?哪些是业务层的核心规则?哪些是数据层的存储细节?清晰的分层,能让你的代码像“瑞士手表”一样精密运转。


最后留个小问题:你在项目中遇到过哪些分层架构的挑战?欢迎在评论区聊聊你的经验~

图片来源网络

http://www.xdnf.cn/news/6735.html

相关文章:

  • AI 笔记 -基于retinaface的FPN上采样替换为CARAFE
  • Android framework 中间件开发(一)
  • 149.WEB渗透测试-MySQL基础(四)
  • 【暗光图像增强】【基于CNN的方法】2020-AAAI-EEMEFN
  • 显性知识的主要特征
  • math.js 加/减/乘/除 使用
  • 第九天——贪心算法——非递减数组
  • ZYNQ Overlay硬件库使用指南:用Python玩转FPGA加速
  • AWS中国区CloudFront证书管理和应用指南
  • 五月月报丨MaxKB在教育行业的应用进展与典型场景
  • 现代简约中式通用,民国画报风,中国风PPT模版8套一组分享
  • 【Vue 3全栈实战】从响应式原理到企业级架构设计
  • 数据结构(3)线性表-链表-单链表
  • k8s监控方案实践补充(二):使用kube-state-metrics获取资源状态指标
  • 前端开发笔记与实践
  • Visual Studio 2022 中添加“高级保存选项”及解决编码问题
  • WebMvcConfigurer介绍-笔记
  • GESP2025年3月认证C++二级( 第三部分编程题(2)时间跨越)
  • MongoDB 应用实战
  • 多尺度对比度调整
  • DDD领域驱动介绍
  • MODBUS RTU调试助手使用方法详解
  • 基于Mongodb的分布式文件存储实现
  • Java实现生产者-消费者模式:从基础到高级实践
  • MiniMax语音模型Speech-02近日登顶多个全球榜单,详细技术解析
  • 【Reality Capture 】02:Reality Capture1.5中文版软件设置与介绍
  • Lua中使用module时踩过的坑
  • 计算机指令分类和具体的表示的方式
  • 【Win32 API】 lstrcmpA()
  • Java内存泄露生产环境排查过程,通透了