0

boolean isValid(Object, ConstraintValidatorContext)ビジネス ロジックを実行し、そのロジックに応じて true/false を返すカスタム Bean バリデーターを実装しています。

私ができるようにしたいのは、スローされる ConstraintViolation 例外にデータを追加することです。それをキャッチして処理する例外ハンドラーは、それを引き起こしたエラー/引数に関する詳細を含むこの余分なデータを引き出すことができます。現在、これらの動的な詳細がない違反にのみメッセージを関連付けることができます。

たとえば、isValid に渡されるオブジェクトには、バリデーターによって内容が検証されるマップが含まれます。バリデーター API はブール値のみを返すため、マップのどのメンバーが制約違反をトリガーしたかの粒度が失われます。この情報を保存して転送できる方法を探しています。

EDIT 8/13/2013 - JAX-RS を含むソリューション例

(この質問に関係のないJAXBの詳細を一部省略しています)

FooParam.java

public class FooParam {
  private Map<String, String> subParamMap;

  public Map<String, String> getSubParamMap() { return this.subParamMap; }
  public void setSubParamMap(Map<String, String> subParamMap) {
    this.subParamMap = subParamMap;
  }

  public FooParam() { this.subParamMap = new HashMap<>(); }
}

FooResource.java

public class FooResource {

  ...

  public void doSomething(@CheckValidParam(value=FooResoure.class) FooParam fooParam) { 
    ...
  }
}

CheckValidParam.java

@Target({ElementType.TYPE, ElementType.METHOD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = CheckValidParamValidator.class)
@Documented
public @interface CheckValidParam{

    String message() default "{com.foo.bar.CheckValidParam.message}";

    Class<?>[] groups() default { };

    Class<? extends Payload>[] payload() default  { };

    Class<?> value();

    @Target({ElementType.TYPE, ElementType.METHOD, ElementType.PARAMETER})
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @interface List {
        CheckValidParam[] value();
    }
}

CheckValidParamValidator.java

public class CheckValidParamValidator implements ConstraintValidator<CheckValidParam, FooParam> {

    private Class<?> entityClass;

    @Override
    public void initialize(CheckValidParam checkValidParam ) {
        this.entityClass = checkValidParam.value();
    }

    @Override
    public boolean isValid(FooParam fooParam, ConstraintValidatorContext constraintValidatorContext) {

        String message = constraintValidatorContext.getDefaultConstraintMessageTemplate();
        constraintValidatorContext.disableDefaultConstraintViolation();
        boolean isValid = true;
        Map<String, String> subParamMap = fooParam.getSubParamMap();

        for (Map.Entry<String, String> entry : subParamMap.entrySet()) {
          //Contrived validation logic
          if (entry.getValue().equalsIgnoreCase("junk")) {   
            constraintValidatorContext.buildConstraintViolationWithTemplate(message)
                                      .addNode(entry.getKey()).addConstraintViolation();
            isValid = false;
           }
        }
        return isValid;
    }
}

JAX-RS パイプラインでスローされた MethodConstraintViolationExceptions をインターセプトするクラスの簡素化されたバージョン。無効なパラメーターと関連するエラー メッセージを引き出すことを示しています。

MethodConstraintValidationMapper.java

@Provider
public class MethodConstraintValidationMapperimplements ExceptionMapper<MethodConstraintViolationException> {

    private static final Logger log = Logger.getLogger(MethodConstraintValidationMapper.class);

    @Override
    public Response toResponse(MethodConstraintViolationException ex) {
        Response response;
        Set<MethodConstraintViolation<?>> violations = ex.getConstraintViolations();
        List<ValidationExceptionError> errors = new ArrayList<>();
        for (MethodConstraintViolation<?> methodConstraintViolation : ex.getConstraintViolations()) {
            ValidationExceptionError error = new ValidationExceptionError();
            error.setFieldName(((PathImpl) methodConstraintViolation.getPropertyPath()).getLeafNode().asString());
            error.setErrorMessage(methodConstraintViolation.getMessage());
            errors.add(error);
        }
        return Response.status(Response.Status.PRECONDITION_FAILED).entity(new GenericEntity<List<ValidationExceptionError>>(errors) {}).type(MediaType.APPLICATION_JSON).build();
    }
}
4

1 に答える 1

2

ConstraintViolationオブジェクトから、無効な値に関する詳細情報を取得できます。特にgetPropertyPath()、リーフ ノードへのパスをナビゲートし、(マップ内の値が検証された場合に) 関連するキーへのアクセスを提供するため、Node#getKey().

于 2013-08-12T20:58:58.697 に答える