Spring 校验(validator,JSR-303)简单实现方式
spring 校验(validator,jsr-303)实现
什么是jsr-303规范
jsr 303是java ee 6中的一项子规范,叫做bean validation,官方参考实现是hibernate validator,此实现与hibernate orm没有任何关系。jsr 303用于对java bean中的字段的值进行验证。
与spring mvc结合
spring-mvc.xml配置:
<!--jsr-303--> <mvc:annotation-driven validator="validator"/> <bean id="validator" class="org.springframework.validation.beanvalidation.localvalidatorfactorybean"> <property name="providerclass" value="org.hibernate.validator.hibernatevalidator"/> <property name="validationmessagesource" ref="messagesource"/> </bean> <bean id="messagesource" class="org.springframework.context.support.reloadableresourcebundlemessagesource"> <property name="basename" value="validatemessage"/> <property name="usecodeasdefaultmessage" value="false"/> <property name="defaultencoding" value="utf-8"/> <property name="cacheseconds" value="60"/> </bean> <bean id="webbindinginitializer" class="org.springframework.web.bind.support.configurablewebbindinginitializer"> <property name="conversionservice"> <bean class="org.springframework.format.support.formattingconversionservicefactorybean"></bean> </property> <property name="validator" ref="validator"/> </bean>
实体类添加验证注解
这里贴出部分代码,知道如何加注解即可:
import com.lemontree.common.utils.ajaxresult; import com.lemontree.common.utils.stringutil; import com.lemontree.common.utils.email.emailutils; import org.hibernate.validator.constraints.notempty; import java.util.date; public class user { /** * this field was generated by mybatis generator. * this field corresponds to the database column user.id * * @mbg.generated thu mar 16 13:27:38 cst 2017 */ private integer id; /** * this field was generated by mybatis generator. * this field corresponds to the database column user.user_name * * @mbg.generated thu mar 16 13:27:38 cst 2017 */ @notempty(message = "用户名不能为空") private string username; /** * this field was generated by mybatis generator. * this field corresponds to the database column user.password * * @mbg.generated thu mar 16 13:27:38 cst 2017 */ @notempty(message = "密码不能为空") private string password; }
控制器验证注解添加
将@validated 注解跟在实体类前面,bindingresult紧跟其后:
@requestmapping(value = "/login.htm", method = requestmethod.post) public @responsebody ajaxresult login(@validated user user, bindingresult bindingresult, httpservletrequest request, httpservletresponse response) { if (bindingresult.haserrors()){ list<fielderror> errorses = bindingresult.getfielderrors(); if (collectionutils.isnotempty(errorses)){ errorses.foreach(item->{ system.out.println(item.getdefaultmessage()); }); } } }
java hibernate validator jsr-303验证
jsr-303是java ee 6中的一项子规范,叫做 bean validation,hibernate validator是bean validation 的参考实现。
实际使用就是通过注解来给字段添加约束,然后校验字段是否符合规范,如果不符合就会抛出异常,以此来减少校验数据的代码,并保证拿到的数据都是符合规范的,也可以和spring框架配合使用
集成
官方文档
<dependency> <groupid>org.hibernate</groupid> <artifactid>hibernate-validator</artifactid> <version>6.0.10.final</version> </dependency> <dependency> <groupid>org.glassfish</groupid> <artifactid>javax.el</artifactid> <version>3.0.1-b09</version> </dependency> <dependency> <groupid>javax.validation</groupid> <artifactid>validation-api</artifactid> <version>2.0.1.final</version> </dependency>
使用
校验对象
public class jsrtest { @notnull(message = "id不能为空!") @min(value = 1, message = "id只能大于等于1") integer id; @notnull(message = "姓名不能为空!") string name; public void validateparams() { validator validator = validation.builddefaultvalidatorfactory().getvalidator();//获取一个验证器 set<constraintviolation<jsrtest>> violationset = validator.validate(this);//验证数据,获取到错误集合 iterator<constraintviolation<jsrtest>> iterator = violationset.iterator(); if (iterator.hasnext()) { string errormessage = iterator.next().getmessage();//获取到错误信息 throw new validationexception(errormessage); } } public static void main(string args[]) { jsrtest req = new jsrtest(); req.id = 1; req.validateparams(); } }
像上面那样将在属性上添加注解即可声明约束
校验属性
上面是校验整个对象,也可以单独校验某个字段:
validator.validateproperty(object, "name");
分组校验
public class jsrtest { @notnull(message = "id不能为空!", groups = {validationgroup.class}) @min(value = 1, message = "id只能大于等于1") integer id; @notnull(message = "姓名不能为空!", groups = {validationgroup.class}) string name; @decimalmin(value = "1.1") double price; int date; public static void validateparams(jsrtest jsrtest) { validator validator = validation.builddefaultvalidatorfactory().getvalidator(); set<constraintviolation<jsrtest>> violationset = validator.validate(jsrtest, validationgroup.class); iterator<constraintviolation<jsrtest>> iterator = violationset.iterator(); if (iterator.hasnext()) { string errormessage = iterator.next().getmessage(); throw new validationexception(errormessage); } } public static void main(string args[]) { jsrtest req = new jsrtest(); validateparams(req); } public interface validationgroup { } }
分组校验所指定的calss必须是一个接口,可以指定多个
自定义约束
通常情况下,框架提供的注解已经可以满足正常的验证需求,但是我们也可以自定义注解来满足我们的需求
我们这里的例子是所注释的字符串中不能包含指定字符
@target(field) //元注解,定义该注解使用在字段上 @retention(runtime) //定义注解的生命周期 @constraint(validatedby = customvalidator.class)//指明该注解的校验器 @documented //表示该注解会被添加到javadoc中 public @interface customconstraints { string message() default "默认异常message"; class<?>[] groups() default {}; class<? extends payload>[] payload() default {}; //这个属性可以用来标注错误的严重等级,但是并不被api自身所使用 string value() default " "; }
import javax.validation.constraintvalidator; import javax.validation.constraintvalidatorcontext; /** * 需要实现constraintvalidator接口 * 泛型的第一个参数是自定义的注解,第二个参数注解所注释的字段的类型 */ public class customvalidator implements constraintvalidator<customconstraints, string> { private string value; /** * 初始化调用,拿到注解所指定的value * * @param constraintannotation */ @override public void initialize(customconstraints constraintannotation) { value = constraintannotation.value(); } /** * @param value 注释的字段的值 * @param context * @return true 通过验证,false 未通过验证 */ @override public boolean isvalid(string value, constraintvalidatorcontext context) { if (value != null && value.contains(this.value)) { context.disabledefaultconstraintviolation();//禁用默认的消息 context.buildconstraintviolationwithtemplate("新添加的错误消息").addconstraintviolation(); return false; } return true; } }
然后就可以和其他注解一样使用它了
封装
或者是将验证参数的代码提取去出来,单独写一个方法
public static void validateparams(object object) { validator validator = validation.builddefaultvalidatorfactory().getvalidator();//获取一个验证器 set<constraintviolation<object>> violationset = validator.validate(object);//验证数据,获取到错误集合 iterator<constraintviolation<object>> iterator = violationset.iterator(); if (iterator.hasnext()) { string errormessage = iterator.next().getmessage();//获取到错误信息 throw new validationexception(errormessage); } }
当然这里也可以不抛出异常,而返回一个boolean值,如何封装看实际需求
配合spring使用
@getmapping("/test") public integer lookcanbuygoods(@valid jsrtest req, bindingresult result) throws exception { if (result.haserrors()) { throw new validationexception(result.getallerrors().get(0).getdefaultmessage()); } //do something... return 1; }
@valid添加这个注解之后就会对参数进行验证,如果在其后没有跟bindingresult,验证不通过就会直接抛出异常,如果添加了bindingresult参数,就不会直接抛出异常,而会把异常信息存储在bindingresult中,供开发者自行处理
如果想要使用分组可以这样
@getmapping("/test") public integer test(@validated (jsrtest.validationgroup.class) jsrtest req, bindingresult result) throws exception { if (result.haserrors()) { throw new validationexception(result.getallerrors().get(0).getdefaultmessage()); } //do something... return 1; }
@validated如果不使用分组其作用和@valid一致
注解使用说明
constraint | 详细信息 |
---|---|
@null | 被注释的元素必须为 null |
@notnull | 被注释的元素必须不为 null |
@asserttrue | 被注释的元素必须为 true |
@assertfalse | 被注释的元素必须为 false |
@min(value) | 被注释的元素必须是一个数字,其值必须大于等于指定的最小值 |
@max(value) | 被注释的元素必须是一个数字,其值必须小于等于指定的最大值 |
@decimalmin(value) | 被注释的元素必须是一个数字,其值必须大于等于指定的最小值 |
@decimalmax(value) | 被注释的元素必须是一个数字,其值必须小于等于指定的最大值 |
@size(max, min) | 被注释的元素的大小必须在指定的范围内 |
@digits (integer, fraction) | 被注释的元素必须是一个数字,其值必须在可接受的范围内 |
@past | 被注释的元素必须是一个过去的日期 |
@pastorpresent | 被注释的元素必须是过去或现在的日期 |
@future | 被注释的元素必须是一个将来的日期 |
@futureorpresent | 被注释的元素必须是将来或现在的日期 |
@pattern(value) | 被注释的元素必须符合指定的正则表达式 |
@digits(integer =, fraction =) | 验证字符串是否是符合指定格式的数字,interger指定整数精度,fraction指定小数精度 |
验证是否是邮件地址,如果为null,不进行验证,算通过验证 | |
@notblank | 字符串不能是null还有被trim的长度要大于0 |
@notempty | 不能为null,且长度大于0 |
@negative | 被注释的元素必须是负数 |
@negativeorzero | 被注释的元素必须是负数或0 |
@positive | 必须是正数 |
@positiveorzero | 必须是正数或0 |
以上为个人经验,希望能给大家一个参考,也希望大家多多支持。
下一篇: 2020-10-02