JSR-303 验证组定义一个默认组
JSR-303 validation groups define a default group
我有一个 bean,其中有很多字段都用 JSR-303 验证注释进行了注释。现在有一个新的要求,其中一个字段是必填的,但仅限于某些条件。
我环顾四周,找到了我需要的东西,验证组。
这是我现在拥有的:
public interface ValidatedOnCreationOnly {
}
@NotNull(groups = ValidatedOnCreationOnly.class)
private String employerId;
@Length(max = 255)
@NotNull
private String firstName;
@Length(max = 255)
@NotNull
private String lastName;
但是,当我 运行 在单元测试中进行此验证时:
@Test
public void testEmployerIdCanOnlyBeSetWhenCreating() {
EmployeeDTO dto = new EmployeeDTO();
ValidatorFactory vf = Validation.buildDefaultValidatorFactory();
Set<ConstraintViolation<EmployeeDTO>> violations = vf.getValidator().validate(dto, EmployeeDTO.ValidatedOnCreationOnly.class);
assertEquals(violations.size(), 3);
}
事实证明,所有非组注释验证都被忽略了,我只得到 1 个违规。
我能理解这种行为,但我想知道是否有办法让该组也包含所有未注释的参数。如果不是,我将不得不做这样的事情:
public interface AlwaysValidated {
}
public interface ValidatedOnCreationOnly extends AlwaysValidated {
}
@NotNull(groups = ValidatedOnCreationOnly.class)
private String employerId;
@Length(max = 255, groups = AlwaysValidated.class)
@NotNull(groups = AlwaysValidated.class)
private String firstName;
@Length(max = 255, groups = AlwaysValidated.class)
@NotNull(groups = AlwaysValidated.class)
private String lastName;
我正在使用的真实 class 有更多的字段(大约 20 个),所以这种方法将指示验证的明确方式变成了一个大混乱。
谁能告诉我有没有更好的方法?可能是这样的:
vf.getValidator().validate(dto, EmployeeDTO.ValidatedOnCreationOnly.class, NonGroupSpecific.class);
我在 spring 项目中使用它,所以如果 spring 有其他方法,我会很高兴知道。
javax.validation.groups.Default
中有一个Default
组,代表默认的Bean Validation组。除非明确定义组列表:
- 约束属于
Default
组
- 验证适用于
Default
组
您可以扩展此组:
public interface ValidatedOnCreationOnly extends Default {}
只是想添加更多:
如果您使用的是 spring 框架,则可以使用 org.springframework.validation.Validator
@Autowired
private Validator validator;
并手动执行验证:
validator.validate(myObject, ValidationErrorsToException.getInstance());
在控制器中:
@RequestMapping(method = RequestMethod.POST)
public Callable<ResultObject> post(@RequestBody @Validated(MyObject.CustomGroup.class) MyObject request) {
// logic
}
尽管以这种方式从 javax.validation.groups.Default
扩展是行不通的,因此您必须将 Default.class
包括在组中:
class MyObject {
@NotNull(groups = {Default.class, CustomGroup.class})
private String id;
public interface CustomGroup extends Default {}
}
对我来说到处加Default.class不是好办法。
所以我扩展了 LocalValidatorFactoryBean,它使用一些组进行验证,并在没有任何组的情况下委托进行验证。
我用的是spring boot 2.2.6.RELEASE
我使用了 spring-boot-starter-validation 依赖项。
我要验证的 bean
public class SomeBean {
@NotNull(groups = {UpdateContext.class})
Long id;
@NotNull
String name;
@NotNull
String surName;
String optional;
@NotNull(groups = {CreateContext.class})
String pesel;
@Valid SomeBean someBean;
}
自己的代码 class 扩展了 LocalValidatorFactoryBean
public class CustomValidatorFactoryBean extends LocalValidatorFactoryBean {
@Override
public void validate(Object target, Errors errors, Object... validationHints) {
if (validationHints.length > 0) {
super.validate(target, errors, validationHints);
}
super.validate(target, errors);
}
}
通过@Bean 或仅使用@Component(如您所愿)将其放入spring 上下文
@Bean
@Primary
public LocalValidatorFactoryBean customLocalValidatorFactoryBean() {
return new CustomValidatorFactoryBean();
}
在一些 RestController 中的使用
// So in this method will do walidation on validators with CreateContext group and without group
@PostMapping("/create")
void create(@RequestBody @Validated(CreateContext.class) SomeBean someBean) {
}
@PostMapping("/update")
void update(@RequestBody @Validated(UpdateContext.class) SomeBean someBean) {
}
由于某些原因,testValidation 在被 RestController 或其他 spring bean 调用 DummyService.testValidation() 时无法正常工作。
只有在 RestController 端工作:/
@Validated
@Service
@AllArgsConstructor
class DummyService {
public void testValidation(@NotNull String string, @Validated(UpdateContext.class) SomeBean someBean) {
System.out.println(string);
System.out.println(someBean);
}
}
我有一个 bean,其中有很多字段都用 JSR-303 验证注释进行了注释。现在有一个新的要求,其中一个字段是必填的,但仅限于某些条件。
我环顾四周,找到了我需要的东西,验证组。
这是我现在拥有的:
public interface ValidatedOnCreationOnly {
}
@NotNull(groups = ValidatedOnCreationOnly.class)
private String employerId;
@Length(max = 255)
@NotNull
private String firstName;
@Length(max = 255)
@NotNull
private String lastName;
但是,当我 运行 在单元测试中进行此验证时:
@Test
public void testEmployerIdCanOnlyBeSetWhenCreating() {
EmployeeDTO dto = new EmployeeDTO();
ValidatorFactory vf = Validation.buildDefaultValidatorFactory();
Set<ConstraintViolation<EmployeeDTO>> violations = vf.getValidator().validate(dto, EmployeeDTO.ValidatedOnCreationOnly.class);
assertEquals(violations.size(), 3);
}
事实证明,所有非组注释验证都被忽略了,我只得到 1 个违规。
我能理解这种行为,但我想知道是否有办法让该组也包含所有未注释的参数。如果不是,我将不得不做这样的事情:
public interface AlwaysValidated {
}
public interface ValidatedOnCreationOnly extends AlwaysValidated {
}
@NotNull(groups = ValidatedOnCreationOnly.class)
private String employerId;
@Length(max = 255, groups = AlwaysValidated.class)
@NotNull(groups = AlwaysValidated.class)
private String firstName;
@Length(max = 255, groups = AlwaysValidated.class)
@NotNull(groups = AlwaysValidated.class)
private String lastName;
我正在使用的真实 class 有更多的字段(大约 20 个),所以这种方法将指示验证的明确方式变成了一个大混乱。
谁能告诉我有没有更好的方法?可能是这样的:
vf.getValidator().validate(dto, EmployeeDTO.ValidatedOnCreationOnly.class, NonGroupSpecific.class);
我在 spring 项目中使用它,所以如果 spring 有其他方法,我会很高兴知道。
javax.validation.groups.Default
中有一个Default
组,代表默认的Bean Validation组。除非明确定义组列表:
- 约束属于
Default
组 - 验证适用于
Default
组
您可以扩展此组:
public interface ValidatedOnCreationOnly extends Default {}
只是想添加更多:
如果您使用的是 spring 框架,则可以使用 org.springframework.validation.Validator
@Autowired
private Validator validator;
并手动执行验证:
validator.validate(myObject, ValidationErrorsToException.getInstance());
在控制器中:
@RequestMapping(method = RequestMethod.POST)
public Callable<ResultObject> post(@RequestBody @Validated(MyObject.CustomGroup.class) MyObject request) {
// logic
}
尽管以这种方式从 javax.validation.groups.Default
扩展是行不通的,因此您必须将 Default.class
包括在组中:
class MyObject {
@NotNull(groups = {Default.class, CustomGroup.class})
private String id;
public interface CustomGroup extends Default {}
}
对我来说到处加Default.class不是好办法。 所以我扩展了 LocalValidatorFactoryBean,它使用一些组进行验证,并在没有任何组的情况下委托进行验证。
我用的是spring boot 2.2.6.RELEASE 我使用了 spring-boot-starter-validation 依赖项。
我要验证的 bean
public class SomeBean {
@NotNull(groups = {UpdateContext.class})
Long id;
@NotNull
String name;
@NotNull
String surName;
String optional;
@NotNull(groups = {CreateContext.class})
String pesel;
@Valid SomeBean someBean;
}
自己的代码 class 扩展了 LocalValidatorFactoryBean
public class CustomValidatorFactoryBean extends LocalValidatorFactoryBean {
@Override
public void validate(Object target, Errors errors, Object... validationHints) {
if (validationHints.length > 0) {
super.validate(target, errors, validationHints);
}
super.validate(target, errors);
}
}
通过@Bean 或仅使用@Component(如您所愿)将其放入spring 上下文
@Bean
@Primary
public LocalValidatorFactoryBean customLocalValidatorFactoryBean() {
return new CustomValidatorFactoryBean();
}
在一些 RestController 中的使用
// So in this method will do walidation on validators with CreateContext group and without group
@PostMapping("/create")
void create(@RequestBody @Validated(CreateContext.class) SomeBean someBean) {
}
@PostMapping("/update")
void update(@RequestBody @Validated(UpdateContext.class) SomeBean someBean) {
}
由于某些原因,testValidation 在被 RestController 或其他 spring bean 调用 DummyService.testValidation() 时无法正常工作。 只有在 RestController 端工作:/
@Validated
@Service
@AllArgsConstructor
class DummyService {
public void testValidation(@NotNull String string, @Validated(UpdateContext.class) SomeBean someBean) {
System.out.println(string);
System.out.println(someBean);
}
}