具体来说
························································形象来说
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操作数据库
INSERT INTO users (username, password)
VALUES (#{username}, #{password})
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;
}
安全性:隐藏敏感字段(密码、内部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 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(自动生成转换代码)
通过这样的分层设计,你的代码将更加清晰、安全且易于维护。每个层专注自己的职责,使整个系统像精密的齿轮一样协同工作。