JeecgBoot表单验证:自定义校验规则+异步验证实现
在企业级应用开发中,表单验证是确保数据完整性和准确性的关键环节。JeecgBoot作为一款强大的低代码开发平台,提供了丰富而灵活的表单验证机制,本文将深入探讨其自定义校验规则和异步验证的实现方式。
表单验证体系概述
JeecgBoot基于Ant Design Vue和SpringBoot构建了完整的表单验证体系,支持:
- 基础验证:必填项、格式验证、长度限制等
- 自定义验证规则:业务逻辑验证、复杂条件判断
- 异步验证:服务端数据校验、实时查重验证
- 组合验证:多规则组合、条件触发验证
基础验证规则实现
内置验证器
JeecgBoot提供了丰富的内置验证规则,位于 src/utils/helper/validator.ts:
// 邮箱验证
email(required) {
return [{
required: required ? required : false,
validator: async (_rule, value) => {
if (required == true && !value) {
return Promise.reject('请输入邮箱!');
}
if (value && !new RegExp(
/^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/
).test(value)) {
return Promise.reject('请输入正确邮箱格式!');
}
return Promise.resolve();
},
trigger: 'change',
}];
}
// 手机号验证
phone(required) {
return [{
required: required,
validator: async (_, value) => {
if (required && !value) {
return Promise.reject('请输入手机号码!');
}
if (!/^1[3456789]\d{9}$/.test(value)) {
return Promise.reject('手机号码格式有误');
}
return Promise.resolve();
},
trigger: 'change',
}];
}
密码强度验证
rules: [{
required: true,
message: '请输入登录密码',
}, {
pattern: /^(?=.*[a-zA-Z])(?=.*\d)(?=.*[~!@#$%^&*()_+`\-={}:";'<>?,./]).{8,}$/,
message: '密码由8位数字、大小写字母和特殊符号组成!',
}]
自定义校验规则开发
1. 时间范围验证
实现开始时间和结束时间的关联验证:
startTime(endTime, required) {
return [{
required: required ? required : false,
validator: (_, value) => {
if (required && !value) {
return Promise.reject('请选择开始时间');
}
if (endTime && value && dateUtil(endTime).isBefore(value)) {
return Promise.reject('开始时间需小于结束时间');
}
return Promise.resolve();
},
trigger: 'change',
}];
}
endTime(startTime, required) {
return [{
required: required ? required : false,
validator: (_, value) => {
if (required && !value) {
return Promise.reject('请选择结束时间');
}
if (startTime && value && dateUtil(value).isBefore(startTime)) {
return Promise.reject('结束时间需大于开始时间');
}
return Promise.resolve();
},
trigger: 'change',
}];
}
2. 密码确认验证
confirmPassword(values, required) {
return [{
required: required ? required : false,
validator: (_, value) => {
if (!value) {
return Promise.reject('密码不能为空');
}
if (value !== values.password) {
return Promise.reject('两次输入的密码不一致!');
}
return Promise.resolve();
},
}];
}
3. Cron表达式验证器
实现复杂的Cron表达式格式验证:
const cronRule: ValidatorRule = {
validator({}, value) {
if (!value) return Promise.resolve();
const values: string[] = value.split(' ').filter((item) => !!item);
if (values.length > 7) {
return Promise.reject('Cron表达式最多7项!');
}
// 年份验证
if (values.length === 7) {
const year = values[6];
if (year !== '*' && year !== '?') {
let yearValues: string[] = [];
if (year.indexOf('-') >= 0) {
yearValues = year.split('-');
} else if (year.indexOf('/')) {
yearValues = year.split('/');
} else {
yearValues = [year];
}
const checkYear = yearValues.some((item) => isNaN(Number(item)));
if (checkYear) {
return Promise.reject('Cron表达式参数[年]错误:' + year);
}
}
}
// 表达式解析验证
try {
const iter = CronParser.parseExpression(val);
iter.next();
return Promise.resolve();
} catch (e) {
return Promise.reject('Cron表达式错误:' + e);
}
},
};
异步验证实现
1. 重复数据校验
JeecgBoot提供了强大的异步重复校验机制:
// 前端验证规则
duplicateCheckRule(tableName, fieldName, model, schema, required?) {
return [{
validator: (_, value) => {
if (!value && required) {
return Promise.reject(`请输入${schema.label}`);
}
return new Promise<void>((resolve, reject) => {
duplicateCheck({
tableName,
fieldName,
fieldVal: value,
dataId: model.id,
})
.then((res) => {
res.success ? resolve() : reject(res.message || '校验失败');
})
.catch((err) => {
reject(err.message || '验证失败');
});
});
},
}];
}
// 后端校验接口
@RestController
@RequestMapping("/sys/duplicate")
@Tag(name="重复校验")
public class DuplicateCheckController {
@RequestMapping(value = "/check", method = RequestMethod.GET)
@Operation(summary="重复校验接口")
public Result<String> doDuplicateCheck(DuplicateCheckVo duplicateCheckVo) {
if(StringUtils.isEmpty(duplicateCheckVo.getFieldVal())){
return Result.error("数据为空,不作处理!");
}
if (sysDictService.duplicateCheckData(duplicateCheckVo)) {
return Result.ok("该值可用!");
} else {
return Result.error("该值不可用,系统中已存在!");
}
}
}
2. 防抖异步验证
为避免频繁请求,实现防抖机制的异步验证:
const timer = {};
export const duplicateCheckDelay = (params) => {
return new Promise((resove, rejected) => {
let key = `${params.tableName}_${params.fieldName}`;
clearTimeout(timer[key]);
timer[key] = setTimeout(() => {
defHttp
.get({ url: Api.duplicateCheck, params }, { isTransformResponse: false })
.then((res: any) => {
resove(res as any);
})
.catch((error) => {
rejected(error);
});
delete timer[key];
}, 500); // 500ms防抖延迟
});
};
实战应用示例
用户表单验证配置
export const formSchema: FormSchema[] = [
{
label: '用户账号',
field: 'username',
component: 'Input',
required: true,
dynamicRules: ({ model, schema }) =>
rules.duplicateCheckRule('sys_user', 'username', model, schema, true),
},
{
label: '登录密码',
field: 'password',
component: 'StrengthMeter',
rules: [{
required: true,
message: '请输入登录密码',
}, {
pattern: /^(?=.*[a-zA-Z])(?=.*\d)(?=.*[~!@#$%^&*()_+`\-={}:";'<>?,./]).{8,}$/,
message: '密码由8位数字、大小写字母和特殊符号组成!',
}],
},
{
label: '邮箱',
field: 'email',
component: 'Input',
required: true,
dynamicRules: ({ model, schema }) => {
return [
{ ...rules.duplicateCheckRule('sys_user', 'email', model, schema, true)[0], trigger: 'blur' },
{ ...rules.rule('email', false)[0], trigger: 'blur' },
];
},
},
{
label: '手机号码',
field: 'phone',
component: 'Input',
required: true,
dynamicRules: ({ model, schema }) => {
return [
{ ...rules.duplicateCheckRule('sys_user', 'phone', model, schema, true)[0], trigger: 'blur' },
{ pattern: /^1[3456789]\d{9}$/, message: '手机号码格式有误', trigger: 'blur' },
];
},
}
];
验证流程示意图
高级验证技巧
1. 动态验证规则
根据表单状态动态调整验证规则:
dynamicDisabled: ({ values }) => {
return !!values.id; // 编辑时禁用某些字段
},
dynamicRules: ({ model, schema }) => {
if (model.userType === 'admin') {
return [/* 管理员特殊规则 */];
}
return rules.duplicateCheckRule('sys_user', 'username', model, schema, true);
}
2. 多规则组合验证
dynamicRules: ({ model, schema }) => {
return [
{ required: true, message: '字段不能为空' },
{ min: 6, message: '最少6个字符' },
{ ...rules.duplicateCheckRule('table', 'field', model, schema, true)[0] },
{ validator: customValidator }
];
}
3. 跨字段验证
{
label: '结束时间',
field: 'endTime',
component: 'DatePicker',
dynamicRules: ({ model }) => [
{ required: true, message: '请选择结束时间' },
{
validator: (_, value) => {
if (model.startTime && value && value < model.startTime) {
return Promise.reject('结束时间必须大于开始时间');
}
return Promise.resolve();
}
}
]
}
性能优化建议
- 防抖处理:对频繁触发的验证添加防抖机制
- 缓存结果:对重复的验证请求进行缓存
- 分批验证:将验证逻辑分批执行,避免阻塞UI
- 懒加载验证器:按需加载复杂的验证逻辑
常见问题解决方案
问题1:异步验证Promise挂起
解决方案:使用防抖机制和超时处理
const validateWithTimeout = (validator, timeout = 3000) => {
return Promise.race([
validator(),
new Promise((_, reject) =>
setTimeout(() => reject(new Error('验证超时')), timeout)
)
]);
};
问题2:验证规则冲突
解决方案:明确规则优先级,使用 trigger 控制触发时机
rules: [
{ required: true, message: '必填项', trigger: 'blur' },
{ validator: asyncValidator, trigger: 'change' }
]
问题3:国际化支持
解决方案:使用JeecgBoot内置的国际化机制
validator: (_, value) => {
const { t } = useI18n();
if (!value) {
return Promise.reject(t('validation.required'));
}
return Promise.resolve();
}
总结
JeecgBoot的表单验证体系提供了从基础到高级的完整解决方案:
- ✅ 基础验证:内置丰富的验证规则
- ✅ 自定义验证:支持复杂的业务逻辑验证
- ✅ 异步验证:完整的服务端校验机制
- ✅ 性能优化:防抖、缓存等优化措施
- ✅ 错误处理:完善的错误提示和恢复机制
通过合理运用这些验证技术,可以构建出既用户友好又数据安全的企业级表单系统,显著提升应用的数据质量和用户体验。
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考



