前言
最近为了工作也为了更加深入了解掌握java注解的使用,决定 自定义注解 来实现 数据验证 。
api开发中经常会遇到一些对请求数据进行验证的情况,这时候如果使用注解就有两个好处,一是验证逻辑和业务逻辑分离,代码清晰,二是验证逻辑可以轻松复用,只需要在要验证的地方加上注解就可以。
java提供了一些基本的验证注解,比如@notnull、@size,但是更多情况下需要自定义验证逻辑,这时候就可以自己实现一个验证注解,方法很简单,仅需要两个东西:
一个自定义的注解,并且指定验证器 一个验证器的实现自定义验证注解
考虑有一个api,接收一个student对象,并希望对象里的age域的值是奇数,这时候就可以创建以下注解:
1 2 3 4 5 6 7 8 |
@target (elementtype.field) @retention (retentionpolicy.runtime) @constraint (validatedby = agevalidator. class ) public @interface odd { string message() default "age must be odd" ; class <?>[] groups() default {}; class <? extends payload>[] payload() default {}; } |
其中:
@target指明这个注解要作用在什么地方,可以是对象、域、构造器等,因为要作用在age域上,因此这里选择field @retention指明了注解的生命周期,可以有source(仅保存在源码中,会被编译器丢弃),class(在class文件中可用,会被vm丢弃)以及runtime(在运行期也被保留),这里选择了生命周期最长的runtime @constraint是最关键的,它表示这个注解是一个验证注解,并且指定了一个实现验证逻辑的验证器 message()指明了验证失败后返回的消息,此方法为@constraint要求 groups()和payload()也为@constraint要求,可默认为空,详细用途可以查看@constraint文档创建验证器
有了注解之后,就需要一个验证器来实现验证逻辑:
1 2 3 4 5 6 7 8 9 10 |
public class agevalidator implements constraintvalidator<odd,integer> { @override public void initialize(odd constraintannotation) { }
@override public boolean isvalid(integer age, constraintvalidatorcontext constraintvalidatorcontext) { return age % 2 != 0 ; } } |
其中:
验证器有两个类型参数,第一个是所属的注解,第二个是注解作用地方的类型,这里因为作用在age上,因此这里用了integer initialize()可以在验证开始前调用注解里的方法,从而获取到一些注解里的参数,这里用不到 isvalid()就是判断是否合法的地方应用注解
注解和验证器创建好之后,就可以使用注解了:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
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; } } |
1 2 3 4 5 6 7 |
@restcontroller public class studentresource { @postmapping ( "/student" ) public string addstudent( @valid @requestbody student student) { return "student created" ; } } |
在需要启用验证的地方加上@valid注解,这时候如果请求里的student年龄不是奇数,就会得到一个400响应:
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 |
{ "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来接收验证结果即可:
1 2 3 4 5 6 7 8 9 10 |
@restcontroller public 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
查看更多关于JAVA中通过自定义注解进行数据验证的方法的详细内容...