自定义注解实现对实体类的字段进行校验

1:背景

API开发中经常会遇到一些对请求数据进行验证的情况,这时候如果使用注解就有两个好处:
1、一是验证逻辑和业务逻辑分离,代码清晰
2、二是验证逻辑可以轻松复用,只需要在要验证的地方加上注解就可以

2:解决方案

因此,我们在业务开发过程中经常遇到形形色色的注解(Java提供了一些基本的验证注解,比如 @NotNull、@Size),框架自有的注解并不是总能满足复杂的业务需求,我们可以自定义注解来满足我们的需求。方法很简单,仅需要两个东西。

2.1 一个自定义的注解,并且指定验证器

定义一个**@Odd注解,通过@interface**声明一个注解

// 校验对象里的age域的值是奇数,这时候就可以创建以下注解
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = AgeValidator.class)
public @interface Odd {
    String message() default "Age Must Be Odd";
    Class<?>[] groups() default {};
    Class<? extends Payload>[] payload() default {};
}

@Constraint 通过使用validatedBy来指定与注解关联的验证器
@Target 指明这个注解要作用在什么地方,可以是对象、域、构造器等,因为要作用在age域上,因此这里选择 FIELD
@Retention 指明了注解的生命周期,可以有SOURCE(仅保存在源码中,会被编译器丢弃),CLASS(在class文件中可用,会被VM丢弃)以及RUNTIME(在运行期也被保留),这里选择了生命周期最长的RUNTIME

@Constraint是最关键的,它表示这个注解是一个验证注解,并且指定了一个实现验证逻辑的验证器,message()指明了验证失败后返回的消息,此方法为@Constraint要求groups()和payload()也为@Constraint要求,可默认为空,详细用途可以查看@Constraint文档

2.2 验证器类 (需要实现ConstraintValidator泛型接口)

有了注解之后,就需要一个验证器来实现验证逻辑:这个就是上面 @Constraint 通过使用validatedBy 指定的类

public class AgeValidator implements ConstraintValidator<Odd,Integer> {
    @Override
    public void initialize(Odd constraintAnnotation) {
    }
    @Override
    public boolean isValid(Integer age, ConstraintValidatorContext constraintValidatorContext) {
        return age % 2 != 0;
    }
}

验证器有两个类型参数:
第一个是所属的注解(名称Odd)
第二个是注解作用地方的类型,这里因为作用在age上,因此这里用了Integer

  • initialize() 可以在验证开始前调用注解里的方法,从而获取到一些注解里的参数
  • isValid() 就是判断是否合法的地方

使用案例

定义一个实体类

@Data
public class User { 
  // 性别只能从 man or women 里取
  @Check(paramValues = {"man", "women"}
  private String sex;
  // 年龄只能为奇数
  @Odd(message = "年龄不对")
  private Integer age;
}

在需要启用验证的地方一定要加上**@Valid**注解,这时候如果请求里的Student年龄不是奇数,就会得到一个400响应:

@RestController
public class StudentResource {
    @PostMapping("/student")
    public String addStudent(@Valid @RequestBody User user) {
        return "Student Created";
    }
}
  • 3
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
可以使用阿里巴巴的 EasyExcel 库来读取 Excel 并将其转换为实体类对象,同时还可以对字段进行校验。 以下是一个简单的示例代码: ```java // 定义实体类 public class User { @NotEmpty(message = "姓名不能为空") private String name; @NotNull(message = "年龄不能为空") @Min(value = 18, message = "年龄必须大于等于18岁") private Integer age; @Email(message = "邮箱格式不正确") private String email; // 省略 getter 和 setter 方法 } // 读取 Excel 并转换为实体类并校验字段 public List<User> readExcel(File file) throws Exception { List<User> userList = new ArrayList<>(); ExcelReader reader = EasyExcel.read(file).build(); try { Sheet sheet = reader.getSheets().get(0); // 定义读取监听器 reader.read(sheet.getSheetNo()).head(User.class).registerReadListener(new AnalysisEventListener<User>() { @Override public void invoke(User user, AnalysisContext analysisContext) { // 校验字段 Validator validator = Validation.buildDefaultValidatorFactory().getValidator(); Set<ConstraintViolation<User>> violations = validator.validate(user); if (!violations.isEmpty()) { throw new RuntimeException(violations.iterator().next().getMessage()); } userList.add(user); } @Override public void doAfterAllAnalysed(AnalysisContext analysisContext) { // 读取完成后的操作 } }).sheet().doRead(); } finally { reader.finish(); } return userList; } ``` 在上述代码中,我们首先定义了一个 `User` 实体类,并且在字段上使用了校验注解。然后使用 EasyExcel 库读取 Excel 文件,并在读取监听器中将每行数据转换为 `User` 对象,并对其进行字段校验。如果校验不通过,则直接抛出异常。最后将转换后的 `User` 对象加入到 `userList` 中并返回。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值