有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java如何使用自定义ConstraintValidator将ConstraintViolations添加到索引i处的列表元素

我目前正在使用一个自定义的ConstraintValidator来检查一组对象,这些对象有一个与其关联的时间跨度,以检查其时间跨度中的重叠。验证逻辑正在工作,但是,我不确定如何在违反验证逻辑的情况下向每个对象添加“此对象的时隙与另一个对象的时隙重叠”消息

我尝试了以下几种方法: https://docs.oracle.com/javaee/7/api/javax/validation/ConstraintValidatorContext.html

特别是那些在buildConstraintViolationWithTemplate方法文档中描述的

以下是守则的相关章节:

@Override
public boolean isValid(List<Shift> shifts, ConstraintValidatorContext context) {

List<Integer> overlappingShiftIndices = determineOverlappingShifts(shifts);

if (!overlappingShiftIndices.isEmpty()) {
  log.debug("Overlap validation failed.");

  context.disableDefaultConstraintViolation();
  // Moving the error from form-level to fields
  for (int index : overlappingShiftIndices) {
    context.buildConstraintViolationWithTemplate("{com.generali.standbyscheduler.validation.shiftlist.overlap}")
           .addBeanNode()
           .inIterable().atIndex(index)
           .addConstraintViolation();
  }

  return false;
}

log.debug("Overlap validation succeeded.");
return true;
}

如您所见,我在这里尝试了.addBeanNode().inIterable().atIndex(index)方法。查看ConstraintViolation时,属性路径显示为list[index]。这是正确的吗

我计划使用它从Thymeleaf模板中的BindingResult访问确定的违规行为,并且不确定是否可以通过这种方式访问违规行为。该列表将是另一个bean的属性,因此我希望使用类似propertyNameOfList[index]的路径来读取冲突。或者是propertyNameOfList.list[index]还是别的什么


共 (1) 个答案

  1. # 1 楼答案

    当我试图验证对象列表中的某些字段是否唯一时,我也遇到了同样的问题。我自己的解决方案(我在网上找不到:/):

    您必须覆盖当前的PropertyNode,并使用.addPropertyNode(null).inIterable().atIndex(index)添加索引号。例如:

    约束旋转:

    @Target({ElementType.FIELD, ElementType.PARAMETER})
    @Retention(RetentionPolicy.RUNTIME)
    @Constraint(validatedBy = UniqueBusinessIndexValidator.class)
    public @interface UniqueEntries {
    
        String message() default ValidationMessages.REQUIRED_UNIQUE_INDEX;
        Class<?>[] groups() default {};
        Class<? extends Payload>[] payload() default {};
    }
    

    约束验证器:

    public class UniqueBusinessIndexValidator implements ConstraintValidator<UniqueEntries, List<HasBusinessIndex>> {
    
        @Override
        public boolean isValid(List<HasBusinessIndex> collection, ConstraintValidatorContext context) {
            if (collection == null || collection.isEmpty()) {
                return true;
            }
    
            Map<String, List<Integer>> indexesMap = new HashMap<>();
            for (int runner = 0; runner < collection.size(); runner++) {
                String businessIndex = collection.get(runner).getBusinessIndex();
                if (indexesMap.containsKey(businessIndex)) {
                    indexesMap.get(businessIndex).add(runner);
                } else {
                    indexesMap.put(businessIndex, new ArrayList<>(List.of(runner)));
                }
            }
    
            boolean isValid = indexesMap.values().stream().noneMatch(indexes -> indexes.size() > 1);
            if (!isValid) {
                indexesMap.values()
                          .stream()
                          .filter(index -> index.size() > 1)
                          .forEach(index -> addUniqueBusinessIndexkennungViolation(context, index));
            }
            return isValid;
        }
    
        private void addUniqueBusinessIndexkennungViolation(ConstraintValidatorContext context, List<Integer> indexes) {
            for (Integer index : indexes) {
                context.buildConstraintViolationWithTemplate(ValidationMessages.REQUIRED_UNIQUE_INDEX)
                       .addPropertyNode(null)
                       .inIterable()
                       .atIndex(index)
                       .addPropertyNode("businessIndex")
                       .addConstraintViolation()
                       .disableDefaultConstraintViolation();
            }
        }