在业务开发中,比如开发一个用户系统,使用NotBliank,NotNull等原生注解只能校验某个参数是不是为空。在实际的service中我们可能要写很多冗余的代码量,你要写很多if else,比如邀请码是不是为空,是不是符合六位,用户昵称规范(只由数字或者只有字母组成)。这种写法当然也可以实现,但是代码量会很复杂,而且冗余。当然这些代码你可以放到utils封装成工具类方法,但是没有自定义注解来的优雅与简洁。
前置条件springboot 2.6.x
pom依赖
前置知识 注解的保留策略org.springframework.boot spring-boot-starter-validation
@Retention(RetentionPolicy.SOURCE)
只存在源码中,即运行以后这个注解就没了。
注:一开始我也觉得这个注解没用,既然运行就没了,那我写这个有什么用。其实我们lombok的@Data注解就是这个类型的,在运行以后,Data注解生成了get、set方法以后就功成身退没有了。
@Retention(RetentionPolicy.CLASS)
在字节码中存在这个注解,运行期间没有。
应用场景:
依靠这种类型的注解,在运行的时候生成一些代码,类似于Data注解,不过是更上一层的使用。
@Retention(RetentionPolicy.RUNTIME)、
运行期间仍然存在,运行的时候可以通过反射去获取
格式:@Target(xxxx.xxx)
ElementType.TYPE
接口,类,枚举注解
ElementType.FIELD
字段、枚举的常量
ElementType.METHOD
方法
还有很多,我主要就用到这些
@Documented注解,我理解的就是生成帮助文档javadoc
@Inherited注解,自动继承注解
package com.example.demo.dao; import com.example.demo.common.annotation.ArticleCheck; import com.fasterxml.jackson.annotation.JsonFormat; import lombok.Data; import org.hibernate.annotations.CreationTimestamp; import org.hibernate.annotations.UpdateTimestamp; import org.springframework.data.elasticsearch.annotations.Document; import javax.persistence.Column; import javax.persistence.Id; import java.time.LocalDateTime; @Data @Document(indexName = "article") @ArticleCheck public class Article { @Id private String id; @Column(columnDefinition="varchar(32) COMMENT '连接主表的article_id'") private String articleId; @Column(columnDefinition="varchar(32) COMMENT '作者用户open id'") private String openId; @Column(columnDefinition="varchar(191) COMMENT '文章标题'") private String title; @Column(columnDefinition="varchar(33) COMMENT '文章分类id'") private String categoryId; @Column(columnDefinition="int(2) COMMENT '匿名性,匿名1,公开0'") private int anonymity; @Column(columnDefinition="int(2) COMMENT '帖子状态(删除0,草稿1,发布2,隐藏3)默认草稿'") private int state; @Column(columnDefinition="longtext COMMENT '帖子内容'") private String content; @CreationTimestamp @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") private LocalDateTime createdTime; @UpdateTimestamp @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") private LocalDateTime updatedTime; @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") private LocalDateTime deletedTime; }我的注解定义
package com.example.demo.common.annotation; import com.example.demo.common.annotation.validator.ArticleCheckValidator; import com.example.demo.dao.Article; import javax.validation.Constraint; import java.lang.annotation.*; @Target({ ElementType.TYPE, ElementType.PARAMETER }) @Retention(RetentionPolicy.RUNTIME) @Documented @Constraint(validatedBy= ArticleCheckValidator.class) public @interface ArticleCheck { // 注解未通过,打印message信息 String message() default "article invalid"; Class>[] groups() default { }; Class extends Article>[] payload() default { }; }我的注解校验
package com.example.demo.common.annotation.validator; import com.example.demo.common.annotation.ArticleCheck; import com.example.demo.dao.Article; import javax.validation.ConstraintValidator; import javax.validation.ConstraintValidatorContext; import java.lang.annotation.Annotation; public class ArticleCheckValidator implements ConstraintValidator测试注解{ @Override public void initialize(ArticleCheck constraintAnnotation) { ConstraintValidator.super.initialize(constraintAnnotation); } // @Override public boolean isValid(Article article, ConstraintValidatorContext constraintValidatorContext) { if (article.getArticleId()=="123"){ return true; } return false; } }
这是controller层的代码
@PostMapping("/test") public Result testArticle(@RequestBody @Validated Article article){ System.out.println(article); return Result.ok(article.toString()); }易错、注意点