1. 三层架构核心职责
层级 | 职责说明 | 关键技术 / 注解 |
---|---|---|
Controller(控制器) | 1. 接收前端请求(HTTP) 2. 封装参数、校验 3. 调用 Service 处理业务 4. 返回视图 / 数据给前端 | @Controller 、@GetMapping 等 |
Service(业务层) | 1. 封装复杂业务逻辑 2. 协调 Mapper 完成数据库操作 3. 事务管理、权限校验等 | @Service 、@Transactional |
Dao(Data Access Object)(数据访问(持久)层) | 1. 直接操作数据库(增删改查)(SQL 执行) 2. 封装 CRUD 操作 3. 结果映射为 Java 对象 | @Mapper 、XML 映射或注解(@Select ) |

基于 MVC 三层架构,流程说明:
- 前端 :发起 HTTP 请求(如浏览器访问
/list
)。 - Controller 层:接收请求,调用 Service 处理,最终返回 JSON 响应。
- Service 层:封装业务逻辑(解析文件、数据处理),依赖 Dao 获取原始数据。
- Dao 层 :专注数据访问(本例读
user.txt
,未来可扩展数据库操作)。 - 资源层:存放文件或数据库,提供原始数据。
原代码:
java
package com.itxiaoli.controller;
import cn.hutool.core.io.IoUtil;
import com.itxiaoli.pojo.User;
import lombok.Data;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
/**
* 用户信息controller
*/
@RestController
public class UserController {
@RequestMapping("/list")
public List<User> list() throws FileNotFoundException {
//1.加载并读取user.txt文件来获取用户数据
//InputStream in= new FileInputStream("绝对路径"); 不推荐,打包之后绝对目录会找不到
InputStream in = this.getClass().getClassLoader().getResourceAsStream("user.txt");
ArrayList<String> lines = IoUtil.readLines(in, StandardCharsets.UTF_8, new ArrayList<>());
//2.解析用户信息,封装成用户对西昂 ->list集合
List<User> userList = lines.stream().map(line -> {
String[] parts = line.split(",");
Integer id = Integer.parseInt(parts[0]);
String username = parts[1];
String password = parts[2];
String name = parts[3];
Integer age = Integer.parseInt(parts[4]);
LocalDateTime updateTime = LocalDateTime.parse(parts[5], DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
return new User(id, username, password, name, age, updateTime);
}).toList();
//3.将list集合中的数据返回为(json)格式
return userList;
}
}
2.分层解耦优势详解
1. 职责分离(单一职责原则)
原代码:
java
// UserController承担多重职责(文件读取、数据解析、HTTP处理)
public List<User> list() throws FileNotFoundException {
InputStream in = ...; // DAO职责
List<String> lines = ...; // 文件操作
User user = parseUser(lines);// Service职责
return user; // Controller职责
}
优化后:
java
// Controller层 - 仅负责请求分发
@RestController
public class UserController {
@Autowired private UserService userService;
@RequestMapping("/list")
public List<User> list() {
return userService.findAllUser(); // 单一职责
}
}
2. 高内聚低耦合
-
Service 依赖抽象而非实现:
java@Service public class UserServiceImpl implements UserService { @Autowired private UserDao userDao; // 依赖接口而非实现类 }
-
DAO 层可无缝切换实现
(如从文件到数据库):
java// 原文件实现 public class FileUserDaoImpl implements UserDao {...} // 新增数据库实现 public class JdbcUserDaoImpl implements UserDao {...}
3. 可扩展性增强
-
开闭原则实践:
java// 新增缓存功能,无需修改原有代码 @Service public class CachedUserServiceImpl implements UserService { @Autowired private UserDao userDao; @Autowired private CacheManager cacheManager; @Override public List<User> findAllUser() { // 优先从缓存获取 List<User> users = cacheManager.get("users"); if (users == null) { users = userDao.findAll(); cacheManager.put("users", users); } return users; } }
4. 可测试性提升
-
Controller 单元测试示例:
java@SpringBootTest public class UserControllerTest { @Autowired private MockMvc mockMvc; @MockBean private UserService userService; @Test public void testListUsers() throws Exception { // Mock Service返回值 when(userService.findAllUser()).thenReturn(List.of(new User())); // 验证Controller响应 mockMvc.perform(get("/list")) .andExpect(status().isOk()) .andExpect(jsonPath("$.size()").value(1)); } }
5. 代码复用性
-
DAO 层复用示例:
java// UserService和AdminService均可复用UserDao @Service public class AdminService { @Autowired private UserDao userDao; public User lockUser(Long userId) { User user = userDao.findById(userId); // 业务逻辑... return userDao.update(user); } }
3.分层解耦后代码结构
1. Controller 层
java
@RestController
public class UserController {
@Autowired private UserService userService;
@RequestMapping("/list")
public List<User> list() {
return userService.findAllUser();
}
}
2. Service 层
java
// 接口定义
public interface UserService {
List<User> findAllUser();
}
// 实现类
@Service
public class UserServiceImpl implements UserService {
@Autowired private UserDao userDao;
@Override
public List<User> findAllUser() {
List<String> lines = userDao.findAll();
return lines.stream()
.map(this::parseUser)
.collect(Collectors.toList());
}
private User parseUser(String line) {
// 数据解析逻辑
}
}
3. DAO 层
java
// 接口定义
public interface UserDao {
List<String> findAll();
}
// 文件实现
@Repository
public class FileUserDaoImpl implements UserDao {
@Override
public List<String> findAll() {
InputStream in = getClass().getResourceAsStream("/user.txt");
return IoUtil.readLines(in, StandardCharsets.UTF_8);
}
}
4. 分层解耦实践建议
1. 依赖注入最佳实践
-
使用构造器注入替代字段注入:
java@Service public class UserServiceImpl implements UserService { private final UserDao userDao; @Autowired // 可省略,Spring 4.3+支持 public UserServiceImpl(UserDao userDao) { this.userDao = userDao; } }
2. 事务管理
-
在 Service 层声明式管理事务:
java@Service public class UserServiceImpl implements UserService { @Transactional(rollbackFor = Exception.class) public void transferPoints(Long fromId, Long toId, int points) { // 业务逻辑 } }
3. 异常处理
-
在 Controller 层统一处理异常:
java@RestControllerAdvice public class GlobalExceptionHandler { @ExceptionHandler(FileNotFoundException.class) public ResponseEntity<String> handleFileNotFound(Exception e) { return ResponseEntity.status(404).body("文件未找到"); } }
5.分层解耦的挑战与应对
挑战 | 解决方案 |
---|---|
代码量增加 | 使用 Lombok 减少样板代码,合理使用接口默认方法简化实现 |
性能开销 | 层间调用开销可忽略,避免过度分层(如简单项目可合并 Service 和 DAO) |
过度设计 | 根据项目规模选择架构(如小型项目可采用两层架构),优先满足当前需求 |
调试复杂度 | 使用 AOP 记录层间调用日志,结合 IDE 调用链分析工具 |
6. 分层架构演进路径
- 简单项目(初期) :
- Controller → Service(与 DAO 合并)
- 中等规模项目 :
- Controller → Service → DAO
- 大型复杂项目 :
- Controller → Facade → Service → Manager → DAO
- 增加领域模型层(Domain Model)
- 引入事件总线(Event Bus)解耦模块