网站服务器提供商,公司网站域名申请流程,内容管理网站,qq浏览器小程序Valid和Validated
Valid和Validated比较
相同点: Valid注解和 Validated注解都是开启校验功能的注解不同点: Validated注解是Spring基于 Valid注解的进一步封装,并提供比如分组,分组顺序的高级功能使用位置不同: Valid注解 : 可以使用在方法,构造函数,方法参数和成员属性上Va…Valid和Validated
Valid和Validated比较
相同点: Valid注解和 Validated注解都是开启校验功能的注解不同点: Validated注解是Spring基于 Valid注解的进一步封装,并提供比如分组,分组顺序的高级功能使用位置不同: Valid注解 : 可以使用在方法,构造函数,方法参数和成员属性上Validated注解 : 可以用在类型,方法和方法参数上. 但是不能用在成员属性上
Valid高级使用
Valid级联校验
级联校验: 也叫嵌套检测.嵌套就是一个实体类包含另一个实体类Valid和可以用在成员属性的字段上,因此 Valid可以提供级联校验示例: Data
public class Hair {NotBlank(message 头发长度必须提交)private Double length;NotBlank(message 头发颜色必须提交)private String color;
}Data
public class Person {NotBlank(message 用户姓名必须提交)Size(min2, max8)private String userName;// 添加Valid注解实现嵌套检测ValidNotEmpty(message 用户要有头发)private ListHair hairs;
}PostMapping(/person)
public Result addPerson(Valid RequestBody Person person) {return Result.buildSuccess(person);
}
复制代码 只是在方法参数前面添加 Valid和 Validated注解,不会对嵌套的实体类进行校验.要想实现对嵌套的实体类进行校验,需要在嵌套的实体类属性上添加 Valid注解
Validated高级使用
Validated分组校验
分组校验: 对指定的组开启校验,可以分别作用于不同的业务场景中分组校验是由 Validated注解中的value提供的groups: JSR 303校验注解中的分组方法groups示例:Data
public 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;
}
复制代码 开启分组校验: 通过 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注解实现示例:
Data
public class UserGroupSequence {public interface FirstGroup {}public interface SecondGroup {}// 使用GroupSequence定义分组校验顺序按照FirstGroupSecondGroup分组顺序进行校验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.classPostMapping(/user)public Result addGroup(Validated(value Group.class) RequestBody UserGroupSequence user) {return Result.buildSuccess(user);}
}
复制代码
使用 GroupSequence注解指定分组校验顺序后,第一组分组的约束的校验没有通过后,就不会进行第二组分组的约束的校验
Validated非实体类校验
在非实体类上添加 Validated注解对非实体类进行校验
Validated
public 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)
ResponseBody
public Result resolveConstraintViolationException(ConstraintVilationException exception) {SetConstraintVilation? 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(nameid) String userId) {return Result.buildSuccess(userId);
}
复制代码
继承BasicErrorController类
ControllerAdvice注解只能处理进入控制器方法抛出的异常BasicErrorController接口可以处理全局异常PathVariable路径校验异常不是控制器方法抛出的,此时还没有进入控制器方法: BasicErrorController处理异常,比如404异常时,会跳转到 /error路径,此时会返回错误的html页面为了保证返回结果统一,继承BasicErrorController类,重写BasicErrorController接口中的错误处理方法
RestController
public class PathErrorController extends BasicErrorController {Autowiredpublic PathErrorController(ErrorAttributes errorAttributes, ServerProperties serverProperties, ListErrorViewResolver errorViewResolvers) {super(errorAttributes, serverProperties.getError(), errorViewResolvers);}/*** 处理html请求*/Overridepublic ModelAndView errorHtml(HttpServletRequest request, HttpServletResponse response) {HttpStatus status getStatus(request);MapString, Object model getErrorAttributes(request, isIncludeStackTrace(request, MediaType.TEXT_HTML));ModelAndView modelAndView new ModelAndView(pathErrorPage, model, status);return modelAndView;}/*** 处理json请求*/Overridepublic ResponseEntityMapString, Object error(HttpServletRequest request) {MapString, Object body getErrorAttributes(request, isIncludeStackTrace(request, MediaType.ALL));MapString, 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 ConstraintValidatorShow, Integer {private SetInteger set new HashSet();/*** 初始化操作* 获取value属性指定的数字保存到Set集合中*/Overridepublic void initilize(Show constraintAnnotation) {int[] value constraintAnnotation.value();for (int v : value) {set.add(i);}} Overridepublic boolean isValid(Integer value, ConstraintValidatorContext context) {return set.contains(value);}}
}
复制代码
注意点: Constraint注解: 将自定义的注解和实现的校验类联系起来自定义校验注解类需要实现ConstraintValidatorA extends Annotation, T 接口 接口中第一个泛型参数表示的是自定义注解类接口中第二个泛型参数表示的是校验的属性的值的类型initialize() 方法: 获取到自定义注解中的相关的数据isValid() 方法: 实现自定义的校验逻辑返回boolean类型的校验结果自定义注解的使用:
Data
public 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);
}