Spring Boot 分层架构与数据流转详解
核心分层架构图解析
具体来说👇
························································形象来说👇
各层详细说明
-
Controller(控制层)
-
职责:接收HTTP请求,返回HTTP响应
-
工作流程:
-
接收前端发送的请求数据(JSON/表单)
-
调用Service处理业务逻辑
-
将Service返回的VO对象转为JSON响应
-
-
关键注解:
-
@RestController
:标记为控制器 -
@PostMapping
/@GetMapping
:定义API路径 -
@RequestBody
:接收JSON请求体 -
@Valid
:参数校验
-
-
-
Service(服务层)
-
职责:处理核心业务逻辑
-
工作流程:
-
接收Controller传递的DTO对象
-
调用Mapper操作数据库
-
处理业务规则和计算
-
将Entity转换为VO返回给Controller
-
-
关键注解:
-
@Service
:标记为服务组件 -
@Transactional
:管理数据库事务
-
-
-
Mapper(数据访问层)
-
职责:与数据库直接交互
-
工作流程:
-
接收Service传递的Entity对象
-
执行SQL语句(增删改查)
-
将数据库结果转为Entity返回
-
-
关键技术:
-
MyBatis:SQL映射框架
-
@Mapper
:标记Mapper接口 -
XML文件:编写SQL语句
-
-
-
Entity(实体层)
-
职责:映射数据库表结构
-
特点:
-
与数据库表一一对应
-
包含所有表字段
-
不应包含业务逻辑
-
-
示例:
@Data public class User {private Long id;private String username;private String password; // 敏感字段private Date createTime; }
-
-
DTO(数据传输对象)
-
职责:层间数据传输
-
特点:
-
用于Controller接收请求数据
-
只包含前端需要的字段
-
包含数据校验规则
-
-
示例:
public class UserDTO {@NotBlankprivate String username;@Size(min=6, max=20)private String password; }
-
-
VO(视图对象)
-
职责:返回给前端的数据
-
特点:
-
只包含前端需要的数据
-
对敏感字段脱敏
-
格式化数据展示
-
-
示例:
public class UserVO {private Long id;private String username;private String createTime; // 格式化后的字符串 }
-
完整数据流转过程
-
前端发起请求
-
发送HTTP请求(如POST /users)
-
携带JSON数据(DTO格式)
-
-
Controller接收请求
@PostMapping("/users") public UserVO createUser(@Valid @RequestBody UserDTO userDTO) {return userService.createUser(userDTO); }
-
Service处理业务
@Service public class UserService {public UserVO createUser(UserDTO userDTO) {// DTO转EntityUser user = new User();user.setUsername(userDTO.getUsername());user.setPassword(encodePassword(userDTO.getPassword()));// 保存到数据库userMapper.insert(user);// Entity转VOreturn convertToVO(user);} }
-
Mapper操作数据库
<!-- UserMapper.xml --> <insert id="insert">INSERT INTO users (username, password) VALUES (#{username}, #{password}) </insert>
-
VO返回给前端
private UserVO convertToVO(User user) {UserVO vo = new UserVO();vo.setId(user.getId());vo.setUsername(user.getUsername());// 格式化日期vo.setCreateTime(formatDate(user.getCreateTime()));// 不返回密码等敏感字段return vo; }
为什么需要VO?
-
安全性:隐藏敏感字段(密码、内部ID等)
// Entity包含敏感字段 public class User {private String password;private String internalCode; }// VO只返回安全字段 public class UserVO {private String username;private String displayName; }
-
数据格式化:转换数据库原始数据
// 数据库存储的原始日期 private Date createTime; // VO中的格式化日期 @JsonFormat(pattern = "yyyy-MM-dd HH:mm") private String createTime;
-
减少网络传输:只返回必要字段
// 不返回大型字段 // private byte[] avatarImage;
-
数据组合:聚合多个Entity的数据
public class OrderDetailVO {private OrderVO order;private List<OrderItemVO> items;private UserVO user; }
一些错误写法
❌ 错误1:直接返回Entity
// Controller中
public User getUser() {return userService.getUser(); // 返回包含密码的Entity
}
✅ 正确做法:返回VO
public UserVO getUser() {User user = userService.getUser();return convertToVO(user);
}
❌ 错误2:DTO/VO混用
public class UserDTO {// 请求字段private String password;// 响应字段private String createTime;
}
✅ 正确做法:DTO/VO分离
// 请求专用
public class UserRequestDTO {private String username;private String password;
}// 响应专用
public class UserResponseVO {private String username;private String createTime;
}
总结要点
-
分层结构:
-
Controller:处理HTTP请求/响应
-
Service:实现业务逻辑
-
Mapper:数据库操作
-
Entity:映射数据库表
-
DTO:接收请求数据
-
VO:返回响应数据
-
-
数据流转方向:
前端 → DTO → Controller → Service → Mapper → Entity → 数据库
数据库 → Entity → Mapper → Service → VO → Controller → 前端 -
核心原则:
-
永远不要直接返回Entity给前端
-
各层只处理本层的职责
-
DTO用于输入,VO用于输出
-
Service处理业务逻辑和类型转换
-
-
转换工具推荐:
-
简单项目:
BeanUtils.copyProperties()
-
复杂项目:MapStruct(自动生成转换代码)
-
通过这样的分层设计,你的代码将更加清晰、安全且易于维护。每个层专注自己的职责,使整个系统像精密的齿轮一样协同工作。