ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

字段校验规则清单:从基础到高级实践

字段校验规则清单:从基础到高级实践

1. 为什么我们需要字段校验规则清单?

在开发任何涉及用户输入或数据交互的系统时,字段校验都是保证数据质量和系统稳定性的第一道防线。我见过太多因为前端校验不严谨导致数据库崩溃的案例——比如一个简单的年龄字段,如果只在前端用HTML5的number类型限制,攻击者完全可以绕过前端直接调用API接口提交"年龄=一百万岁"这样的荒谬数据。

字段校验的核心价值在于:

  • 数据完整性:确保必填字段不被遗漏
  • 业务合规性:比如金额不能为负数,身份证号必须符合规则
  • 系统安全性:防止SQL注入、XSS等攻击
  • 用户体验:即时反馈比提交后报错更友好

2. 基础校验类型详解

2.1 必填校验(Required)

这是最基本的校验类型,但实际应用中远比if(!value) throw error复杂。以用户注册表单为例:

// 错误示范 - 仅检查空字符串 function validateRequired(value) { return value !== ''; } // 正确做法 - 考虑各种边界情况 function validateRequired(value) { return ( value !== undefined && value !== null && (typeof value !== 'string' || value.trim() !== '') && (!Array.isArray(value) || value.length > 0) ); }

常见坑点:

  • 数字0会被误判为空值
  • 空格字符串通过校验
  • 空数组未被正确处理
  • 多选框至少选一项的场景

2.2 范围校验(Range)

范围校验通常用于数字、日期等可比较类型:

// 日期范围校验示例 function validateDateRange(date, minDate, maxDate) { const timestamp = new Date(date).getTime(); return ( timestamp >= new Date(minDate).getTime() && timestamp <= new Date(maxDate).getTime() ); }

特殊场景处理:

  • 开区间 vs 闭区间(是否包含边界值)
  • 时区处理(建议统一转为UTC时间比较)
  • 浮点数精度问题(金额比较建议使用decimal.js)

3. 高级校验类型实现

3.1 唯一性校验(Unique)

唯一校验需要与数据库交互,实现时要注意:

// Spring Boot JPA实现示例 @Column(unique = true) private String username; // 自定义唯一校验逻辑 public void checkUniqueEmail(String email) { if (userRepository.existsByEmail(email)) { throw new BusinessException("邮箱已被注册"); } }

性能优化技巧:

  • 对高频查询字段添加数据库唯一索引
  • 使用Redis做缓存层校验
  • 批量导入时先collect+groupBy内存去重

3.2 组合唯一校验(Composite Unique)

当唯一性需要多个字段组合确定时:

-- MySQL联合唯一索引 ALTER TABLE orders ADD CONSTRAINT uk_order_item UNIQUE (user_id, product_id, date);

实际案例: 电商系统中,同一个用户对同一商品每天只能提交一次评价,就需要(user_id, product_id, date)的组合唯一约束。

4. 正则表达式实战指南

4.1 常用正则模式

