这更多的是一个理论问题而不是技术问题。我想知道实现某些方法(或方法?)以在扩展相同 POJO 的不同 POJO 上工作的最佳方法是什么。在我创建的示例应用程序中,我想使用 jakarta 验证一些 POJO(Jakarta Bean Validation)。 在这里您可以找到完整的示例应用程序zoo repo,无论如何我将在这里描述主要功能。
我专注于 SpringBoot 应用程序。
我有一个休息控制器,接受列表作为输入:
@RestController
@RequestMapping(value = "/api/v1", produces = MediaType.APPLICATION_JSON_VALUE)
public class AnimalController {
AnimalService service;
@PostMapping("/validate")
@ResponseStatus(value = HttpStatus.OK)
public List<ValidationErrorDTO> validateCollection(@RequestBody List<AnimalDTO> request)
{
return service.validateCollection(request);
}
public AnimalController(AnimalService service) {
super();
this.service = service;
}
}
在 AnimalDTO 类中,我在属性上添加了一些 jakarta 注释:
import jakarta.validation.constraints.Size;
public class AnimalDTO {
@Size(max = 5, message = "name can not be longer than 5")
private String name;
@Size(max = 5, message = "owner can not be longer than 5")
private String owner;
...
在服务的方法实现中我收到错误:
@Component
public class AnimalServiceImpl implements AnimalService{
@Override
public List<ValidationErrorDTO> validateCollection(List<AnimalDTO> collection) {
List<ValidationErrorDTO> validationErrorList = new ArrayList<>();
//instantiate the validator
ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
Validator validator = factory.getValidator();
//for every record of the collection, validate the record and add errors to the error list
for(int i= 0; i<collection.size();i++) {
int k =i;
//get single record errors
Set<ConstraintViolation<AnimalDTO>> violations = validator.validate(collection.get(i));
violations.forEach(v -> validationErrorList.add(new ValidationErrorDTO(k, v.getPropertyPath().toString(), v.getMessage())));
}
return validationErrorList;
}
}
现在,我有两个 POJO DogDTO 和 CatDTO 扩展了 AnimalDTO,我想重用相同的方法,或者无论如何在这种情况下应用最佳模式来验证输入列表。
我有什么选择?
我没有尝试任何编码,因为这不是技术问题,但我确信我错过了一些东西。也许我想太多了,最好的方法就是使用另一种方法?
你似乎提到了 Jakarta beanvalidation ,在 spring-boot 中使用它的正确方法是用
@Validated
注释 bean 。然后它将创建一个代理,该代理包装该 bean 中的任何方法,其中输入或输出参数都使用 bean 验证注释进行注释。 bean 验证将在执行该方法之前和之后验证输入/输出参数。
如果输入参数验证失败,该方法将不会执行并抛出
ConstraintViolationException
,内部包含所有ConstraintViolation
。
就代码而言,它看起来像:
@Validated
public class AnimalServiceImpl implements AnimalService{
@Override
public void validate(List<@Valid AnimalDTO> collection) {
......
}
}
调用者需要捕获 ConstraintViolationException 并将其转换为
List<ValidationErrorDTO>
喜欢 :
List<AnimalDTO> animals = new ArrayList<>();
animals.add(cat1Dto);
animals.add(cat2Dto);
animals.add(dog1Dto);
animals.add(dog2Dto);
try{
animalService.validate(animals);
} catch (ConstraintViolationException exp) {
Set<ConstraintViolation<?>> violations = exp.getConstraintViolations();
//convert them to List<ValidationErrorDTO>
}