Sentinel 默认抛出BlockException及其子类,推荐统一转换为自定义业务异常。首选实现BlockExceptionHandler拦截并响应;次选在SphU.entry()处try-catch转换;注解方式可用blockHandler降级;全局@ControllerAdvice兜底处理未捕获的BlockException。

在 Sentinel 中,当触发限流、降级、系统保护等规则时,默认抛出的是 BlockException 及其子类(如 FlowException、DegradeException 等)。这类异常属于 Sentinel 框架层异常,通常不直接暴露给上层业务或前端。因此,实际项目中推荐将其统一转换为自定义的业务异常(如 BusinessException),便于全局异常处理、日志归因和前端友好提示。
1. 使用 Sentinel 的 BlockExceptionHandler 统一拦截
这是最推荐的方式:通过实现 BlockExceptionHandler 接口,在异常被抛出前完成转换和响应处理。
- 创建自定义处理器,实现
handle方法,在其中将BlockException包装或转为业务异常,并写入响应(适用于 Web 场景) - 需通过
SentinelWebServletFilter或SentinelWebMvcConfig注册该处理器(Spring Boot 项目中常配合@PostConstruct初始化) - 注意:此方式不会“抛出”业务异常供后续 try-catch 捕获,而是直接写出 HTTP 响应;如需抛出异常供全局
@ControllerAdvice处理,需配合其他方式
2. 在资源调用处手动 try-catch 转换
适用于非 Web 场景、或需要保留异常传播链路的场景(例如 Dubbo 服务、定时任务):
- 对每个
SphU.entry()调用做 try-catch,捕获BlockException - 在 catch 块中 new 一个自定义业务异常(如
new BusinessException("请求过于频繁,请稍后再试", ErrorCode.RATE_LIMITED)),并 throw 出去 - 优点是控制粒度细、逻辑清晰;缺点是模板代码多,建议封装工具方法或使用 AOP 简化
3. 基于 @SentinelResource 注解 + fallback 或 blockHandler 转换
若使用注解方式定义资源,可通过 blockHandler 方法统一处理阻塞逻辑:
立即学习“Java免费学习笔记(深入)”;
-
blockHandler方法必须是 static 的,且参数列表需包含原方法参数 +BlockException - 在
blockHandler中可构造并抛出自定义异常(但注意:该异常不会被 Spring 的@ControllerAdvice拦截,因为它是 Sentinel 内部调用的) - 更实用的做法是在
blockHandler中返回预设的降级结果(如空对象、默认值),或记录日志+发告警,而将“抛异常”逻辑交给外围调用方统一处理
4. 结合 Spring 全局异常处理器兜底(推荐补充)
即使用了上述方式,仍建议配置全局异常处理器,覆盖未被捕获的 BlockException:
- 在
@ControllerAdvice中添加@ExceptionHandler(BlockException.class)方法 - 方法内将
BlockException映射为标准响应体(如Result.fail(ErrorCode.LIMIT_EXCEEDED)) - 注意:该方式仅对 Controller 层抛出的
BlockException有效;若资源在 Service 层被SphU.entry()保护,则需确保异常能透传到 Web 层
关键点在于:转换时机取决于你的架构分层和异常处理策略。Web 接口优先用 BlockExceptionHandler 直接响应;内部服务调用推荐 try-catch + 抛业务异常;注解方式适合轻量降级,避免异常传播时用 blockHandler 返回默认值。三者可组合使用,保持异常语义清晰、处理路径明确。


















