非受检异常是策略模式中表达“不执行”语义的轻量信号,应定义如SkipStrategyException等业务异常,由策略执行器统一捕获并路由,避免泛化异常、提升可维护性与可观测性。

非受检异常不是错误,而是控制流的语义信号
在策略模式中,不同策略实现同一接口但行为各异。当某个策略判定当前上下文不满足执行条件(如权限不足、数据缺失、业务规则不匹配),传统做法是返回特殊值(如null、false或枚举状态),但调用方需层层判断,易漏处理、逻辑分散。而非受检异常(RuntimeException及其子类)可作为轻量、无侵入的“提前退出信号”——它不强制上层捕获,却能自然中断当前策略链,把控制权交还给策略调度器统一决策。
定义语义清晰的业务退出异常
避免直接抛RuntimeException或IllegalStateException这类泛化异常。应创建有业务含义的自定义非受检异常,明确表达“为何不执行”:
-
命名体现意图:如
SkipStrategyException、RuleNotApplicableException、ContextMismatchException - 携带上下文信息:构造时传入策略名、规则ID、关键参数摘要,便于日志追踪和调试
- 不包含敏感数据:不暴露用户ID、密码、内部路径等,message字段仅用于开发定位
策略执行器统一捕获并路由
策略调度器(如StrategyExecutor)负责按序尝试多个策略。它应主动捕获策略抛出的退出异常,并据此决定后续动作:
- 捕获
SkipStrategyException→ 记录INFO日志,继续尝试下一个策略 - 捕获
RuleNotApplicableException→ 标记该规则失效,更新缓存或上报监控 - 捕获其他
RuntimeException→ 视为真实错误,记录ERROR日志并终止流程
示例代码片段:
Java Maven 项目审查工作流的通用输入处理。当 Java Maven 项目以 ZIP压缩包或 GitLab 仓库 URL 形式提供且需要...时使用。
立即学习“Java免费学习笔记(深入)”;
public Result execute(ExecutionContext ctx) {for (Strategy strategy : strategies) {
try {
return strategy.apply(ctx);
} catch (SkipStrategyException e) {
log.info("策略[{}]跳过: {}", strategy.name(), e.getMessage());
continue;
}
}
throw new NoApplicableStrategyException("所有策略均不适用");
}
与Spring等框架协同增强可维护性
若项目使用Spring,可进一步解耦:
- 用
@Order注解声明策略优先级,替代硬编码列表顺序 - 将退出异常注册为
@ControllerAdvice中的忽略类型,防止被全局异常处理器误转为HTTP错误响应 - 配合
@Valid和自定义约束注解,在策略入参校验失败时自动抛出ConstraintViolationException(也是非受检异常),天然融入退出机制
这种设计让策略本身专注“做什么”,退出逻辑收口到执行器,既保持单个策略的简洁性,又赋予整体调度足够的灵活性和可观测性。

















