springBoot使用自定义注解实现复杂校验

2022-11-14 08:51:32 419 转载:www.kaotop.com/it/1077888.html

目录

    • 为什么使用?
    • 前置条件
    • 前置知识
      • 注解的保留策略
      • 注解的作用目标
      • 其他
    • 使用自定义注解
    • 我的实体类定义
      • 我的注解定义
      • 我的注解校验
      • 测试注解
    • 易错、注意点


为什么使用?

在业务开发中,比如开发一个用户系统,使用NotBliank,NotNull等原生注解只能校验某个参数是不是为空。在实际的service中我们可能要写很多冗余的代码量,你要写很多if else,比如邀请码是不是为空,是不是符合六位,用户昵称规范(只由数字或者只有字母组成)。这种写法当然也可以实现,但是代码量会很复杂,而且冗余。当然这些代码你可以放到utils封装成工具类方法,但是没有自定义注解来的优雅与简洁。

前置条件

springboot 2.6.x
pom依赖

1

2

3

4

5

;--;;;;;;; 注解验证器--;

;dependency;

;groupid;org.springframework.boot;/groupid;

;artifactid;spring-boot-starter-validation;/artifactid;

;/dependency;

前置知识 注解的保留策略

  1. @Retention(RetentionPolicy.SOURCE)
    只存在源码中,即运行以后这个注解就没了。
    注:一开始我也觉得这个注解没用,既然运行就没了,那我写这个有什么用。其实我们lombok的@Data注解就是这个类型的,在运行以后,Data注解生成了get、set方法以后就功成身退没有了。

  2. @Retention(RetentionPolicy.CLASS)
    在字节码中存在这个注解,运行期间没有。
    应用场景:
    依靠这种类型的注解,在运行的时候生成一些代码,类似于Data注解,不过是更上一层的使用。

  3. @Retention(RetentionPolicy.RUNTIME)、
    运行期间仍然存在,运行的时候可以通过反射去获取

注解的作用目标

格式:@Target(xxxx.xxx)
ElementType.TYPE
接口,类,枚举注解
ElementType.FIELD
字段、枚举的常量
ElementType.METHOD
方法
还有很多,我主要就用到这些

其他

@Documented注解,我理解的就是生成帮助文档javadoc
@Inherited注解,自动继承注解

使用自定义注解 我的实体类定义

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

packagecom.example.demo.dao;


importcom.example.demo.common.annotation.ArticleCheck;

importcom.fasterxml.jackson.annotation.JsonFormat;

importlombok.Data;

importorg.hibernate.annotations.CreationTimestamp;

importorg.hibernate.annotations.UpdateTimestamp;

importorg.springframework.data.elasticsearch.annotations.Document;


importjavax.persistence.Column;

importjavax.persistence.Id;

importjava.time.LocalDateTime;



@Data

@Document(indexName ="article")

@ArticleCheck

publicclassArticle {;-- --;

@Id

privateString id;


@Column(columnDefinition="varchar(32) COMMENT '连接主表的article_id'")

privateString articleId;


@Column(columnDefinition="varchar(32) COMMENT '作者用户open id'")

privateString openId;



@Column(columnDefinition="varchar(191) COMMENT '文章标题'")

privateString title;



@Column(columnDefinition="varchar(33) COMMENT '文章分类id'")

privateString categoryId;



@Column(columnDefinition="int(2) COMMENT '匿名性,匿名1,公开0'")

privateintanonymity;


@Column(columnDefinition="int(2) COMMENT '帖子状态(删除0,草稿1,发布2,隐藏3)默认草稿'")

privateintstate;


@Column(columnDefinition="longtext COMMENT '帖子内容'")

privateString content;


@CreationTimestamp

@JsonFormat(pattern ="yyyy-MM-dd HH:mm:ss")

privateLocalDateTime createdTime;


@UpdateTimestamp

@JsonFormat(pattern ="yyyy-MM-dd HH:mm:ss")

privateLocalDateTime updatedTime;



@JsonFormat(pattern ="yyyy-MM-dd HH:mm:ss")

privateLocalDateTime deletedTime;

}

我的注解定义

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

packagecom.example.demo.common.annotation;


importcom.example.demo.common.annotation.validator.ArticleCheckValidator;

importcom.example.demo.dao.Article;


importjavax.validation.Constraint;

importjava.lang.annotation.*;



@Target({;-- --; ElementType.TYPE, ElementType.PARAMETER })

@Retention(RetentionPolicy.RUNTIME)

@Documented

@Constraint(validatedBy= ArticleCheckValidator.class)

public@interfaceArticleCheck {;-- --;

// 注解未通过,打印message信息

String message()default"article invalid";


Class;--?--;[] groups()default{;-- --; };


Class;--?extendsArticle--;[] payload()default{;-- --; };

}

我的注解校验

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

packagecom.example.demo.common.annotation.validator;


importcom.example.demo.common.annotation.ArticleCheck;

importcom.example.demo.dao.Article;


importjavax.validation.ConstraintValidator;

importjavax.validation.ConstraintValidatorContext;

importjava.lang.annotation.Annotation;



publicclassArticleCheckValidatorimplementsConstraintValidator;articlecheck, article=""; {;-- --;

@Override

publicvoidinitialize(ArticleCheck constraintAnnotation) {;-- --;

ConstraintValidator.super.initialize(constraintAnnotation);

}

//


@Override

publicbooleanisValid(Article article, ConstraintValidatorContext constraintValidatorContext) {;-- --;

if(article.getArticleId()=="123"){;-- --;

returntrue;

}

returnfalse;

}

}


;/articlecheck,;

测试注解

这是controller层的代码

1

2

3

4

5

@PostMapping("/test")

publicResult testArticle(@RequestBody@ValidatedArticle article){;-- --;

System.out.println(article);

returnResult.ok(article.toString());

}

易错、注意点

  1. 在controller层里面要是怕post方法,要加上@RequestBody。
  2. 你要想让你的类执行校验还有加上@Validated,只有有这个注解,类中的自定义注解才可以生效。
*特别说明:本文来自网络,如有侵权,请联系我们删除,非常感谢!