Java注解简介:

Java注解又称Java标注,是JDK5.0版本开始支持加入源代码的特殊语法元数据。

Java语言中的类、方法、变量、参数和包等都可以被标注。和Javadoc不同,Java标注可以通过反射获取标注内容。在编译器生成类文件时,标注可以被嵌入到字节码中。Java虚拟机可以保留标注内容,在运行时可以获取到标注内容。 当然它也支持自定义Java标注。

java元注解所在包java.lang.annotation,下面有很多元注解【如下图】:

43180f74d65429d60308429ef492d570.png

元注解

jakarta-validation和hibernate-validation为我们提供了很多拿来即用的校验注解

引入springboot相关pom坐标就会自动给我们引入对应的jakarta-validation和hibernate-validation包

2dd3c4c0c2695fc2aaa134e53a272a3f.png

Jakarta-validation

709d50e1fd4af1c8241423e7e003adf3.png

hibernate-validation

jakarta-validation和hibernate-validation中常用注解说明:

javax.validation.constraints.AssertFalse.message     = 只能为falsejavax.validation.constraints.AssertTrue.message      = 只能为truejavax.validation.constraints.DecimalMax.message      = 必须小于或等于{value}javax.validation.constraints.DecimalMin.message      = 必须大于或等于{value}javax.validation.constraints.Digits.message          = 数字的值超出了允许范围(只允许在{integer}位整数和{fraction}位小数范围内)javax.validation.constraints.Email.message           = 不是一个合法的电子邮件地址javax.validation.constraints.Future.message          = 需要是一个将来的时间javax.validation.constraints.FutureOrPresent.message = 需要是一个将来或现在的时间javax.validation.constraints.Max.message             = 最大不能超过{value}javax.validation.constraints.Min.message             = 最小不能小于{value}javax.validation.constraints.Negative.message        = 必须是负数javax.validation.constraints.NegativeOrZero.message  = 必须是负数或零javax.validation.constraints.NotBlank.message        = 不能为空javax.validation.constraints.NotEmpty.message        = 不能为空javax.validation.constraints.NotNull.message         = 不能为nulljavax.validation.constraints.Null.message            = 必须为nulljavax.validation.constraints.Past.message            = 需要是一个过去的时间javax.validation.constraints.PastOrPresent.message   = 需要是一个过去或现在的时间javax.validation.constraints.Pattern.message         = 需要匹配正则表达式"{regexp}"javax.validation.constraints.Positive.message        = 必须是正数javax.validation.constraints.PositiveOrZero.message  = 必须是正数或零javax.validation.constraints.Size.message            = 个数必须在{min}和{max}之间org.hibernate.validator.constraints.CreditCardNumber.message        = 不合法的信用卡号码org.hibernate.validator.constraints.Currency.message                = 不合法的货币 (必须是{value}其中之一)org.hibernate.validator.constraints.EAN.message                     = 不合法的{type}条形码org.hibernate.validator.constraints.Email.message                   = 不是一个合法的电子邮件地址org.hibernate.validator.constraints.Length.message                  = 长度需要在{min}和{max}之间org.hibernate.validator.constraints.CodePointLength.message         = 长度需要在{min}和{max}之间org.hibernate.validator.constraints.LuhnCheck.message               = ${validatedValue}的校验码不合法, Luhn模10校验和不匹配org.hibernate.validator.constraints.Mod10Check.message              = ${validatedValue}的校验码不合法, 模10校验和不匹配org.hibernate.validator.constraints.Mod11Check.message              = ${validatedValue}的校验码不合法, 模11校验和不匹配org.hibernate.validator.constraints.ModCheck.message                = ${validatedValue}的校验码不合法, ${modType}校验和不匹配org.hibernate.validator.constraints.NotBlank.message                = 不能为空org.hibernate.validator.constraints.NotEmpty.message                = 不能为空org.hibernate.validator.constraints.ParametersScriptAssert.message  = 执行脚本表达式"{script}"没有返回期望结果org.hibernate.validator.constraints.Range.message                   = 需要在{min}和{max}之间org.hibernate.validator.constraints.SafeHtml.message                = 可能有不安全的HTML内容org.hibernate.validator.constraints.ScriptAssert.message            = 执行脚本表达式"{script}"没有返回期望结果org.hibernate.validator.constraints.URL.message                     = 需要是一个合法的URLorg.hibernate.validator.constraints.time.DurationMax.message        = 必须小于${inclusive == true ? '或等于' : ''}${days == 0 ? '' : days += '天'}${hours == 0 ? '' : hours += '小时'}${minutes == 0 ? '' : minutes += '分钟'}${seconds == 0 ? '' : seconds += '秒'}${millis == 0 ? '' : millis += '毫秒'}${nanos == 0 ? '' : nanos += '纳秒'}org.hibernate.validator.constraints.time.DurationMin.message        = 必须大于${inclusive == true ? '或等于' : ''}${days == 0 ? '' : days += '天'}${hours == 0 ? '' : hours += '小时'}${minutes == 0 ? '' : minutes += '分钟'}${seconds == 0 ? '' : seconds += '秒'}${millis == 0 ? '' : millis += '毫秒'}${nanos == 0 ? '' : nanos += '纳秒'}

