RESTful API异常捕获位置:Service层还是Controller层?
RESTful API异常捕获:Service层还是Controller层?
这不是主观选择,而是要根据异常类型和职责划分来决定:
一、业务类异常:Service层抛出,Controller/全局过滤器处理
Service层是业务逻辑的核心,最清楚业务规则(比如用户是否存在、参数是否符合业务要求)。这类异常应该由Service层主动抛出自定义业务异常,而非在Service层捕获处理——因为Service层的职责是实现业务逻辑,不是处理HTTP响应。
比如修改你的Service层代码,加入业务校验:
public async Task<User> UpdateAsync(User user, int id) { var existingUser = await _repository.GetByIdAsync(id); if (existingUser == null) { // 抛出自定义业务异常,明确业务错误类型 throw new UserNotFoundException($"用户ID {id} 不存在"); } // 其他业务规则校验,比如用户权限、参数合法性 if (user.Age < 18) { throw new InvalidUserInputException("用户年龄不能小于18岁"); } await _repository.UpdateAsync(user, id); return user; }
二、通用/系统类异常:Controller层或全局过滤器统一捕获
像数据库连接失败、未知异常这类和业务无关的系统异常,不需要在每个Service或Controller方法里单独捕获。推荐用全局异常过滤器统一处理,这样能保证所有API的错误返回格式一致,也避免重复代码。
比如用全局过滤器替代Controller里的try-catch:
public class GlobalExceptionFilter : IExceptionFilter { private readonly ILogger<GlobalExceptionFilter> _logger; public GlobalExceptionFilter(ILogger<GlobalExceptionFilter> logger) { _logger = logger; } public void OnException(ExceptionContext context) { // 统一记录异常日志 _logger.LogError(context.Exception, "API请求发生未处理异常"); // 根据异常类型返回对应HTTP状态码 var (statusCode, message) = context.Exception switch { UserNotFoundException => (StatusCodes.Status404NotFound, context.Exception.Message), InvalidUserInputException => (StatusCodes.Status400BadRequest, context.Exception.Message), _ => (StatusCodes.Status500InternalServerError, "服务器内部错误") }; context.Result = new ObjectResult(new { Code = statusCode, Message = message }) { StatusCode = statusCode }; context.ExceptionHandled = true; } }
此时Controller层可以简化,不用写try-catch:
[HttpPut] [Route("{id}")] [ProducesResponseType(200)] [ProducesResponseType(404)] [ProducesResponseType(400)] public async Task<ActionResult<UserDto>> UpdateUserInfo(int id, UserDto userRequest) { var user = _userMapper.ConvertToEntity(userRequest); var updatedUser = await _userService.UpdateAsync(user, id); var result = _userMapper.ConvertToUserDto(updatedUser); return Ok(result); }
总结
- Service层:负责根据业务规则抛出具体的自定义异常,不处理HTTP响应相关逻辑。
- Controller/全局过滤器:负责统一捕获所有异常,转换成符合REST规范的HTTP响应,同时统一记录日志。
内容的提问来源于stack exchange,提问作者charbs29
相关产品推荐
相关产品推荐

