博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
JAVA里自定义注解来进行数据验证
阅读量:7024 次
发布时间:2019-06-28

本文共 3228 字,大约阅读时间需要 10 分钟。

API开发中经常会遇到一些对请求数据进行验证的情况,这时候如果使用注解就有两个好处,一是验证逻辑和业务逻辑分离,代码清晰,二是验证逻辑可以轻松复用,只需要在要验证的地方加上注解就可以。

Java提供了一些基本的验证注解,比如@NotNull@Size,但是更多情况下需要自定义验证逻辑,这时候就可以自己实现一个验证注解,方法很简单,仅需要两个东西:

  • 一个自定义的注解,并且指定验证器
  • 一个验证器的实现

自定义验证注解

考虑有一个API,接收一个Student对象,并希望对象里的age域的值是奇数,这时候就可以创建以下注解:

@Target(ElementType.FIELD)@Retention(RetentionPolicy.RUNTIME)@Constraint(validatedBy = AgeValidator.class)public @interface Odd {    String message() default "Age Must Be Odd";    Class
[] groups() default {}; Class
[] payload() default {};}

其中:

  • @Target指明这个注解要作用在什么地方,可以是对象、域、构造器等,因为要作用在age域上,因此这里选择FIELD
  • @Retention指明了注解的生命周期,可以有SOURCE(仅保存在源码中,会被编译器丢弃),CLASS(在class文件中可用,会被VM丢弃)以及RUNTIME(在运行期也被保留),这里选择了生命周期最长的RUNTIME
  • @Constraint是最关键的,它表示这个注解是一个验证注解,并且指定了一个实现验证逻辑的验证器
  • message()指明了验证失败后返回的消息,此方法为@Constraint要求
  • groups()payload()也为@Constraint要求,可默认为空,详细用途可以查看@Constraint文档

创建验证器

有了注解之后,就需要一个验证器来实现验证逻辑:

public class AgeValidator implements ConstraintValidator
{ @Override public void initialize(Odd constraintAnnotation) { } @Override public boolean isValid(Integer age, ConstraintValidatorContext constraintValidatorContext) { return age % 2 != 0; }}

其中:

  • 验证器有两个类型参数,第一个是所属的注解,第二个是注解作用地方的类型,这里因为作用在age上,因此这里用了Integer
  • initialize()可以在验证开始前调用注解里的方法,从而获取到一些注解里的参数,这里用不到
  • isValid()就是判断是否合法的地方

应用注解

注解和验证器创建好之后,就可以使用注解了:

public class Student {    @Odd    private int age;    private String name;    public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }    public int getAge() {        return age;    }    public void setAge(int age) {        this.age = age;    }}
@RestControllerpublic class StudentResource {    @PostMapping("/student")    public String addStudent(@Valid @RequestBody Student student) {        return "Student Created";    }}

在需要启用验证的地方加上@Valid注解,这时候如果请求里的Student年龄不是奇数,就会得到一个400响应:

{    "timestamp": "2018-08-15T17:01:44.598+0000",    "status": 400,    "error": "Bad Request",    "errors": [        {            "codes": [                "Odd.student.age",                "Odd.age",                "Odd.int",                "Odd"            ],            "arguments": [                {                    "codes": [                        "student.age",                        "age"                    ],                    "arguments": null,                    "defaultMessage": "age",                    "code": "age"                }            ],            "defaultMessage": "Age Must Be Odd",            "objectName": "student",            "field": "age",            "rejectedValue": 12,            "bindingFailure": false,            "code": "Odd"        }    ],    "message": "Validation failed for object='student'. Error count: 1",    "path": "/student"}

也可以手动来处理错误,加上一个BindingResult来接收验证结果即可:

@RestControllerpublic class StudentResource {    @PostMapping("/student")    public String addStudent(@Valid @RequestBody Student student, BindingResult validateResult) {        if (validateResult.hasErrors()) {            return validateResult.getAllErrors().get(0).getDefaultMessage();        }        return "Student Created";    }}

这时候如果验证出错,便只会返回一个状态为200,内容为Age Must Be Odd的响应。

转载于:https://www.cnblogs.com/xz816111/p/9484902.html

你可能感兴趣的文章
webpack-dev-server的刷新模式inline和iframe详解
查看>>
滴滴开源基于 RocketMQ 的分布式消息队列 DDMQ
查看>>
云服务器ecs企业版快速入门概述
查看>>
洛谷 P1854 花店橱窗布置
查看>>
晓羊教育获新东方、华创资本领投近1.5亿元人民币B轮融资 打造基础教育信息化大数据新生态 ...
查看>>
史上最详细阿里云服务器搭建及域名申请攻略
查看>>
阿里云表格存储TableStore全新升级 打造统一在线数据存储平台 ...
查看>>
「镁客·请讲」中芯芯片陈智维:国内芯片没有创新可言,但大家做的是从无到有 ...
查看>>
【直播预告】阿里技术专家天樵:基于JVM的脚本语言开发、运用实践
查看>>
第二十章:异步和文件I/O.(十八)
查看>>
win10应用程序添加到开机启动项的两种解决办法
查看>>
一招教你无阻塞读写Golang channel
查看>>
阿里有群姑娘,是马老师的师兄,还是逍遥子的学长……
查看>>
Docker 在 Coding WebIDE 项目中的运用
查看>>
ATtiny85 制作迷你小游戏机
查看>>
jQuery限制“Text-Area”域中的字符的个数
查看>>
bboss框架配置监控介绍
查看>>
Fastify 2.0.1 和 1.14.3 发布,极速 Node.js Web 框架
查看>>
和平之翼代码生成器SMEU版 4.0.0 Beta5 宝船公布
查看>>
Android--进程间通信(Binder)
查看>>