在分层架构中,服务层(Service Layer) 和 控制层(Controller Layer) 虽然都涉及业务逻辑的处理,但它们的职责和定位有本质区别。
一句话概括:
-
控制层(Controller):是 HTTP 请求的“入口”和“出口”,负责协议层逻辑。
-
服务层(Service):是业务逻辑的“发动机”,负责实现核心业务规则。
控制器仅做路由转发。服务层统一处理业务。两者分工明确,共同构建高可维护性的应用架构。
1. 职责划分
控制层(Controller) | 服务层(Service) |
---|---|
处理 HTTP 请求/响应 的交互逻辑 | 处理 核心业务逻辑 的实现与协调 |
解析请求参数、验证输入格式(如 Pydantic) | 实现具体的业务规则(如订单创建、审批流程) |
调用服务层方法并格式化返回结果 | 协调多个模型(Model)或外部服务(如数据库、API) |
处理路由、权限校验、异常捕获 | 管理事务(如数据库原子操作) |
不直接操作数据库或外部服务 | 可被多个控制器或其他服务复用 |
2. 代码示例对比
控制层(Controller)
# app/api/v1/apis/workflow.py
from fastapi import APIRouter, Depends, HTTPException
from app.services.workflow import WorkflowService
router = APIRouter()
@router.post("/process/start")
async def start_process(
biz_type: str,
biz_id: int,
user: User = Depends(get_current_user), # 权限校验
service: WorkflowService = Depends() # 依赖注入服务层
):
# 参数校验(简单示例)
if biz_type not in ["leave", "expense"]:
raise HTTPException(400, "无效的业务类型")
# 调用服务层核心逻辑
try:
instance = await service.start_process(biz_type, biz_id, user.id)
return {"process_id": instance.id} # 格式化响应
except InsufficientPermissionError as e:
raise HTTPException(403, str(e)) # 捕获服务层异常并转换
服务层(Service)
# app/services/workflow.py
from app.models.workflow import ProcessInstance
from app.models.user import User
from app.core.db import atomic_transaction
class WorkflowService:
async def start_process(
self,
biz_type: str,
biz_id: int,
user_id: int
) -> ProcessInstance:
# 业务规则校验(示例)
user = await User.get(id=user_id)
if not user.has_permission("PROCESS_START"):
raise InsufficientPermissionError("用户无权操作")
# 数据库事务管理
async with atomic_transaction():
# 调用其他服务或模型
process_id = await self.engine.start_process(biz_type, biz_id)
instance = await ProcessInstance.create(
process_id=process_id,
biz_type=biz_type,
biz_id=biz_id,
status="RUNNING"
)
# 触发后续业务逻辑(如通知)
await self.notify_approvers(instance)
return instance
3. 关键区别
维度 | 控制层 | 服务层 |
---|---|---|
输入来源 | HTTP 请求参数、Headers、Cookies | 方法参数(来自控制器或其他服务) |
输出目标 | HTTP 响应(JSON/XML) | 返回业务对象(如 ORM 模型、DTO 对象) |
依赖关系 | 依赖服务层 | 依赖模型层、工具类、外部服务(如 Perfect) |
复用性 | 通常不可复用(绑定特定路由) | 高度可复用(多个控制器/任务可调用) |
单元测试重点 | 请求解析、响应格式、异常转换 | 业务规则、事务一致性、外部服务交互 |
4. 常见错误
❌ 控制层做业务逻辑
# 错误示例:在控制器中直接操作数据库
@router.post("/process/start")
async def start_process(...):
# 直接操作数据库(破坏分层原则)
instance = await ProcessInstance.create(...)
await send_email(...) # 直接调用通知
✅ 正确分层
# 控制器仅做路由转发
@router.post("/process/start")
async def start_process(...):
return await service.start_process(...) # 业务逻辑交给服务层
# 服务层统一处理业务
class WorkflowService:
async def start_process(...):
# 业务逻辑集中在此
instance = await ProcessInstance.create(...)
await self.notify_approvers(...)
5. 分层架构的优势
-
解耦性:控制器不关心业务实现,服务层不关心 HTTP 细节。
-
可测试性:服务层可脱离 Web 框架单独测试(如用 pytest 直接调用)。
-
复用性:一个服务可被多个控制器(甚至 CLI 命令行)复用。
-
维护性:业务逻辑集中管理,修改时无需搜索分散的控制器代码。