校验目标正则表达式说明
手机号^1[3-9]\d{9}$中国大陆手机号
邮箱^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$兼容大多数常见格式
身份证号`^[1-9]\d{5}(1819

4.2 正则优化技巧

  1. 预编译正则:对于高频使用的正则,提前编译提升性能

    private static final Pattern PHONE_PATTERN = Pattern.compile("^1[3-9]\\d{9}$");
  2. 避免灾难性回溯:

    • 慎用嵌套量词(a+)+
    • 用具体字符类\d替代通配符.
  3. 可读性维护:

    // 使用命名捕获组(ES2018+) const dateRegex = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/; const { groups: { year, month, day } } = dateRegex.exec('2023-05-15');

5. 校验规则组合策略

5.1 校验顺序优化

合理的校验顺序可以提升性能和用户体验:

  1. 先做本地可验证的规则(必填、格式)
  2. 再做需要服务端交互的规则(唯一性)
  3. 最后执行耗时的业务规则校验

5.2 多语言错误消息

// 错误码映射方案 const errorMessages = { 'required': { 'zh-CN': '${field}不能为空', 'en-US': '${field} is required' }, 'email': { 'zh-CN': '邮箱格式不正确', 'en-US': 'Invalid email format' } }; function getMessage(rule, field, lang = 'zh-CN') { return errorMessages[rule][lang] .replace('${field}', field); }

6. 校验表设计模板

6.1 基础字段校验表

字段名类型必填范围格式唯一性关联字段
用户名string是2-20字符中文/字母全局唯一-
手机号string是11位数字1开头全局唯一国家区号
密码string是8-32位大小写+数字-密码强度(前端)

6.2 状态流转校验

对于订单状态等需要校验状态机的场景:

# 状态流转规则示例 ALLOWED_TRANSITIONS = { 'CREATED': ['PAID', 'CANCELLED'], 'PAID': ['SHIPPED', 'REFUNDING'], 'SHIPPED': ['COMPLETED', 'RETURNING'] } def validate_transition(current, next): if next not in ALLOWED_TRANSITIONS.get(current, []): raise InvalidStateError(f"Cannot change from {current} to {next}")

7. 前端与后端校验协同

7.1 分层校验策略

层级校验重点实现方式
前端即时反馈、基础格式JS/TS、表单库校验
API网关参数完整性、基础类型JSON Schema、参数过滤器
服务端业务规则、数据一致性领域模型校验、数据库约束
数据库最终一致性保障唯一索引、外键、CHECK约束

7.2 校验逻辑复用方案

推荐使用JSON Schema实现前后端统一校验:

// 用户注册Schema示例 { "$schema": "http://json-schema.org/draft-07/schema#", "type": "object", "required": ["username", "password", "email"], "properties": { "username": { "type": "string", "minLength": 2, "maxLength": 20, "pattern": "^[a-zA-Z\u4e00-\u9fa5]+$" }, "password": { "type": "string", "minLength": 8, "maxLength": 32, "pattern": "^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d).+$" } } }

8. 性能优化与异常处理

8.1 批量校验优化

当处理CSV导入等批量操作时:

// 使用Hibernate Validator进行批量校验 Validator validator = Validation.buildDefaultValidatorFactory().getValidator(); Set<ConstraintViolation<User>> violations = new HashSet<>(); for (User user : users) { violations.addAll(validator.validate(user)); if (violations.size() > 50) break; // 达到阈值提前终止 }

8.2 优雅的错误收集

// 前端错误收集示例 const errors = {}; function validateField(field, value) { const fieldErrors = []; if (rules.required && !value) { fieldErrors.push('必填字段'); } if (rules.pattern && !new RegExp(rules.pattern).test(value)) { fieldErrors.push('格式不符'); } if (fieldErrors.length) { errors[field] = fieldErrors; } } // 最终返回结构化错误 { "username": ["必填字段", "至少2个字符"], "email": ["邮箱格式不正确"] }

9. 现代校验库推荐

9.1 前端校验库对比

库名特点适用场景
Yup声明式Schema,TypeScript友好React/Vue表单
Joi功能强大,浏览器/Node通用全栈应用
VeeValidateVue专用,模板集成友好Vue 2/3项目
Zod类型安全优先TypeScript重度项目

9.2 后端校验框架

Spring Boot示例:

@Data public class UserDTO { @NotBlank(message = "用户名不能为空") @Size(min = 2, max = 20, message = "用户名2-20个字符") private String username; @Email(message = "邮箱格式不正确") private String email; @AssertTrue(message = "必须接受协议") private boolean agreed; }

Django示例:

from django.core.validators import RegexValidator phone_validator = RegexValidator( regex=r'^1[3-9]\d{9}$', message="手机号格式不正确" ) class User(models.Model): phone = models.CharField( max_length=11, validators=[phone_validator], unique=True )

10. 复杂业务规则校验

10.1 跨字段依赖校验

// 密码与确认密码匹配校验 function validatePasswordMatch(data) { if (data.password !== data.confirmPassword) { return { isValid: false, errors: { confirmPassword: '两次输入密码不一致' } }; } return { isValid: true }; }

10.2 条件必填逻辑

// 当支付方式为银行转账时,账号信息必填 public class PaymentRequest { @NotNull private PaymentType type; @NotBlank(groups = BankTransfer.class) private String accountNumber; @Valid private BankInfo bankInfo; public interface BankTransfer {} @AssertTrue(message = "银行转账需要完整账号信息") private boolean isValidBankTransfer() { return type != PaymentType.BANK_TRANSFER || (accountNumber != null && bankInfo != null); } }

11. 测试策略

11.1 单元测试覆盖

// Jest测试示例 describe('validateEmail', () => { test('接受标准邮箱', () => { expect(validateEmail('test@example.com')).toBeTruthy(); }); test('拒绝无@符号的字符串', () => { expect(validateEmail('invalid-email')).toBeFalsy(); }); });

11.2 边界值测试

// JUnit参数化测试 @ParameterizedTest @ValueSource(strings = {"", " ", "a", "a@b", "a@b.c"}) void testEmailBoundary(String email) { assertFalse(validator.validateEmail(email)); }

12. 安全注意事项

重要:所有前端校验都只能提升用户体验,必须同时在服务端做完全相同的校验

  1. SQL注入防护:

    • 永远不要用字符串拼接构造SQL
    • 使用预编译语句或ORM框架
  2. XSS防护:

    // 转义HTML输出 function escapeHtml(unsafe) { return unsafe .replace(/&/g, "&amp;") .replace(/</g, "&lt;") .replace(/>/g, "&gt;"); }
  3. 正则DoS防护:

    • 避免使用用户输入作为正则表达式
    • 对复杂正则设置超时机制

13. 移动端特殊处理

13.1 小程序表单校验

// 微信小程序示例 Page({ formSubmit(e) { const { value } = e.detail; if (!value.username) { wx.showToast({ title: '用户名必填', icon: 'none' }); return; } // 调用云函数进行服务端校验 wx.cloud.callFunction({ name: 'validateForm', data: value }); } });

13.2 输入法兼容问题

常见问题:

  • 中文输入法下触发过早校验
  • 全角/半角字符差异
  • 移动键盘特殊符号处理

解决方案:

// 延迟校验触发 let composing = false; input.addEventListener('compositionstart', () => composing = true); input.addEventListener('compositionend', () => { composing = false; validate(); });

14. 国际化(i18n)支持

14.1 多语言错误消息

// 基于i18n的校验错误配置 const messages = { en: { validation: { required: '{field} is required', email: 'Invalid email format' } }, zh: { validation: { required: '{field}不能为空', email: '邮箱格式不正确' } } }; function getMessage(rule, field, locale) { return messages[locale].validation[rule] .replace('{field}', field); }

14.2 本地化格式校验

// Java本地化手机号校验 public boolean validatePhoneNumber(String number, Locale locale) { if (locale.getCountry().equals("CN")) { return number.matches("^1[3-9]\\d{9}$"); } else if (locale.getCountry().equals("US")) { return number.matches("^\\+1\\d{10}$"); } // 其他地区规则... }

15. 可视化配置方案

15.1 低代码校验配置

// 可视化编辑器生成的校验配置 { "fields": [ { "name": "username", "label": "用户名", "type": "string", "rules": [ { "type": "required", "message": "用户名必填" }, { "type": "minLength", "value": 2 }, { "type": "maxLength", "value": 20 } ] } ] }

15.2 动态规则加载

// 从服务端获取校验规则 async function loadValidationRules(formId) { const response = await fetch(`/api/validation-rules/${formId}`); return response.json(); } // 初始化动态表单 const rules = await loadValidationRules('user-registration'); const validator = new Validator(rules);

16. 历史数据迁移校验

16.1 脏数据处理策略

-- 找出不符合新规则的历史数据 SELECT * FROM users WHERE LENGTH(username) < 2 OR LENGTH(username) > 20;

16.2 渐进式校验迁移

  1. 先添加数据库约束NOT NULL
  2. 部署新校验逻辑到服务端
  3. 最后更新前端校验规则
  4. 对历史数据分批清洗

17. 微服务场景下的分布式校验

17.1 唯一性校验挑战

在分布式系统中,需要额外考虑:

// 使用Redis分布式锁保证唯一性校验原子性 public boolean checkUniqueWithLock(String key, String value) { String lockKey = "lock:" + key + ":" + value; try { // 尝试获取分布式锁 boolean locked = redisTemplate.opsForValue() .setIfAbsent(lockKey, "1", Duration.ofSeconds(5)); if (!locked) throw new BusyException("操作太频繁"); return !repository.existsByField(key, value); } finally { redisTemplate.delete(lockKey); } }

17.2 最终一致性方案

对于允许短暂重复的场景:

  1. 先快速通过内存校验
  2. 异步队列处理最终一致性检查
  3. 发现冲突后触发补偿机制

18. 校验规则版本管理

18.1 规则变更策略

  1. 非破坏性变更:

    • 放宽校验条件(如长度上限增加)
    • 添加可选字段校验
  2. 破坏性变更:

    • 收紧校验条件
    • 修改必填字段
    • 需要配合数据迁移和版本通知

18.2 版本化校验配置

# 校验规则版本控制示例 version: 1.2.0 effective_date: 2023-06-01 fields: username: min_length: 2 max_length: 20 email: format: standard required: true

19. 机器学习辅助校验

19.1 异常输入检测

使用简单ML模型识别可疑输入:

# 使用TF-IDF检测异常输入示例 from sklearn.feature_extraction.text import TfidfVectorizer from sklearn.ensemble import IsolationForest # 训练异常检测模型 vectorizer = TfidfVectorizer() X = vectorizer.fit_transform(normal_samples) clf = IsolationForest().fit(X) # 检测异常输入 def is_abnormal(input): vec = vectorizer.transform([input]) return clf.predict(vec)[0] == -1

19.2 智能纠错建议

// 邮箱纠错示例 function suggestEmailCorrection(email) { const commonTypos = { 'gamil.com': 'gmail.com', 'hotnail.com': 'hotmail.com' }; for (const [wrong, correct] of Object.entries(commonTypos)) { if (email.endsWith(wrong)) { return email.replace(wrong, correct); } } return null; }

20. 无障碍(A11Y)校验考量

20.1 错误提示的可访问性

<!-- 正确的错误提示方式 --> <div class="form-group"> <label for="email">邮箱</label> <input id="email" type="email" aria-describedby="email-error"> <div id="email-error" class="error-message" role="alert"> 请输入有效的邮箱地址 </div> </div>

20.2 校验时机选择

  • 即时校验:适合简单格式校验(用input事件)
  • 失焦校验:适合复杂校验(用blur事件)
  • 提交校验:最终保障(用submit事件)

21. 性能监控与调优

21.1 校验耗时统计

// 前端性能监控 function withValidationMetrics(fn) { return function(...args) { const start = performance.now(); const result = fn(...args); const duration = performance.now() - start; metrics.track('validation_time', { field: args[0], duration: duration }); return result; }; } const validateEmail = withValidationMetrics(email => { return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email); });

21.2 高频校验优化

对于自动完成等高频触发场景:

// 防抖校验实现 const debouncedValidate = _.debounce(validate, 300); input.addEventListener('input', () => { debouncedValidate(input.value); });

22. 领域特定校验模式

22.1 电商领域示例

商品库存校验:

public void validateInventory(OrderItem item) { Product product = productRepository.findById(item.getProductId()); if (product.getStock() < item.getQuantity()) { throw new InventoryException("库存不足"); } if (product.getStatus() != ProductStatus.ON_SALE) { throw new BusinessException("商品已下架"); } }

22.2 金融领域示例

金额校验:

from decimal import Decimal, getcontext getcontext().prec = 6 def validate_amount(amount): if not isinstance(amount, Decimal): amount = Decimal(str(amount)) if amount <= Decimal('0'): raise ValueError("金额必须大于0") if amount.as_tuple().exponent < -2: raise ValueError("最多支持两位小数")

23. 校验规则文档化

23.1 Swagger集成示例

@Schema(description = "用户注册参数") public class RegisterDTO { @Schema(description = "用户名", required = true, minLength = 2, maxLength = 20) @NotBlank @Size(min = 2, max = 20) private String username; @Schema(description = "邮箱", format = "email") @Email private String email; }

23.2 校验规则导出

// 将校验规则导出为Markdown文档 function generateValidationDocs(rules) { let md = `# 字段校验规则\n\n`; Object.entries(rules).forEach(([field, rule]) => { md += `## ${field}\n`; md += `- 类型: ${rule.type}\n`; if (rule.required) md += `- 必填: 是\n`; if (rule.minLength) md += `- 最小长度: ${rule.minLength}\n`; if (rule.pattern) md += `- 正则: \`${rule.pattern}\`\n`; md += '\n'; }); return md; }

