我正在使用Spring,Jersey和Hibernate(JPA)在Java中构建REST Web服务。
现在,我正在尝试在资源中添加对验证的支持。JSR-303(Bean验证)自然是一个合适的选择(我使用的是Hibernate Validator,它是JSR-303的参考实现)。但是,我尝试首先合并一些概念。
在我看来,至少有两种可能的验证:
String
Integer
10
javax.validation.ConstraintViolationException
我将通过一个示例来解释“数据完整性验证”的确切含义。当两个或多个资源之间存在关系时,会发生这种情况。想象两个资源:a Product和a Category。A Product 有 个Category。当客户端将要Product创建的表示发送到服务器(POST HTTP请求)时,它必须通知Category产品。当然,客户必须事先知道类别。想象一下JSON:
Product
Category
{ "quantity": "10", "state": "PRODUCED", "category": { "id": "123" } }
好吧,ID类别123可能不存在。如果我们尝试将其插入数据库,显然会得到与外键相关的异常。因此,我认为我们必须验证这些问题并向客户端返回正确的消息,就像常规的属性验证一样。
123
现在,我的主要问题是:
这些问题在某种程度上与Java有关,但我也希望对这些问题有一些新的认识。 一些技术独立的。:)如果您可以在REST Web服务上为这些问题提供自己的解决方案,那就太好了。
该解决方案最终归为JacksonJaxbJsonProvider实现了JAX-RS MessageBodyReader和的Jackson’s的子类MessageBodyWriter。惊人的Dropwizard的方法使我受到启发。在此提供程序中,我们需要以某种方式注入Validator实例(我将Spring用于注入,将Hibernate Validator用于JSR-303实现)。如果您使用Hibernate ORM,请不要忘记禁用实体验证,否则您将两次验证同一实体。不过,这可能是所需要的。
JacksonJaxbJsonProvider
MessageBodyReader
MessageBodyWriter
然后,在这个子类中MessageBodyReader,我验证对象并抛出一个InvalidEntityException来自验证器的错误的自定义。我还创建了一个JAX- RS ExceptionMapper<InvalidEntityException>,该映射将每个映射InvalidEntityException到正确的HTTP响应中。在我的情况下,我返回了错误请求和包含错误描述的JSON对象。
InvalidEntityException
ExceptionMapper<InvalidEntityException>
请注意,此MessageBodyReader会检查@Valid和@Validated注释。这意味着它正确支持组。这很重要,因为我们可能不想在整个应用程序中进行相同的验证。例如,当我们要进行部分更新(PUT)时。或者,例如,id属性在POST请求中必须为null,但在其他所有地方都不为null。
@Valid
@Validated
数据完整性验证尚未完全处理。但是我正计划捕获数据库异常并将它们转换为我自己的域异常(例如DataIntegrityException),因为它看起来效率更高且与我无关。
DataIntegrityException
更新:
从JAX-RS 2开始,推荐的方法是使用其Bean验证支持。在这里检查:https : //jersey.java.net/documentation/latest/bean- validation.html