自定义注解使用

现象:

自定义注解使用

方法:

1:元注解
java.lang.annotation 下定义了元注解

  • @Documented 文档相关 标注了此注解则会包含在javadoc文档中
  • @Retention 指定注解生命周期
  • @Target 指定注解作用范围
  • @Inherited 指定子类可以继承父类的注解
  • @Native 指定字段是常量
  • @Repeatable 指定在一个地方可以重复使用同一个注解

2:元注解 @Retention 生命周期

  • SOURCE: 只保留在源文件
  • CLASS: 保留到class文件
  • RUNTIME: 运行时也存在

3:元注解 @Target 作用范围

  • TYPE——接口、类、枚举、注解
  • FIELD——字段、枚举的常量
  • METHOD——方法
  • PARAMETER——方法参数
  • CONSTRUCTOR ——构造函数
  • LOCAL_VARIABLE——局部变量
  • ANNOTATION_TYPE——注解
  • PACKAGE——包,用于记录java文件的package信息

4:新建java类选择注解@Annitation

自定义注解使用_第1张图片

5:示例建立MyAnnitation注解

自定义注解使用_第2张图片
6:使用:
自定义注解使用_第3张图片

二:实例使用:

需求:自定义注解校验请求参数只能是指定值
比如 请求接口 type 参数 只能是"1"、“2”、“3”

方法:
1:引入validation校验jar包

   
           org.springframework.boot
           spring-boot-starter-validation
   

2:建立自定义注解
自定义注解范围 :字段、枚举的常量、方法参数
使用@Constraint 指定校验逻辑的类

@Target({ElementType.PARAMETER,ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Constraint(validatedBy = EnumRangeValidator.class)
public @interface CheckEnum {
	
	// 校验能输入的值
    String[] rang();
    
	// 错误提示
    String message() default "输入的内容不在规定范围";

    // 名称固定参数:校验分组信息
    Class[] groups() default {};
    
    // 名称固定参数:加载的负载
    Class[] payload() default {};

}

3:建立校验逻辑的类EnumRangeValidator


public class EnumRangeValidator implements ConstraintValidator {

    private String[] range;

    @Override
    public void initialize(CheckEnum constraintAnnotation) {
        // 初始化将注解中的枚举内容放数组range
        range=constraintAnnotation.rang();
    }

    @Override
    public boolean isValid(String request, ConstraintValidatorContext constraintValidatorContext) {

        // 判断输入的值在不在 注解设置的范围
        if(StringUtils.isNotBlank(request)){
            if(range!=null && range.length>0){
                return Arrays.asList(range).contains(request);
            }
        }

        return false;
    }
}

4:全局异常监听控制返回
这里简单返回String 实际开发中应该定义全局返回对象

@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {

    @ResponseBody
    @ResponseStatus(HttpStatus.OK)
    @ExceptionHandler({MethodArgumentNotValidException.class})
    private String argumentsNotValid(MethodArgumentNotValidException e) {
        try {
            var fieldError = e.getBindingResult().getFieldError();
            var defaultMessage = fieldError.getDefaultMessage();
            log.error("参数校验不通过 ", e);
            return defaultMessage;
        } catch (NullPointerException exception) {
            log.error("fieldError 为空", e);
            return "参数异常";
        }
    }

    @ResponseBody
    @ResponseStatus(HttpStatus.OK)
    @ExceptionHandler(ConstraintViolationException.class)
    private String multiArgumentNotValid(ConstraintViolationException e) {
        var constraintViolations = e.getConstraintViolations();
        var reduce =
                constraintViolations.stream()
                        .map(ConstraintViolation::getMessage)
                        .reduce((x, y) -> x + " " + y)
                        .orElse("");
        log.error("参数校验不通过 ", e);
        return reduce;
    }
}

5:请求入参对象EnumValidRequest

@Data
@NoArgsConstructor
@AllArgsConstructor
public class EnumValidRequest {

    /**
     * @NotBlank 不能为空校验
     */
    @NotBlank(message = "id不能为空!")
    private String id;
    private String name;

    /**
     * 设置类型  值只能是1、2、3
     * 使用自定义枚举校验 类型只能传值1、2、3
     */
    @CheckEnum(rang = {"1","2","3"})
    private String type;
}

6:请求接口test/check/enum
使用定义的EnumValidRequest 作为参数

@Slf4j
@RestController
@RequestMapping("/test")
@Validated
public class RequestController {

    @PostMapping("/check/enum")
    public String getA(@Valid @RequestBody EnumValidRequest request){
        log.debug("a请求执行:{}",request);
        return "A";
    }

}

7:启动项目 访问接口test/check/enum

  • 输入的type不在范围时返回:
    自定义注解使用_第4张图片
  • 不传id时返回:
    自定义注解使用_第5张图片
  • 正常参数访问返回:
    自定义注解使用_第6张图片

你可能感兴趣的:(java,java,spring)