24. 校验规则测试数据生成

24.1 合法测试数据

// 根据校验规则生成合法测试数据 function generateValidData(rules) { const data = {}; Object.entries(rules).forEach(([field, rule]) => { if (rule.type === 'string') { data[field] = generateString(rule); } else if (rule.type === 'number') { data[field] = generateNumber(rule); } }); return data; } function generateString(rule) { const length = rule.minLength || 5; let result = ''; // 生成逻辑... return result; }

24.2 边界测试数据

// JUnit 5参数化测试数据 static Stream<Arguments> invalidUsernames() { return Stream.of( Arguments.of(""), // 空字符串 Arguments.of(" "), // 空格 Arguments.of("a"), // 太短 Arguments.of("very_long_username_exceeding_limit") // 太长 ); } @ParameterizedTest @MethodSource("invalidUsernames") void testInvalidUsernames(String username) { assertFalse(validator.validateUsername(username)); }

25. 校验规则的自动化重构

25.1 重复规则提取

// 提取公共邮箱校验规则 const commonRules = { email: { pattern: /^[^\s@]+@[^\s@]+\.[^\s@]+$/, message: '邮箱格式不正确' } }; // 在多个表单中复用 const loginRules = { email: commonRules.email, password: { required: true } };

25.2 规则版本迁移工具

