自定义校验注解的开发

在这里插入图片描述

在业务中,会涉及到很多参数校验,通常情况下,我们会使用注解在入参中进行标注。但是一些特定的业务校验注解需要我们自定义开发。

应用场景描述

业务中入参经常有开始时间结束时间,需要保证结束时间 > 开始时间,下面Demo演示了如何自定义一个参数校验注解。

自定义注解

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Repeatable(DateValidate.List.class)
@Constraint(validatedBy = DateValidator.class)
public @interface DateValidate {

    String startDateName();
    String endDateName();
    //作为校验注解必须属性
    String message();
    //作为校验注解必须属性
    Class<?>[] groups() default {};
    //作为校验注解必须属性
    Class<? extends Payload>[] payload() default {};

    //java8新增的可重复注解
    @Target(TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    @interface List{
        DateValidate[] value();
    }

}

定义校验方法

/**
 * @Description 时间验证,依赖于Hutool工具包做时间解析,DateUtil.parse方法会自动识别一些常用格式,使用方法:在入参类上标注,可标注多个 @DateValidate(startDateName = "startTime",endDateName = "endTime",message = "开始时间不能大于结束时间")
 * @Date 2022/11/1 15:58
 * @Version 1.0
 **/

@Slf4j
public class DateValidator implements ConstraintValidator<DateValidate,Object> {

    private String startDateName;
    private String endDateName;

    @Override
    public void initialize(DateValidate constraintAnnotation) {
        this.startDateName = constraintAnnotation.startDateName();
        this.endDateName = constraintAnnotation.endDateName();

    }

    @Override
    public boolean isValid(Object object, ConstraintValidatorContext context) {
        Date startDate;
        Date endDate;
        try {
            Field fsd = object.getClass().getDeclaredField(startDateName);
            fsd.setAccessible(true);
            startDate = DateUtil.parse((String)fsd.get(object));
            Field fed=object.getClass().getDeclaredField(endDateName);
            fed.setAccessible(true);
            endDate = DateUtil.parse((String)fed.get(object));
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        //如果有时间为空放过校验,让@NotNull注解去处理
        if(startDate == null || endDate == null){
            return true;
        }
        return endDate.after(startDate);
    }


}

使用方式

入参中:

@Data
@DateValidate(startDateName = "startTime",endDateName = "endTime",message = "开始时间不能大于结束时间")
public class ListForm extends PageQuery {
    private static final long serialVersionUID = 1L;

    @ApiModelProperty(value = "开始时间")
    @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
    private String startTime;

    @ApiModelProperty(value = "结束时间")
    @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
    private String endTime;
}

Controller中:
给ListForm加入@Valid 注解

结果演示

请求结果(全局异常捕获的)

{
  "code": "110104",
  "data": {},
  "msg": "参数错误, 开始时间不能大于结束时间"
}

拓展

在业务需求中,还有很多可以自定义的校验注解,例如手机号码校验注解,防止sql注入校验注解。开发注解校验可以减少很多重复的校验代码。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
### 回答1: 以下是 Java 自定义注解包含 map 参数的代码示例: ``` import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import java.util.Map; @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface CustomAnnotation { Map<String, String> mapParam() default {}; } ``` 在这个代码示例中,我们定义了一个名为 `CustomAnnotation` 的注解,该注解包含一个名为 `mapParam` 的 map 类型的参数。注解的生命周期是 `RUNTIME`,因此该注解可以在运行时被读取,并且该注解仅可应用于方法(由 `@Target(ElementType.METHOD)` 指定)。 ### 回答2: Java中的注解是一种特殊的语法,用于提供额外的信息和元数据给编译器和运行时环境。自定义注解可以根据我们的需求创建自己的注解类型。 下面是一个示例代码,演示了如何使用自定义注解来给方法的参数添加额外的信息: ```java import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.PARAMETER) public @interface ParamInfo { String value(); // 定义注解参数 } public class MyClass { public void process(@ParamInfo("name") String name, @ParamInfo("age") int age) { // 在方法体中使用注解参数 System.out.println("Name: " + name); System.out.println("Age: " + age); } } public class Main { public static void main(String[] args) { MyClass myClass = new MyClass(); myClass.process("John Doe", 30); } } ``` 在上面的示例中,首先我们定义了一个名为`ParamInfo`的自定义注解,它被`@Retention(RetentionPolicy.RUNTIME)`和`@Target(ElementType.PARAMETER)`注解所修饰。`@Retention`注解表示这个注解在运行时仍然会保留,而`@Target`注解表示这个注解只能用于方法的参数上。 然后在`MyClass`类的`process`方法中,我们使用了`@ParamInfo`注解来修饰方法的参数。注解的参数`value`表示了这个参数的名称。在方法体中,我们可以通过反射机制获取到注解信息,并使用它们进行逻辑处理。 最后在`Main`类中的`main`方法里,我们创建了一个`MyClass`实例并调用了`process`方法,向其中传入了参数值。运行程序,就会在控制台打印出参数的值。 总结起来,通过自定义注解,我们可以为Java方法的参数提供额外的信息,从而实现更灵活的程序设计和逻辑处理。 ### 回答3: Java中的自定义注解是用来描述程序中的元数据的一种方式。自定义注解可以用来标记类、方法、字段等,并且可以附加一些元数据信息。在实际开发中,我们可以使用自定义注解来实现各种功能,例如校验参数、生成文档等。 下面是一个示例,展示如何使用自定义注解来实现对Map参数进行校验的功能: 首先,定义一个自定义注解`@MapParamValidation`,用来标记需要进行参数校验的方法。该注解包含一个属性`requiredKeys`,用来指定必需的键值对。代码如下: ```java import java.lang.annotation.*; @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface MapParamValidation { String[] requiredKeys(); } ``` 然后,在具体的方法上使用该注解,并根据注解的属性值对Map参数进行校验。如果缺少必需的键值对,则抛出异常。代码如下: ```java import java.util.*; public class MyClass { @MapParamValidation(requiredKeys = {"key1", "key2"}) public void doSomething(Map<String, Object> map) { for (String key : requiredKeys) { if (!map.containsKey(key)) { throw new IllegalArgumentException("Missing required key: " + key); } } // 执行具体的逻辑 // ... } } ``` 下面是一个测试示例,展示如何调用`doSomething`方法,并传入一个缺少必需键值对的Map参数。代码如下: ```java public class Main { public static void main(String[] args) { MyClass myClass = new MyClass(); Map<String, Object> map = new HashMap<>(); map.put("key1", "value1"); myClass.doSomething(map); // 正常调用 Map<String, Object> invalidMap = new HashMap<>(); invalidMap.put("key1", "value1"); invalidMap.put("key3", "value3"); myClass.doSomething(invalidMap); // 抛出异常:Missing required key: key2 } } ``` 通过使用自定义注解和反射,我们可以实现对Map参数进行校验的功能。这样可以减少代码的重复性,提高开发效率。同时,使用自定义注解可以使代码更加清晰、易读。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

结构化思维wz

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值