重点:自定义注解校验

当官方提供的注解不够满足不了我们实际开发需求时,我们就可以自己定义符合自己业务逻辑的注解。

下面我们来自定义一个校验集合内容的注解,要求:只允许输入注解传递的值

1)创建ListValue.java注解类

@Documented@Constraint(validatedBy = { ListValueConstraintValidator.class})@Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE })@Retention(RetentionPolicy.RUNTIME)public @interface ListValue {    String message() default "{com.bigdata.common.valid.ListValue.message}";    Class>[] groups() default {};    Class extends Payload>[] payload() default { };    int[] value() default {};}

ListValueConstraintValidator.class是我们的校验器,用于书写我们校验的业务逻辑

2)创建ListValueConstraintValidator.java校验器类

public class ListValueConstraintValidator implements ConstraintValidator {    private Set set=new HashSet<>();    @Override    public void initialize(ListValue constraintAnnotation) {        int[] value = constraintAnnotation.value();        for (int i : value) {            set.add(i);        }    }    @Override    public boolean isValid(Integer value, ConstraintValidatorContext context) {        return  set.contains(value);    }}

3)统一异常处理类,用于处理参数校验异常

@Slf4j@RestControllerAdvice(basePackages = "com.bigcat.gulimall.gulimallproduct.controller" )public class ExceptionAdvice {    /**     * 未知异常     * @param throwable     * @return     */    @ExceptionHandler(value = Throwable.class)    public R handleException(Throwable throwable){        log.error("未知异常{},异常类型{}",throwable.getMessage(),throwable.getClass());        return R.error(1000,"未知异常");    }    /**     * 数据校验异常     * @param exception     * @return     */    @ExceptionHandler(value = MethodArgumentNotValidException.class)    public R handleValidException(MethodArgumentNotValidException exception){        Map map=new HashMap<>();        BindingResult bindingResult = exception.getBindingResult();        bindingResult.getFieldErrors().forEach(fieldError -> {            String message = fieldError.getDefaultMessage();            String field = fieldError.getField();            map.put(field,message);        });        log.error("数据校验出现问题{},异常类型{}",exception.getMessage(),exception.getClass());        return R.error(1234,"参数校验异常").put("data",map);    }}

4)使用我们自定义的注解来校验我们我们需要校验的字段showStatus,顺便使用一下Jakarta-validation里的注解

@Data@TableName()public class BrandEntity implements Serializable {   private static final long serialVersionUID = 1L;   /**    * 品牌id    */   @TableId   @NotNull(message = "不能为null",groups = {UpdateGroup.class})   private Long brandId;   /**    * 品牌名    */   @NotBlank(message = "品牌名必须非空",groups = {AddGroup.class})   private String name;   /**    * 品牌logo地址    */   @NotBlank(message = "logo不能为空",groups = {AddGroup.class})   @URL(message = "logo必须为一个合法的url")   private String logo;   /**    * 介绍    */   private String descript;   /**    * 显示状态[0-不显示;1-显示]    */   @NotNull(message = "显示状态不能为Null",groups = {AddGroup.class})// @Min(value = 0,message = "必须为0或者1",groups = {AddGroup.class,UpdateGroup.class})// @Max(value = 1,message = "必须为0或者1",groups = {AddGroup.class,UpdateGroup.class})   @ListValue(value = {0,1},message = "必须为0或者1",groups = {AddGroup.class,UpdateGroup.class})   private Integer showStatus;   /**    * 检索首字母    */   @NotBlank(message = "检索首字母不能为空",groups = {AddGroup.class})   @Pattern(regexp = "^[A-Za-z]{1}+$",message = "检索首字母必须为一个字母",groups = {AddGroup.class,UpdateGroup.class})   private String firstLetter;   /**    * 排序    */   @NotNull(message = "不能为空",groups = {AddGroup.class})   @Min(value = 0)   private Integer sort;}

5)在接口中java注解@Validated,不然不会生效

@RequestMapping("/save")  public R save(@Validated(value = AddGroup.class) @RequestBody BrandEntity brand){brandService.save(brand);      return R.ok();  }

6)测试

61df54759b1ec1a941ca8353b6b15adc.png
Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