# 规则升级脚本示例 def migrate_validation_rules_v1_to_v2(old_rules): new_rules = {} for field, rule in old_rules.items(): new_rule = { 'type': rule['field_type'], 'constraints': [] } if rule.get('required'): new_rule['constraints'].append({ 'type': 'required' }) # 其他规则转换逻辑... new_rules[field] = new_rule return new_rules

26. 校验规则的动态调整

26.1 基于上下文的规则

// 根据用户类型动态调整校验规则 function getValidationRules(userType) { const baseRules = { username: { required: true, minLength: 2 } }; if (userType === 'admin') { return { ...baseRules, email: { required: true, pattern: /@company\.com$/ } }; } return baseRules; }

26.2 运行时规则修改

// 动态更新校验规则 public class DynamicValidator { private Map<String, Predicate<String>> rules = new ConcurrentHashMap<>(); public void addRule(String field, Predicate<String> rule) { rules.put(field, rule); } public boolean validate(String field, String value) { return rules.getOrDefault(field, v -> true).test(value); } }

27. 校验规则可视化调试

27.1 规则调试面板

<div class="validator-debugger"> <h3>校验规则测试</h3> <select id="rule-selector"> <option value="email">邮箱校验</option> <option value="phone">手机号校验</option> </select> <input id="test-input" type="text"> <button id="test-button">测试</button> <div id="test-result"></div> </div> <script> document.getElementById('test-button').addEventListener('click', () => { const rule = document.getElementById('rule-selector').value; const value = document.getElementById('test-input').value; const isValid = validators[rule](value); document.getElementById('test-result').textContent = isValid ? '✓ 验证通过' : '✗ 验证失败'; }); </script>

