人世繁华|请不要在Java开发中再使用判断进行参数校验了
3.JSR303校验规范及其实现为了解决上面的痛点 , 将验证逻辑与相应的领域模型进行绑定是十分有必要的 。 为此产生了JSR303–BeanValidation规范 。 HibernateValidator是JSR-303的参考实现 , 它提供了JSR303规范中所有的约束(constraint)的实现 , 同时也增加了一些扩展 。
HibernateValidator提供的常用的约束注解
org.springframework.bootspring-boot-starter-validation一种可以实现接口来定制Validator , 一种是使用约束注解 。 胖哥觉得注解可以满足绝大部分的需求 , 所以建议使用注解来进行数据校验 。 而且注解更加灵活 , 控制的粒度也更加细 。 接下来我们来学习如何使用注解进行数据校验 。
4.1约束注解的基本使用我们对需要校验的方法入参进行注解约束标记 , 例子如下:
@DatapublicclassStudent{@NotBlank(message="姓名必须填")privateStringname;@NotNull(message="年龄必须填写")@Range(min=1,max=50,message="年龄取值范围1-50")privateIntegerage;@NotEmpty(message="成绩必填")privateListscores;}POST请求然后定义一个POST请求的SpringMVC接口:
?@RestController@RequestMapping("/student")publicclassStudentController{?@PostMapping("/add")publicRest>addStudent(@Valid@RequestBodyStudentstudent){returnRestBody.okData(student);}}通过对addStudent方法入参添加@Valid来启用参数校验 。 当使用下面数据进行请求将会抛出MethodArgumentNotValidException异常 , 提示age范围超出1-50 。
POST/student/addHTTP/1.1Host:localhost:8888Content-Type:application/json?{"name":"felord.cn","age":77,"scores":[55]}GET请求如法炮制 , 我们定义一个GET请求的接口:
@GetMapping("/get")publicRest>getStudent(@ValidStudentstudent){returnRestBody.okData(student);}使用下面的请求可以正确对学生分数scores进行了校验 , 但是抛出的并不是MethodArgumentNotValidException异常 , 而是BindException异常 。 这和使用@RequestBody注解有关系 , 这对我们后面的统一处理非常十分重要 。
GET/student/get?name=felord.cn&age=12HTTP/1.1Host:localhost:8888自定义注解可能有些同学注意到上面的年龄我进行了这样的标记:
@NotNull(message="年龄必须填写")@Range(min=1,max=50,message="年龄取值范围1-50")privateIntegerage;这是因为@Range不会去校验为空的情况 , 它只处理非空的时候是否符合范围约束 。 所以要用多个注解来约束 。 如果我们某些场景需要重复的捆绑多个注解来使用时 , 可以使用自定义注解将它们封装起来组合使用 , 下面这个注解就是将@NotNull和@Range进行了组合 , 你可以仿一个出来用用看 。
importorg.hibernate.validator.constraints.Range;?importjavax.validation.Constraint;importjavax.validation.Payload;importjavax.validation.ReportAsSingleViolation;importjavax.validation.constraints.NotNull;importjavax.validation.constraintvalidation.SupportedValidationTarget;importjavax.validation.constraintvalidation.ValidationTarget;importjava.lang.annotation.*;?/***@authora*@since17:31**/@Constraint(validatedBy={})@SupportedValidationTarget({ValidationTarget.ANNOTATED_ELEMENT})@Retention(RetentionPolicy.RUNTIME)@Target({ElementType.METHOD,ElementType.FIELD,ElementType.ANNOTATION_TYPE,ElementType.CONSTRUCTOR,ElementType.PARAMETER,ElementType.TYPE_USE})@NotNull@Range(min=1,max=50)@Documented@ReportAsSingleViolationpublic@interfaceAge{//message必须有Stringmessage()default"年龄必须填写 , 且范围为1-50";?//可选Class>[]groups()default{};?//可选ClassextendsPayload>[]payload()default{};}还有一种情况 , 我们在后台定义了枚举值来进行状态的流转 , 也是需要校验的 , 比如我们定义了颜色枚举:
- 人世繁华|YES,英伟达哪会扔出30系列核弹?,平心而论,若不是AMD
- 人世繁华|手机用暗黑模式更省电?!这是真的吗?
- 人世繁华|苹果手机全型号竟全部在列,打脸现场?上半年手机销量前十公布
- 请不要叫我测评君|K30 Ultra上手评测:有赶工之嫌的性价比神作,Redmi
- 人世繁华|字节跳动挖角百度前高管——居然“早有前科”啊
- 人世繁华|可信计算真能“彻底改变”网络安全的“命运”?
- 人世繁华|总投资50亿,恒大新能源汽车底价1.7亿元摘南宁超600亩土地
- 科技娜评|Pro主动降噪,独享二人世界,七夕攻略:华为FreeLace
- 人世繁华|打破传统建立新的营销推广模式,小程序商城三级分销
- 科技有点牛|为什么造不出漂亮的汽车?请不起设计师吗?,专注自主研发的奇瑞