核心分层架构图解析
具体来说👇
························································形象来说👇
各层详细说明
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 { @NotBlank private 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转Entity User user = new User(); user.setUsername(userDTO.getUsername()); user.setPassword(encodePassword(userDTO.getPassword())); // 保存到数据库 userMapper.insert(user); // Entity转VO return 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(自动生成转换代码)
通过这样的分层设计,你的代码将更加清晰、安全且易于维护。每个层专注自己的职责,使整个系统像精密的齿轮一样协同工作。