27.2 正则表达式可视化

使用工具如regexper.com生成正则表达式图解,帮助团队理解复杂规则:

^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}$

对应可视化图形可以清晰展示邮箱校验的各个组成部分。

28. 校验规则的AB测试

28.1 不同严格度的规则对比

// 定义不同严格级别的校验规则 const validationVariants = { relaxed: { password: { minLength: 6 } }, standard: { password: { minLength: 8, requireSpecialChar: true } }, strict: { password: { minLength: 12, requireSpecialChar: true, requireMixedCase: true } } }; // 根据用户分组应用不同规则 function getVariantRules(userId) { const variant = getUserVariant(userId); // AB测试分组逻辑 return validationVariants[variant]; }

28.2 校验规则效果分析

通过埋点收集数据:

指标宽松版标准版严格版
注册转化率85%78%65%
首次登录成功率92%95%98%
客服投诉率12%8%3%

根据业务目标选择最佳平衡点。

29. 校验规则的知识管理

29.1 规则决策记录

为每个重要校验规则创建ADR(Architecture Decision Record):

# 密码强度校验规则决策 ## 状态 已通过 ## 背景 现有系统密码规则仅为6位任意字符,安全评估显示需要增强 ## 决策 采用以下密码规则: - 最小长度8位 - 必须包含字母和数字 - 可选包含特殊字符 ## 后果 - 安全性提升,预计减少30%的暴力破解风险 - 注册转化率可能下降5-8% - 需要更新所有客户端提示文案

29.2 规则变更通知

