@valid和@validated@valid和@validated比较相同点:
@valid注解和 @validated注解都是开启校验功能的注解
不同点:
@valid注解 : 可以使用在方法,构造函数,方法参数和成员属性上
@validated注解 : 可以用在类型,方法和方法参数上. 但是不能用在成员属性上
@validated注解是spring基于 @valid注解的进一步封装,并提供比如分组,分组顺序的高级功能
使用位置不同:
@valid高级使用@valid级联校验级联校验: 也叫嵌套检测.嵌套就是一个实体类包含另一个实体类
@valid和可以用在成员属性的字段上,因此 @valid可以提供级联校验
示例:
@datapublic class hair { @notblank(message = "头发长度必须提交!") private double length; @notblank(message = "头发颜色必须提交!") private string color;}@datapublic class person { @notblank(message = "用户姓名必须提交!") @size(min=2, max=8) private string username; // 添加@valid注解实现嵌套检测 @valid @notempty(message = "用户要有头发!") private list<hair> hairs;} @postmapping("/person")public result addperson(@valid @requestbody person person) { return result.buildsuccess(person);}
只是在方法参数前面添加 @valid和 @validated注解,不会对嵌套的实体类进行校验.要想实现对嵌套的实体类进行校验,需要在嵌套的实体类属性上添加 @valid注解
@validated高级使用@validated分组校验分组校验:
对指定的组开启校验,可以分别作用于不同的业务场景中
分组校验是由 @validated注解中的value提供的
groups:
@datapublic class persongroup { public interface addgroup {} public interface updategroup {} // @validated注解value方法指定分组updategroup.class时校验 @notblank(message = "用户id必须提交!", groups = updategroup.class) private string id; // @validated注解value方法指定分组addgroup.class或者分组updategroup.class时校验 @notblank(message = "用户的姓名必须提交!", groups = {addgroup.class, updategroup.class}) private string name; // @validated注解value方法未指定分组时校验 @range(min = 1, max = 200, message = "用户的年龄必须提交!") private int age;}
jsr 303校验注解中的分组方法groups
示例:
开启分组校验: 通过 @validated注解的value方法对指定的分组开启校验
@restcontroller@requestmapping("/person")public class persongroupcontroller { // 不指定分组时校验 @getmapping("/person") public result getperson(@validated @requestbody persongroup person) { return result.buildsuccess(person); } // 指定addgroup分组校验 @postmapping("/person") public result addperson(@validated(value = persongroup.addgroup.class) @requestbody persongroup person) { return result.buildsuccess(person); } // 指定updategroup分组校验 @putmapping("/person") public result updateperson(@validated(value = persongroup.updategroup.class) @requestbody persongroup person) { return result.buildsuccess(person); }}
校验方法添加groups的值来指定分组,只有使用 @validated注解的value的值指定这个分组时,开会开启注解的校验数据的功能
@validated分组校验顺序默认情况下,分组间的约束是无序的,但是在一些特殊的情况下可能对分组间的校验有一定的顺序
比如第二组的分组的约束的校验需要依赖第一组的稳定状态来进行,此时,要求分组间的约束校验一定要有顺序
分组校验顺序通过使用 @groupsequence注解实现
示例:
@datapublic class usergroupsequence { public interface firstgroup {} public interface secondgroup {} // 使用groupsequence定义分组校验顺序:按照firstgroup,secondgroup分组顺序进行校验 @groupsequence({firstgroup.class, secondgroup.class}) public interface group {} @notempty(message = "用户id必须提交!", group = firstgroup.class) private string userid; @notempty(message = "用户姓名必须提交!", group = firstgroup.class) @size(min = 2, max = 8, message = "用户姓名的长度在2~8之间", goup = second.class) private string username;}
@restcontroller@requestmapping("/user")public class usergroupsequencecontroller { // 这里方法中@validated注解value的值是group.class @postmapping("/user") public result addgroup(@validated(value = group.class) @requestbody usergroupsequence user) { return result.buildsuccess(user); }}
使用 @groupsequence注解指定分组校验顺序后,第一组分组的约束的校验没有通过后,就不会进行第二组分组的约束的校验
@validated非实体类校验在非实体类上添加 @validated注解对非实体类进行校验
@validatedpublic class annotationcontroller { @getmapping("/person") public result getage(@range(min = 2, max = 8, message = "年龄在3~8岁!") @requestparam int age) { return result.buildsuccess(age); }}
在globalexceptionhandler中添加全局统一异常处理方法:
@exceptionhandler(constraintviolationexception.class)@responsebodypublic result resolveconstraintviolationexception(constraintvilationexception exception) { set<constraintvilation<?>> constraintvilations = exception.getconstraintvilations(); // 处理异常信息 if (!collectionutils.isempty(constraintvilations)) { stringbuilder messagebuilder = new stringbuilder(); for (constraintvilation constraintviolation : constraintvilations) { messagebuilder.append(constraintvilation.getmessage()).append(","); } string errormessage = messagebuilder.tostring(); if (errormessage.length() > 1) { errormessage.substring(0, errormessage.length() - 1); } return result.builderfailure(errorstatus.illegal_data.getcode(), errormessage); } return result.builderfailure(errorstatus.illegal_data.getcode(), exception.getmessage())}
@pathvariable@pathvariable的作用: 用来指定请求url路径里面的变量
@pathvariable和 @requestparam的区别:
@pathvariable用来指定请求url中的变量
@requestparam用来获取静态的url请求入参
正则表达式校验使用正则表达式校验 @pathvariable指定的路径变量
// 请求路径中的id必须是数字,否则寻找不到这个路径404@getmapping("/user/{id:\\d+}")public result getid(@pathvariable(name="id") string userid) { return result.buildsuccess(userid);}
继承basicerrorcontroller类@controlleradvice注解只能处理进入控制器方法抛出的异常
basicerrorcontroller接口可以处理全局异常
@pathvariable路径校验异常不是控制器方法抛出的,此时还没有进入控制器方法:
basicerrorcontroller处理异常,比如404异常时,会跳转到 /error路径,此时会返回错误的html页面
为了保证返回结果统一,继承basicerrorcontroller类,重写basicerrorcontroller接口中的错误处理方法
@restcontrollerpublic class patherrorcontroller extends basicerrorcontroller { @autowired public patherrorcontroller(errorattributes errorattributes, serverproperties serverproperties, list<errorviewresolver> errorviewresolvers) { super(errorattributes, serverproperties.geterror(), errorviewresolvers); } /** * 处理html请求 */ @override public modelandview errorhtml(httpservletrequest request, httpservletresponse response) { httpstatus status = getstatus(request); map<string, object> model = geterrorattributes(request, isincludestacktrace(request, mediatype.text_html)); modelandview modelandview = new modelandview("patherrorpage", model, status); return modelandview; } /** * 处理json请求 */ @override public responseentity<map<string, object>> error(httpservletrequest request) { map<string, object> body = geterrorattributes(request, isincludestacktrace(request, mediatype.all)); map<string, object> responsebody = new hashmap<>(8); responsebody.put("success", false); responsebody.put("code", body.get("status")); responsebody.put("message", body.get("error")); return new responseentity<>(responsebody, httpstatus.ok); }}
自定义校验注解使用场景:
对某一个只能输入指定值的字段进行校验. 此时需要使用自定义注解实现
定义自定义的注解 @show :
@documented@constraint(validateby = {show.showconstraintvalidator.class})@target({elementtype.method, elementtype.field, elementtype.annotation_type})@rentation(runtime)public @interface show { string message() default "{com.oxford.annotation.show.message}"; class<?>[] groups() default {}; class<? extends payload>[] payload() default {}; int[] value(); class showconstraintvalidator implements constraintvalidator<show, integer> { private set<integer> set = new hashset<>(); /** * 初始化操作 * 获取value属性指定的数字,保存到set集合中 */ @override public void initilize(show constraintannotation) { int[] value = constraintannotation.value(); for (int v : value) { set.add(i); } } @override public boolean isvalid(integer value, constraintvalidatorcontext context) { return set.contains(value); } } }
注意点:
实现自定义的校验逻辑
返回boolean类型的校验结果
获取到自定义注解中的相关的数据
接口中第一个泛型参数表示的是自定义注解类
接口中第二个泛型参数表示的是校验的属性的值的类型
将自定义的注解和实现的校验类联系起来
@constraint注解:
自定义校验注解类需要实现constraintvalidator<a extends annotation, t> 接口
initialize() 方法:
isvalid() 方法:
自定义注解的使用:
@datapublic class annotationquery { @show(value = {0, 1}, message = "数值只能是0或者1") private integer isshow;}
@postmapping("/annotation")public result addannotation(@validated @requestbody annotationquery annotation) { return result.buildsuccess(annotation);}
以上就是使用@valid,@validated和@pathvariable的java代码示例及使用方法的详细内容。