springboot中hibernate validator校验模式,分组校验,自定义校验
檢驗模式
上面例子中一次性返回了所有驗證不通過的集合,通常按順序驗證到第一個字段不符合驗證要求時,就可以直接拒絕請求了。Hibernate Validator有以下兩種驗證模式:
普通模式(默認是這個模式):會校驗完所有的屬性,然后返回所有的驗證失敗信息。
快速失敗模式:只要有一個驗證失敗,則返回。
通常在實際開發中,我們需要配置快速失敗模式,快速失敗模式的配置方式:
package com.morris.validator.config;import org.hibernate.validator.HibernateValidator; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.validation.beanvalidation.MethodValidationPostProcessor;import javax.validation.Validation; import javax.validation.Validator; import javax.validation.ValidatorFactory;@Configuration public class ValidatorConfig {@Beanpublic Validator validator() {ValidatorFactory validatorFactory = Validation.byProvider(HibernateValidator.class).configure()// 快速失敗模式.failFast(true).buildValidatorFactory();return validatorFactory.getValidator();} }也可以如下配置:
@Bean public Validator validator() {ValidatorFactory validatorFactory = Validation.byProvider(HibernateValidator.class).configure()// 快速失敗模式//.failFast(true).addProperty( "hibernate.validator.fail_fast", "true" ).buildValidatorFactory();return validatorFactory.getValidator(); }參數校驗
post參數校驗
post參數校驗需要在方法的參數前面加上注解 @Valid,然后就可以在方法參數對應的實體類的字段上面加上@NotNull、@NotEmpty注解進行校驗了。
@PostMapping("add") public R add(@Valid @RequestBody User user) {return R.ok(); }get參數校驗
get參數校驗無法使用注解@Valid,需要使用@Validated注解來使得驗證生效。
注入MethodValidationPostProcessor
在ValidatorConfig注入MethodValidationPostProcessor來開啟@Validated注解的校驗功能。
@Bean public MethodValidationPostProcessor methodValidationPostProcessor() {MethodValidationPostProcessor postProcessor = new MethodValidationPostProcessor();// 設置validator模式為快速失敗返回postProcessor.setValidator(validator());return postProcessor; }Controller中的配置
Controller上面添加@Validated
注解,方法參數上面添加校驗注解。
ConstraintViolationException異常處理
對get參數校驗會拋出ConstraintViolationException異常,所以需要在GlobalExceptionHandler中對ConstraintViolationException異常進行處理。
@ExceptionHandler(value = ConstraintViolationException.class) public R ConstraintViolationExceptionHandler(ConstraintViolationException ex) {R r = null;Set<ConstraintViolation<?>> constraintViolations = ex.getConstraintViolations();Iterator<ConstraintViolation<?>> iterator = constraintViolations.iterator();while (iterator.hasNext()) {ConstraintViolation<?> cvl = iterator.next();r = R.fail(HttpStatus.BAD_REQUEST.value(), cvl.getMessageTemplate());break;}log.error("Custom exception! error={}", ex);return r; }測試
# curl -X POST http://localhost:8080/user/get -H "content-type:application/json" {"code":400,"message":"status不能為空","result":null}# curl -X POST http://localhost:8080/user/get?status= -H "content-type:application/json" {"code":400,"message":"status不能為空","result":null}# curl -X POST http://localhost:8080/user/get?status=xxxx -H "content-type:application/json" {"code":200,"message":"OK","result":null}級聯校驗
級聯校驗需要在校驗的屬性上面加上@Valid注解。
public class User { ... ...@Validprivate Address address; }@Data public class Address {@NotBlank(message = "province不能為空")private String province;private String city; }測試:
# curl -X POST http://localhost:8080/user/add -H "content-type:application/json" -d '{"userName":"xx", "age": 10, "address": {"province": "ShangHai"}}' {"code":200,"message":"OK","result":null}# curl -X POST http://localhost:8080/user/add -H "content-type:application/json" -d '{"userName":"xx", "age": 10, "address": {"province": ""}}' {"code":400,"message":"province不能為空","result":null}分組
Person類字段分組校驗如下:
public interface PersonCreateGroup { }public interface PersonUpdateGroup { }@Data public class Person {@NotNull(message = "id不能為空", groups = PersonUpdateGroup.class)private Integer id;@NotNull(message = "userName不能為空", groups = {PersonCreateGroup.class, PersonUpdateGroup.class})@NotBlank(message = "userName不能為空", groups = {PersonCreateGroup.class, PersonUpdateGroup.class})private String userName;@NotNull(message = "age不能為空")private Integer age; }Person類中三個分組分別對應的字段如下:
-
PersonUpdateGroup:id、userName
-
PersonCreateGroup:userName
-
Default:age
PersonController代碼如下:
package com.morris.validator.controller;import com.morris.validator.vo.*; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController;import javax.validation.Valid;@RestController @RequestMapping("person") @Validated public class PersonController {@PostMapping("add")@Validated(PersonCreateGroup.class)public R add(@Valid @RequestBody Person person) {return R.ok();}@PostMapping("update")@Validated(PersonUpdateGroup.class)public R update(@Valid @RequestBody Person person) {return R.ok();}@PostMapping("add2")public R add2(@Valid @RequestBody Person person) {return R.ok();}}下面分別對PersonController中的各個接口進行測試:
add:
# curl -X POST http://localhost:8080/person/add -H "content-type:application/json" -d '{"userName":"xxx", "age": 10}' {"code":200,"message":"OK","result":null}# curl -X POST http://localhost:8080/person/add -H "content-type:application/json" -d '{"userName":"xxx"}' {"code":400,"message":"age不能為空","result":null}# curl -X POST http://localhost:8080/person/add -H "content-type:application/json" -d '{"age":10}' {"code":400,"message":"userName不能為空","result":null}update:
# curl -X POST http://localhost:8080/person/update -H "content-type:application/json" -d '{"id":1, "userName":"xxx", "age": 10}' {"code":200,"message":"OK","result":null}# curl -X POST http://localhost:8080/person/update -H "content-type:application/json" -d '{"userName":"xxx", "age": 10}' {"code":400,"message":"id不能為空","result":null}# curl -X POST http://localhost:8080/person/update -H "content-type:application/json" -d '{"id":1, "age": 10}' {"code":400,"message":"userName不能為空","result":null}# curl -X POST http://localhost:8080/person/update -H "content-type:application/json" -d '{"id":1, "userName":"xxx"}' {"code":400,"message":"age不能為空","result":null}add2:
# curl -X POST http://localhost:8080/person/add2 -H "content-type:application/json" -d '{"age": 10}' {"code":200,"message":"OK","result":null}# curl -X POST http://localhost:8080/person/add2 -H "content-type:application/json" -d '{}' {"code":400,"message":"age不能為空","result":null}總結:
-
校驗時指定了group,就會校驗指定group和默認group
-
校驗時沒指定group,只會校驗默認group
校驗時可以指定多個分組,并為這些分組指定順序:
@GroupSequence({OneGroup.class, TwoGroup.class, ThreeGroup.class}) public interface PersonOrder { }自定義校驗器
一般情況,內置的校驗器可以解決很多問題。但也有無法滿足情況的時候,此時,我們可以實現validator的接口,自定義自己需要的驗證器。
如下所示,實現了一個身份證規則驗證器:
package com.morris.validator.validator;import javax.validation.ConstraintValidator; import javax.validation.ConstraintValidatorContext; import java.util.regex.Matcher; import java.util.regex.Pattern;public class IdCardValidator implements ConstraintValidator<IdCard, String> {/*** 身份證規則校驗正則表達式*/private String reg = "^(\\d{6})(\\d{4})(\\d{2})(\\d{2})(\\d{3})([0-9]|X)$";private Pattern pt = Pattern.compile(reg);@Overridepublic void initialize(IdCard idCard) {}@Overridepublic boolean isValid(String value, ConstraintValidatorContext arg1) {if (value == null) {return true;}Matcher m = pt.matcher(value);if (m.find()) {return true;}return false;}}自定義注解:
package com.morris.validator.validator;import javax.validation.Constraint; import javax.validation.Payload; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target;@Target({ElementType.FIELD, ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @Constraint(validatedBy= IdCardValidator.class) public @interface IdCard {String message() default "身份證號碼格式不對";Class<?>[] groups() default {};Class<? extends Payload>[] payload() default {}; }使用如下:
public class Person {... ...@IdCard(message = "身份證號碼格式不對")private String idCardNo; }測試如下:
# curl -X POST http://localhost:8080/person/add -H "content-type:application/json" -d '{"userName":"morris","age":10, "idCardNo":"33"}' {"code":400,"message":"身份證號碼格式不對","result":null}參考文檔
- 官網:https://docs.jboss.org/hibernate/stable/validator/reference/en-US/html_single/
總結
以上是生活随笔為你收集整理的springboot中hibernate validator校验模式,分组校验,自定义校验的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: [Java web编程]第2章 HTML
- 下一篇: 强制卸载lync server 的CMS