核心思路是用自定义注解声明校验规则,通过反射运行时读取执行,并在MySQL写入前统一拦截验证;注解需@Target(FIELD)和@Retention(RUNTIME),支持required/min/max/pattern/message等属性;泛型validate(T bean)方法遍历字段、提取注解、委托对应校验器,失败抛ValidationException;可集成MyBatis拦截器、JDBC封装或Spring MVC参数解析器实现自动校验;同时需保持JavaBean注解与MySQL表结构(如NOT NULL、VARCHAR长度)及命名规范一致。

核心思路是:用自定义注解声明校验规则,靠反射在运行时读取并执行校验,再在数据写入 MySQL 前统一拦截验证——不改业务逻辑,只加注解就能控制字段是否必填、长度范围、格式等。
定义校验用的自定义注解
注解必须保留在运行时,且仅作用于字段,才能被反射读取:
- @Target(ElementType.FIELD) —— 只允许标注在字段上,和 JavaBean 属性一一对应
- @Retention(RetentionPolicy.RUNTIME) —— 编译后仍保留,反射才能获取
- 提供可配置属性,如 required()、min()、max()、pattern()、message(),方便产品或前端提需求时直接填写
例如:@NotBlank(message = "用户名不能为空") private String username;
用反射遍历字段并触发校验
写一个泛型校验方法 validate(T bean),内部完成四步:
立即学习“Java免费学习笔记(深入)”;
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 调用 bean.getClass().getDeclaredFields() 获取所有字段
- 对每个字段 setAccessible(true),跳过 static/final 字段
- 用 field.getAnnotation(NotBlank.class) 等提取注解实例
- 根据注解类型匹配预置校验器(如 NotBlankValidator 校验非空、PatternValidator 校验正则),失败则收集错误信息
校验失败统一抛出 ValidationException,含字段名 + 自定义 message,便于上层统一处理或返回前端。
在落库前自动拦截验证
避免手动调用 validate(),而是嵌入到数据持久化流程的关键节点:
- MyBatis 场景:实现 ResultSetHandler 拦截器,在查询结果映射为 JavaBean 后立即校验;或在 Executor 拦截器中,在 insert/update 执行前校验入参对象
- JDBC 场景:封装 insert 方法,在 doSql() 执行 SQL 前先调用 validate(bean)
- Spring MVC 场景:配合 @Valid 或自定义 HandlerMethodArgumentResolver,在 Controller 接收参数绑定完成后自动触发
这样只要 JavaBean 落库,就必然经过校验,无需每处 insert 都写 if-check。
配合数据库字段做一致性约束
注解校验只是应用层防护,MySQL 层也需同步加固:
- JavaBean 字段加 @Column(nullable = false) 或 @Size(max = 20) 时,建表语句应同步设 NOT NULL、VARCHAR(20) 等
- 注意 MySQL 在 Linux 下大小写敏感,实体类字段名与数据库列名保持完全一致(推荐全小写+下划线)
- 若使用 MyBatis-Plus,可用 @TableField(fill = FieldFill.INSERT) 配合 MetaObjectHandler 自动填充 create_time,再结合注解校验其非空或格式

















