在 Spring 框架中,控制层(Controller)、业务层(Service) 和 持久层(Repository/Mapper) 是分层架构的核心组成部分,职责分离明确,通过依赖注入(DI)协作。
1. 各层职责
(1) 控制层(Controller)
-
作用:处理 HTTP 请求和响应,是前后端交互的入口。
-
职责:
-
接收请求参数(如
@RequestParam
、@RequestBody
)。 -
调用 业务层 处理逻辑。
-
返回 JSON 数据或视图(如
@ResponseBody
)。
-
-
核心注解:
-
@Controller
(返回视图)或@RestController
(纯 API,返回 JSON)。
-
(2) 业务层(Service)
-
作用:处理 核心业务逻辑(如订单计算、权限校验)。
-
职责:
-
组合多个持久层操作(如事务管理)。
-
处理业务规则(如数据校验、流程控制)。
-
调用 持久层 操作数据库。
-
-
核心注解:
-
@Service
(标识业务组件)。 -
@Transactional
(管理事务)。
-
(3) 持久层(Repository/Mapper)
-
作用:直接与 数据库交互,执行 CRUD 操作。
-
职责:
-
定义数据库操作方法(如 SQL 或 ORM 映射)。
-
屏蔽数据库细节(如 MySQL 或 MongoDB 差异)。
-
-
核心注解:
-
JPA:
@Repository
(接口继承JpaRepository
)。 -
MyBatis:
@Mapper
(接口 + XML/SQL 映射)。
-
2. 各层协作关系
(1) 调用流程
HTTP请求 → Controller → Service → Repository → 数据库↑返回响应 ↑业务逻辑 ↑SQL执行
-
Controller 接收请求参数,校验格式。
-
Service 处理业务逻辑(如订单总价计算),调用 Repository 读写数据。
-
Repository 执行 SQL 或通过 ORM 操作数据库,返回结果给 Service。
-
Service 处理完成后,返回数据给 Controller。
-
Controller 封装响应(如 JSON),返回给前端。
(2) 依赖关系
-
单向依赖:
Controller → Service → Repository
-
上层依赖下层,下层不感知上层(如 Repository 不依赖 Service)。
-
通过
@Autowired
实现依赖注入。
-
3. 分层优势
优势 | 说明 |
---|---|
职责分离 | 各层专注单一职责(如 Controller 处理请求,Service 处理业务)。 |
代码复用 | 多个 Controller 可共用同一个 Service(如订单和支付模块共用用户服务)。 |
易于维护 | 修改数据库逻辑只需调整 Repository,不影响 Service 和 Controller。 |
事务管理 | 事务注解(@Transactional )通常放在 Service 层,确保业务操作原子性。 |
测试友好 | 可单独测试 Service 逻辑,Mock 数据库操作(如使用 Mockito)。 |
4. 实际开发中的常见问题
(1) 能不能跳过 Service,直接 Controller 调用 Repository?
-
不推荐!会导致:
-
业务逻辑散落在 Controller 中,难以复用。
-
事务管理困难(如多个 Repository 操作无法统一回滚)。
-
(2) Service 层为什么需要接口?
-
接口的作用:
-
实现类可替换(如切换缓存策略)。
-
便于 AOP 代理(如事务管理、日志切面)。
public interface UserService { // 接口User getUserById(Long id); }@Service public class UserServiceImpl implements UserService { // 实现类// 具体逻辑 }
-
(3) 实体类(Entity)放在哪一层?
-
通常独立为领域模型层:
com.example.project ├── controller ├── service ├── repository └── entity // 实体类(User、Order)
-
所有层共享实体类,但 避免将实体直接暴露给前端(建议用 DTO 转换)。
-
5. 总结
-
Controller:处理 HTTP 交互,参数校验,调用 Service。
-
Service:核心业务逻辑,事务管理,调用 Repository。
-
Repository:数据库操作,屏蔽 SQL 细节。