在项目的根目录下创建:.cursor\skills\chain-of-responsibility-expert
创建文件SKILL.md:
---
name: chain-of-responsibility-expert
description: Designs and implements Chain of Responsibility with abstract handler, concrete handlers, chain assembler, and context supporting full traversal and short-circuit. Defaults to Java; switches language on user request. Use when the user invokes /chain-of-responsibility or asks for 责任链、处理器链、拦截链、可插拔链路、审批流/权限链/过滤链重构;in this repo, align with cn.lomark.zoc.strategy (Handler, AbstractHandler, *Context, *HandlerChain).
---
# 责任链模式设计与实现专家
当用户发送 **`/chain-of-responsibility`** 或明确要按责任链编写/重构代码时,**必须**按本文输出;默认语言为 **Java**,若用户指定其他语言则整体切换(仍保持相同结构与规则)。
## 必须遵守的核心规则
1. **可运行**:给出完整包结构、可编译的类与最小依赖说明(如 Spring 可选)。
2. **必须有 Context**:承载请求数据、中间状态、最终结果;**禁止**用裸 `Map` 代替强类型上下文。
3. **两种执行语义**(须在代码中显式体现):
- **全链路执行**:每一环都运行,除非前置已将上下文标为停止(若业务需要“全员执行”,则不设停止条件)。
- **拦截中断**:某一环判定失败后调用 `context.stop()`(或等价机制),后续环节 **不再** 执行。
4. **开闭原则 / 可插拔**:新增环节 = 新增 Handler + 在链装配处注册顺序;**禁止**修改已有 Handler 的 `if-else` 堆砌来插入逻辑。
5. **禁止循环依赖**:Handler 只依赖接口/服务抽象;**Chain 装配类**依赖各 Handler,Handler **不得** 依赖 Chain。
6. **禁止硬编码**:业务阈值、开关、角色编码等来自配置、`@ConfigurationProperties`、枚举或注入的策略表;魔法字符串集中为常量或枚举。
7. **业务示例要求**:交付物中须包含至少三类示例之一的真实链路骨架:**权限校验链**、**审批流链**、**过滤链**(可与用户场景合并,但结构要独立可读)。
## 与本仓库(channel-platform)对齐时
参考现有形态(`cloud-fast-charging` 模块 `cn.lomark.zoc.strategy`):
- `Handler` + `AbstractHandler`:`setNext`、`handle(Request)`。
- 上下文类继承 `Request`(如 `DksRechargeContext`、`VirtualRechargeContext`)。
- `*HandlerChain`:`@PostConstruct` 中 `setNext` 串联,对外 `execute(Context)` 从第一个 handler 进入。
若当前 `AbstractHandler` **未**内置短路语义,有两种合规做法(二选一并在“模式说明”中写明):
- **A**:在子类中仅在成功路径调用 `super.handle(ctx)`;失败则 **不** 调用,实现中断。
- **B**:升级抽象层,在模板方法中统一判断 `context.isStopped()`(推荐长期维护)。
## 输出结构(固定顺序,不得省略)
对用户回复必须按以下 **六级标题** 组织(中文标题原样使用):
### 1. 模式说明
- 一句话定义责任链;说明**全链路** vs **拦截中断**在本设计中的触发条件。
- 点明与调用方的边界:谁创建 Context、谁解析最终结果。
### 2. 类设计
用表格或列表说明:`Context`、`Handler`(抽象/接口)、`ConcreteHandlers`、`Chain`(装配)、可选 `ChainResult`/枚举;说明依赖方向与扩展点。
### 3. 代码
给出 **完整** 可运行代码(包名、类名、字段、方法齐全)。至少包含:
- 上下文类(含 `stop` / `isStopped` 或等价 API,以及业务字段)。
- 抽象处理器(模板方法或显式传递 `next`)。
- ≥2 个具体处理器(其一演示**成功传递**,其一演示**中断**)。
- 链装配类(推荐 Spring `@Service` + `@PostConstruct`;非 Spring 则提供纯 Java 构造装配示例)。
### 4. 使用示例
展示调用方:构建 Context → 调用 `chain.execute(context)` → 读取结果与停止原因(若有)。
### 5. 扩展方法
说明新增一个环节的步骤清单(新建类、注入、装配顺序、配置项、单测要点);强调 **不修改** 既有 Handler 主体逻辑。
### 6. 适用场景
简述何时采用责任链;何时应改用策略模式、管道、或规则引擎(各一行对比即可)。
---
## 推荐 Java 骨架(生成代码时应贴近此结构,可按业务改名)
下列为 **canonical 模板**:上下文带短路标记;抽象类用 `final handle` 统一传递,避免遗漏 `super.handle`;链与 Handler 无环依赖。
```java
// ChainContext.java — 强类型上下文 + 短路
package com.example.chain;
public class ChainContext {
private boolean stopped;
private String stopReason;
// TODO: 业务字段
public void stop(String reason) {
this.stopped = true;
this.stopReason = reason;
}
public boolean isStopped() { return stopped; }
public String getStopReason() { return stopReason; }
}
```
```java
// ChainHandler.java — 抽象处理器
package com.example.chain;
public abstract class ChainHandler {
private ChainHandler next;
public void setNext(ChainHandler next) { this.next = next; }
public final void handle(ChainContext ctx) {
if (ctx.isStopped()) return;
doHandle(ctx);
if (!ctx.isStopped() && next != null) next.handle(ctx);
}
protected abstract void doHandle(ChainContext ctx);
}
```
```java
// ExampleChain.java — 装配(Spring 示例)
package com.example.chain;
import jakarta.annotation.PostConstruct;
import org.springframework.stereotype.Service;
import jakarta.annotation.Resource;
@Service
public class ExampleChain {
@Resource private AuthHandler authHandler;
@Resource private ApprovalHandler approvalHandler;
@Resource private FilterHandler filterHandler;
@PostConstruct
void wire() {
authHandler.setNext(approvalHandler);
approvalHandler.setNext(filterHandler);
}
public void execute(ChainContext ctx) {
authHandler.handle(ctx);
}
}
```
**权限校验 / 审批流 / 过滤链** 三类示例:将 `AuthHandler`、`ApprovalHandler`、`FilterHandler` 替换为对应业务命名,在 `doHandle` 中读取配置或仓储,失败时 `ctx.stop("...")`。
更多 **可编译的完整串联示例**(权限 → 审批 → 过滤,含配置类与 `main`):见 [examples.md](examples.md)。
---
## 自检清单(输出前在思考中完成)
- [ ] Context 是否为强类型且持有最终结果?
- [ ] 是否同时演示了“全链路”和“拦截中断”路径(可用注释 + 两个调用示例说明)?
- [ ] 是否存在 Handler → Chain 的反向依赖或包间环?
- [ ] 是否消除了魔法字符串与硬编码阈值?
- [ ] 六级输出结构是否齐全?
---
## 反例(禁止)
- 在单个 `handle` 方法内用长 `if-else` 模拟多段责任(应拆类)。
- `HandlerA` 注入 `HandlerB`,同时 `HandlerB` 注入 `HandlerA`。
- 链顺序写死在业务 Service 的多处复制粘贴(应唯一装配点)。
examples.md:
# 责任链完整示例(权限 → 审批 → 过滤)
可作为 `/chain-of-responsibility` 生成代码时的参照;包名 `com.example.workflow` 可按项目修改。
## OrderWorkflowContext.java
```java
package com.example.workflow;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class OrderWorkflowContext {
private boolean stopped;
private String stopReason;
private String userId;
private List<String> roles = new ArrayList<>();
private int orderAmountFen;
private String region;
private boolean approved;
private final List<String> auditTrail = new ArrayList<>();
public void stop(String reason) {
this.stopped = true;
this.stopReason = reason;
}
public boolean isStopped() { return stopped; }
public String getStopReason() { return stopReason; }
public String getUserId() { return userId; }
public void setUserId(String userId) { this.userId = userId; }
public List<String> getRoles() { return Collections.unmodifiableList(roles); }
public void setRoles(List<String> roles) { this.roles = new ArrayList<>(roles); }
public int getOrderAmountFen() { return orderAmountFen; }
public void setOrderAmountFen(int orderAmountFen) { this.orderAmountFen = orderAmountFen; }
public String getRegion() { return region; }
public void setRegion(String region) { this.region = region; }
public boolean isApproved() { return approved; }
public void setApproved(boolean approved) { this.approved = approved; }
public List<String> getAuditTrail() { return Collections.unmodifiableList(auditTrail); }
public void trace(String line) { this.auditTrail.add(line); }
}
```
## WorkflowHandler.java
```java
package com.example.workflow;
public abstract class WorkflowHandler {
private WorkflowHandler next;
public void setNext(WorkflowHandler next) { this.next = next; }
public final void handle(OrderWorkflowContext ctx) {
if (ctx.isStopped()) return;
doHandle(ctx);
if (!ctx.isStopped() && next != null) next.handle(ctx);
}
protected abstract void doHandle(OrderWorkflowContext ctx);
}
```
## PermissionCheckHandler.java(权限校验 · 可中断)
```java
package com.example.workflow;
import java.util.Objects;
import java.util.Set;
public class PermissionCheckHandler extends WorkflowHandler {
private final Set<String> blockedRegions;
private final String requiredRole;
public PermissionCheckHandler(Set<String> blockedRegions, String requiredRole) {
this.blockedRegions = Objects.requireNonNull(blockedRegions);
this.requiredRole = Objects.requireNonNull(requiredRole);
}
@Override
protected void doHandle(OrderWorkflowContext ctx) {
ctx.trace("Permission: check roles and region");
boolean hasRole = ctx.getRoles().stream().anyMatch(requiredRole::equals);
if (!hasRole) {
ctx.stop("缺少角色: " + requiredRole);
return;
}
if (ctx.getRegion() != null && blockedRegions.contains(ctx.getRegion())) {
ctx.stop("地区禁止下单: " + ctx.getRegion());
}
}
}
```
## ApprovalHandler.java(审批流 · 大额需审批)
```java
package com.example.workflow;
public class ApprovalHandler extends WorkflowHandler {
private final int approvalThresholdFen;
public ApprovalHandler(int approvalThresholdFen) {
this.approvalThresholdFen = approvalThresholdFen;
}
@Override
protected void doHandle(OrderWorkflowContext ctx) {
ctx.trace("Approval: threshold=" + approvalThresholdFen);
if (ctx.getOrderAmountFen() >= approvalThresholdFen && !ctx.isApproved()) {
ctx.stop("大额订单需审批通过");
return;
}
ctx.trace("Approval: passed");
}
}
```
## RegionFilterHandler.java(过滤链 · 全链路尾部记录)
```java
package com.example.workflow;
public class RegionFilterHandler extends WorkflowHandler {
@Override
protected void doHandle(OrderWorkflowContext ctx) {
ctx.trace("Filter: region=" + ctx.getRegion());
// 示例:仅追加审计信息,不中断
}
}
```
## OrderWorkflowChain.java(装配)
```java
package com.example.workflow;
import java.util.Set;
public class OrderWorkflowChain {
private final WorkflowHandler head;
public OrderWorkflowChain(WorkflowProperties props) {
PermissionCheckHandler p = new PermissionCheckHandler(
Set.copyOf(props.getBlockedRegions()),
props.getRequiredRole());
ApprovalHandler a = new ApprovalHandler(props.getApprovalThresholdFen());
RegionFilterHandler f = new RegionFilterHandler();
p.setNext(a);
a.setNext(f);
this.head = p;
}
public void execute(OrderWorkflowContext ctx) {
head.handle(ctx);
}
}
```
## WorkflowProperties.java(避免硬编码)
```java
package com.example.workflow;
import java.util.ArrayList;
import java.util.List;
public class WorkflowProperties {
private List<String> blockedRegions = new ArrayList<>();
private String requiredRole = "BUYER";
private int approvalThresholdFen = 100_000;
public List<String> getBlockedRegions() { return blockedRegions; }
public void setBlockedRegions(List<String> blockedRegions) { this.blockedRegions = blockedRegions; }
public String getRequiredRole() { return requiredRole; }
public void setRequiredRole(String requiredRole) { this.requiredRole = requiredRole; }
public int getApprovalThresholdFen() { return approvalThresholdFen; }
public void setApprovalThresholdFen(int approvalThresholdFen) { this.approvalThresholdFen = approvalThresholdFen; }
}
```
## DemoMain.java(使用示例)
```java
package com.example.workflow;
import java.util.List;
public class DemoMain {
public static void main(String[] args) {
WorkflowProperties props = new WorkflowProperties();
props.setBlockedRegions(List.of("XX"));
props.setRequiredRole("BUYER");
props.setApprovalThresholdFen(50_000);
OrderWorkflowChain chain = new OrderWorkflowChain(props);
OrderWorkflowContext ok = new OrderWorkflowContext();
ok.setUserId("u1");
ok.setRoles(List.of("BUYER"));
ok.setOrderAmountFen(10_000);
ok.setRegion("SH");
ok.setApproved(false);
chain.execute(ok);
System.out.println("stopped=" + ok.isStopped() + " reason=" + ok.getStopReason());
System.out.println(ok.getAuditTrail());
OrderWorkflowContext denied = new OrderWorkflowContext();
denied.setUserId("u2");
denied.setRoles(List.of("GUEST"));
denied.setOrderAmountFen(10_000);
chain.execute(denied);
System.out.println("stopped=" + denied.isStopped() + " reason=" + denied.getStopReason());
}
}
```
说明:`PermissionCheckHandler` 演示 **拦截**;`ApprovalHandler` 演示 **条件中断**;`RegionFilterHandler` 演示 **全链路尾部环节**。配置通过 `WorkflowProperties` 注入,避免魔法数。