【问题标题】:Spring data rest validation + exception mapper: confusingSpring数据休息验证+异常映射器:令人困惑
【发布时间】:2016-04-05 21:59:23
【问题描述】:

我正在使用 Spring Data Rest,一切顺利。

我想对我的实体应用验证 (JSR 303)。

spring 文档说我可以通过几种方式拦截应用程序事件(我无法开始工作,而且现在 spring.io 似乎已关闭)。

但是,我确实通过 put 让它工作了

@已验证

在我的存储库上:

@Validated
@RepositoryRestResource(collectionResourceRel = "workers", path = "workers")
public interface WorkerRepository extends PagingAndSortingRepository<Worker, Long> {

}

它会抛出异常。问题是它是一个 spring 异常,甚至不是根异常,我需要基本上进行验证并将它们转换为自定义实体有效负载:

{
  "foo": "must be of length 10",
  "baz": "Must match pattern '[A-Z]+'"
}

所以,简而言之,我想

  • 使用 JSR 303 验证实体
  • 使用 400: 和映射或字段生成 HTTP 实体 -> 错误

最直接的方法是什么? 我也偶然发现了这个:

Detected @ExceptionHandler methods in repositoryRestExceptionHandler

这似乎很有用。当我结帐该课程时,它看起来确实是我所需要的

【问题讨论】:

    标签: java spring spring-data-rest


    【解决方案1】:

    Spring data rest 不会自动应用 bean 验证。如果要进行 bean 验证,则需要在 spring data rest 中注册适当的验证器。

    以下配置对我有用:

    @Configuration
    public class MyValidationConfiguration extends RepositoryRestConfigurerAdapter {
    
        @Bean
        @Primary
        /**
         * Create a validator to use in bean validation - primary to be able to autowire without qualifier
         */
        Validator validator() {
            return new LocalValidatorFactoryBean();
        }
    
        @Override
        public void configureValidatingRepositoryEventListener(ValidatingRepositoryEventListener validatingListener) {
            Validator validator = validator();
            //bean validation always before save and create
            validatingListener.addValidator("beforeCreate", validator);
            validatingListener.addValidator("beforeSave", validator);
        }
    } 
    

    使用此配置,每个具有 bean 验证约束的实体都会在更新和创建之前进行验证。

    (这不会为 spring-data-rest 项目中的自定义控制器启用 bean 验证 - 但这不是您所要求的 - 是吗?)

    • spring 数据休息验证机制正在抛出一个RepositoryConstraintViolationException
    • RepositoryRestExceptionHandler处理
    • 导致错误被序列化为RepositoryConstraintViolationExceptionMessage

    因此,验证错误响应将导致 400 Bad Request 的正文如下:

    {
      "errors" : [ {
        "entity" : "MyEntity",
        "message" : "may not be null",
        "invalidValue" : "null",
        "property" : "price"
      }, {
        "entity" : "MyEntity",
        "message" : "may not be empty",
        "invalidValue" : "",
        "property" : "name"
      }
    }
    

    自定义控制器

    您可以使用 spring-data-rest 实体生命周期application events 来利用您的 spring-data-rest 注册验证器。例如您可以在自定义控制器中发出 BeforeSaveEvent 来触发所有事件处理程序以及 spring-data-rest 提供的验证事件侦听器。这样就可以实现得到相同的错误和错误表示。

    【讨论】:

    • 这看起来可能有效,这正是我所需要的。但我需要拦截这些验证失败会发生什么。
    • @ChristianBongiorno - 感谢您的提示 - 我在帖子中添加了更多细节 - 配置就是你所需要的 - 其余的已经在 spring-data-rest 中提供了
    • @MathiasDpunkt 很好的答案,但事实上,您如何为 spring-data-rest 自定义控制器实现类似的行为?
    • @m4rtin 我在帖子中添加了一段 - 有帮助吗?
    • @MathiasDpunkt 它确实让我走上了正轨,非常感谢!也感谢您的快速回复:)
    【解决方案2】:

    一般来说会很痛苦,你必须完全控制hibernate下的约束违反列表。 MethodValidationPostProcessor 可以帮助您触发@Validated 接口/类的验证过程。 如果您的返回对象或参数是您的复杂类,它也必须标记为 @Valid。

    下一篇文章可以帮助你一点: https://dzone.com/articles/method-validation-spring-31

    不幸的是,我没有发现像 spring-webmvc 这样的 DataBinding 机制可以在一个地方报告带有转换/验证问题的错误(而且它看起来不能以某种方式重用)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-11-02
      • 1970-01-01
      • 2010-12-21
      • 1970-01-01
      • 2016-06-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多