如何在 Spring Boot Data Rest 控制器中 return RFC-7807 格式的验证错误?

How can I return validation errors in a RFC-7807 format in Spring Boot Data Rest controllers?

我有一个 Spring 存储库

@RepositoryRestResource
public interface MongoIntegrationTokenRepository extends MongoRepository<IntegrationToken, String>, CrudRepository<IntegrationToken, String> {}

我已经添加了验证配置以添加验证支持并且我的实体具有验证注释:

@Configuration
class MyRestMvcConfiguration implements RepositoryRestConfigurer {

    private final LocalValidatorFactoryBean localValidatorFactoryBean;

    @Autowired
    public MyRestMvcConfiguration(LocalValidatorFactoryBean localValidatorFactoryBean) {
        this.localValidatorFactoryBean = localValidatorFactoryBean;
    }

    @Override
    public void configureValidatingRepositoryEventListener(
            ValidatingRepositoryEventListener validatingRepositoryEventListener) {
        validatingRepositoryEventListener.addValidator("beforeCreate", localValidatorFactoryBean);
        validatingRepositoryEventListener.addValidator("beforeSave", localValidatorFactoryBean);
        validatingRepositoryEventListener.addValidator("beforeSave", localValidatorFactoryBean);
    }
}

当运行创建操作时,如果有任何验证错误,实体创建失败但JSON响应不包含任何错误详细信息。

A POST 到我端点的无效数据只是 returns:

{
  "message": "Server Error",
  "details": [
    "Validation failed"
  ]
}

我想 return RFC7807 format. This should be possible via Spring HATEOAS or by this popular library by Zalando https://github.com/zalando/problem-spring-web 中的验证错误,但我不确定它们需要如何连接或应该使用哪种方法。

我在 Github 上找到了这个单独的例子。 https://github.com/marciovmartins/problem-spring-web-starter-expanded/blob/aed5825c958fad93f4aaad022689958926cf3b4a/src/main/kotlin/com/github/marciovmartins/problem/spring/web/expanded/ProblemExceptionHandler.kt 并在 Java 中重写了它。这个好像可以。

import java.util.List;
import java.util.stream.Collectors;

import org.springframework.data.rest.core.RepositoryConstraintViolationException;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.context.request.NativeWebRequest;
import org.zalando.problem.Problem;
import org.zalando.problem.ThrowableProblem;
import org.zalando.problem.spring.web.advice.ProblemHandling;
import org.zalando.problem.violations.Violation;

@ControllerAdvice
public class ProblemControllerAdvice implements ProblemHandling {

    @ExceptionHandler
    public ResponseEntity<Problem> handleRepositoryConstraintViolationException(RepositoryConstraintViolationException exception, NativeWebRequest request) {
        List<Violation> violationList = exception.getErrors().getAllErrors()
                .stream()
                .map(objectError -> {
                    if (objectError instanceof FieldError) {
                        return new Violation(((FieldError) objectError).getField(), objectError.getDefaultMessage());
                    }
                    return new Violation(null, objectError.getDefaultMessage());
                })
                .collect(Collectors.toList());

        ThrowableProblem problem = Problem.builder()
                .withTitle("Constraint Violation")
                .withStatus(defaultConstraintViolationStatus())
                .with("violations", violationList)
                .build();
        return create(problem, request);
    }

}