如何在REST Web服务中处理资源验证?

mig*_*ain 20 java rest jpa jersey bean-validation

我正在使用Spring,Jersey和Hibernate(JPA)在Java中构建REST Web服务.

现在我正在尝试在我的资源中添加对验证的支持.JSR-303(Bean验证)自然是一个合适的选择(我使用的是Hibernate Validator,它是JSR-303的参考实现).但是,我试图首先巩固一些概念.

在我看来,至少有两种可能的验证:

  • 对字段进行常规验证,例如检查属性是否为空,检查String属性是否是有效的电子邮件,检查Integer属性是否大于10等等.这是按预期工作的.我已经注册了一个JAX-RS ExceptionMapper,它可以映射javax.validation.ConstraintViolationException到正确的HTTP响应中.
  • 数据完整性验证

我将通过"数据完整性验证"的例子来解释我的意思.当两个或多个资源之间存在关系时会发生这种情况.想象一下两个资源:a Product和a Category.A Product 一个Category.当客户端向服务器发送要Product创建的表示(POST HTTP请求)时,它必须通知Category产品.当然,客户必须事先知道类别.用JSON想象一下:

{
   "quantity": "10",
   "state": "PRODUCED",
   "category": {
      "id": "123"
   }
}
Run Code Online (Sandbox Code Playgroud)

好吧,id的类别123可能不存在.如果我们尝试将其插入数据库,显然我们会得到一个与外键相关的异常.所以我假设我们必须验证这些问题并向客户端返回正确的消息,就像在常规属性验证中一样.


现在,我的主要问题是:

  1. 现在我正在通过JPA与Bean Validation的集成在数据访问级别执行验证.应在验证完成前/后的序列化过程,前/后数据库操作两者
  2. 如何处理数据完整性验证手动?(即明确地咨询数据库检查数据完整性)或者我们应该尝试插入它然后捕获数据库(或DAO)异常?Bean验证与此类验证无关,对吧?
  3. 如果您对JAX-RS/REST和Bean验证有任何经验,如果您让我知道,我将很高兴.使用群组?

这些问题与Java有些相关,但我也希望对这些问题有一些新的看法.一些技术独立的.:)如果您可以在REST Web服务上为这些问题提供自己的解决方案,那就太棒了.

mig*_*ain 8

该解决方案最终成为杰克逊的子类JacksonJaxbJsonProvider,后者实现了JAX-RS MessageBodyReaderMessageBodyWriter.我被惊人的dropwizard的方法所激励.在这个提供程序中,我们需要以某种方式注入一个Validator实例(我使用Spring for Injection和Hibernate Validator来实现JSR-303).如果您使用Hibernate ORM,请不要忘记禁用实体验证,否则您将两次验证同一实体.但这可能是所期望的.

然后,在此子类中MessageBodyReader,我验证对象并InvalidEntityException使用验证器中的错误抛出自定义.我还创建了一个JAX-RS ExceptionMapper<InvalidEntityException>,它将每个映射InvalidEntityException到正确的HTTP响应中.在我的例子中,我返回了一个Bad Request和一个包含错误描述的JSON对象.

请注意,此MessageBodyReader会检查@Valid@Validated注释.这意味着它正确支持组.这很重要,因为我们可能不希望在整个应用程序中进行相同类型的验证.一个例子是我们想要进行部分更新(PUT).或者,例如,id属性在POST请求中必须为null,但在其他任何地方都不为null.

数据完整性验证尚未完全处理.但我计划捕获数据库异常并将它们转换为我自己的域异常(比如说a DataIntegrityException),因为它似乎更有效,并且松散地耦合到我身上.


更新:

从JAX-RS 2开始,推荐的方法是使用它的Bean Validation支持.点击此处:https://jersey.java.net/documentation/latest/bean-validation.html


yef*_*iak 6

您现在可以使用Jersey 2.0通过JSR-303/JSR-349验证资源参数.

https://jersey.java.net/documentation/latest/bean-validation.html#d0e9301