刘光辉
昨天 bb638871a7fb692d80f1b7a758f991dc0879002c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
package jnpf.audit.sdk;
 
import jnpf.audit.model.AuditEventDTO;
 
/**
 * 层 3 审计入口(Task 7 Step 4):业务方唯一入口。
 *
 * <p>{@code record(dto)} = 校验 eventType/actionCode 非空 → {@link AuditContextCollector#fill(AuditEventDTO)}
 * 填充冻结 → {@code sourceLayer} 缺省补 3(层 3 入口默认 sourceLayer=3;调用方已显式传值则不覆盖,见下)
 * → {@link AuditTxHolder#submit(AuditEventDTO, AuditEventPublisher)} 交事务 holder 缓冲
 * (有事务则 afterCommit 才发、回滚不发;无事务直发)。
 *
 * <p>{@code audit.enabled=false} 或当前请求不在 {@link AuditRequestScopeFilter} 允许范围内时,
 * {@code record} 直接 no-op。
 */
public class AuditClient {
 
    private final AuditContextCollector collector;
    private final AuditEventPublisher publisher;
    private final boolean enabled;
    private final AuditRequestScopeFilter requestScopeFilter;
 
    public AuditClient(AuditContextCollector collector, AuditEventPublisher publisher, boolean enabled) {
        this(collector, publisher, enabled, new AuditRequestScopeFilter(false, ""));
    }
 
    public AuditClient(AuditContextCollector collector, AuditEventPublisher publisher, boolean enabled,
                       AuditRequestScopeFilter requestScopeFilter) {
        this.collector = collector;
        this.publisher = publisher;
        this.enabled = enabled;
        this.requestScopeFilter = requestScopeFilter;
    }
 
    public void record(AuditEventDTO dto) {
        if (!enabled || !requestScopeFilter.acceptsCurrentRequest()) {
            return;
        }
        if (dto == null) {
            throw new IllegalArgumentException("审计事件 dto 不能为空");
        }
        if (isBlank(dto.getEventType())) {
            throw new IllegalArgumentException("eventType 不能为空");
        }
        if (isBlank(dto.getActionCode())) {
            throw new IllegalArgumentException("actionCode 不能为空");
        }
        collector.fill(dto);
        if (dto.getSourceLayer() == null) {
            // 裁定修复 B:本 SDK 是层 3 显式接口入口,语义上 sourceLayer 恒为 3;
            // 调用方未显式传值时在此补齐,否则服务端 validate(sourceLayer 非空硬校验)会拒收该事件。
            // 调用方已显式传值(如上层框架转发已知层号)则尊重不覆盖。
            dto.setSourceLayer(3);
        }
        AuditTxHolder.submit(dto, publisher);
    }
 
    private static boolean isBlank(String s) {
        return s == null || s.trim().isEmpty();
    }
}