建立校验规则变更的沟通机制:

  1. 修改前:在团队频道公告+文档标注"即将变更"
  2. 修改后:更新接口版本号,维护旧版本至少一个迭代周期
  3. 提供自动检测工具帮助调用方升级

30. 新兴技术对校验的影响

30.1 无密码登录的校验变化

传统校验:

{ username: { required: true }, password: { required: true, minLength: 8 } }

无密码登录校验:

{ email: { required: true, format: 'email' }, magicLink: { expiresIn: '15m' } }

30.2 生物识别校验

// iOS Face ID校验示例 let context = LAContext() var error: NSError? if context.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: &error) { context.evaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, localizedReason: "验证以继续") { success, error in DispatchQueue.main.async { if success { // 校验通过 } else { // 处理错误 } } } }

31. 校验规则的自动化测试

31.1 规则覆盖度检测

# 使用突变测试验证校验规则有效性 def test_validation_mutations(validator): # 原始合法数据 valid_data = {"email": "test@example.com"} assert validator.validate(valid_data) # 生成突变数据 mutations = [ {"email": "invalid-email"}, # 移除@符号 {"email": "test@example"}, # 移除顶级域名 {"email": ""}, # 空字符串 {"email": "a@b.c" * 100} # 超长字符串 ] # 验证所有突变都应被捕获 for mutation in mutations: assert not validator.validate(mutation)

31.2 规则性能基准

@BenchmarkMode(Mode.AverageTime) @OutputTimeUnit(TimeUnit.MICROSECONDS) public class EmailValidatorBenchmark { private static final String[] TEST_EMAILS = { "valid@example.com", "invalid.email@", "another.valid@test.org" }; @Benchmark public void benchmarkEmailValidation(Blackhole bh) { for (String email : TEST_EMAILS) { bh.consume(EmailValidator.validate(email)); } } }

32. 校验规则的错误分类

32.1 错误严重等级

等级类型示例处理方式
1安全风险SQL注入特征阻断请求并记录安全日志
2业务规则违反订单金额为负拒绝并返回明确错误
3格式问题邮箱缺少@符号提示用户修正
4建议性提示密码强度较弱警告但允许继续

32.2 错误处理策略

function handleValidationErrors(errors) { const securityErrors = errors.filter(e => e.level === 1); if (securityErrors.length) { securityAlert(securityErrors); throw new BlockedRequestError('安全风险'); } // 其他错误处理逻辑... }

33. 校验规则的元数据管理

33.1 规则属性标注

# 校验规则的元数据描述 fields: email: label: 电子邮箱 rules: - type: required message: 邮箱不能为空 severity: error since: v1.0 owner: auth-team - type: pattern value: ^\S+@\S+\.\S+$ message: 邮箱格式不正确 severity: error

33.2 规则依赖分析

graph TD A[用户注册表单] -->|依赖| B(邮箱格式校验) A -->|依赖| C(密码强度校验) B -->|使用| D[正则表达式库] C -->|使用| E[密码策略服务]

34. 校验规则的质量评估

34.1 规则有效性指标

  1. 拦截率:无效请求中被正确拦截的比例
  2. 误报率:有效请求被错误拦截的比例
  3. 处理耗时:平均每个校验规则的执行时间
  4. 维护成本:修改规则所需的平均时间

34.2 规则健康度检查

def check_rule_health(validator): report = { 'redundant_rules': [], 'conflicting_rules': [], 'performance_issues': [] } # 检查冗余规则 for rule1, rule2 in combinations(validator.rules, 2): if rule1.implies(rule2): report['redundant_rules'].append(f"{rule1} 使 {rule2} 冗余") # 性能检测 for rule in validator.rules: if rule.avg_time > 100ms: report['performance_issues'].append(rule.name) return report

35. 校验规则的可扩展设计

35.1 插件式校验架构

// 校验规则插件接口 public interface ValidationPlugin { boolean supports(String fieldType); ValidationResult validate(String fieldName, Object value); } // 实现示例 @Component public class EmailValidationPlugin implements ValidationPlugin { @Override public boolean supports(String fieldType) { return "email".equals(fieldType); } @Override public ValidationResult validate(String fieldName, Object value) { // 具体校验逻辑... } }

35.2 自定义规则DSL

// 自定义校验规则语言示例 const ruleEngine = new RuleEngine({ rules: { isAdult: { validate: value => value >=
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进