【问题标题】:Jersey reuse parameter validation for subresources子资源的 Jersey 重用参数验证
【发布时间】:2016-02-26 16:02:41
【问题描述】:

我必须遵循泽西岛的端点结构:

/objects/
/objects/:id
/objects/:id/:field
/objects/:id/:field/:subfield

我使用的 ID 具有非常特定的格式,因此在向数据库发出请求之前,我首先检查格式是否有效。

现在我必须将这段代码放入每个以:id 为参数的函数的POSTPUTGETDELETE 函数中。所以这只是意味着提前返回。

if (!isIdValid(id)){
    return Response.status(Response.StatusType.BAD_REQUEST)
                   .entity("The ID you've provided is invalid")
                   .build();
}

(实际上错误实体是一个包含更多错误信息的对象)

然后对于使用:field:subfield 参数的每个函数,代码类似。每次都必须复制这种检查和错误处理行为。当我开始复制粘贴内容时,我开始思考:应该有更好的方法吗?

我想将:id 检查代码放在/objects/:id 级别,然后假设所有进一步的嵌套级别都有一个有效的ID。进一步嵌套的其他参数也是如此。

我一直在研究使用子资源定位器,但随后您创建了一个返回子资源新实例的函数。如果验证失败,我无法将Response-object 的条件返回置于该级别。

@Path("{id}")
function Class<ObjectFieldResource> getObjectById(@PathParam("id") String id){
    return ObjectFieldResource.class;
}

我可以开始抛出异常,但我宁愿避免这种情况,因为我并不认为无效输入是一个异常

如何最好地实施这样的结构?我查看了 bean 验证,但这似乎不允许我为我的特定格式 + 自定义错误响应定义验证。

我在实现子资源的方式上是否遗漏了什么?

【问题讨论】:

  • 我知道你说过你不喜欢异常,但你可以有一个 checkID 方法抛出一个异常,然后使用映射器将该异常转换回具有相关信息的响应。 jersey.java.net/documentation/latest/…
  • 我目前有一个通用的异常映射器可以做到这一点。但我确实可以为每种验证错误创建单独的异常类。不过很容易失控。但如果这是要走的路……

标签: java api rest validation jersey


【解决方案1】:

解决方案 1

如果您可以使用正则表达式检查而不是 isIdValid 方法,则可以像这样定义您的资源

@POST
@Path("objects/{id:\\d+}")
public Response doSmth(@PathParam("id") String id) {
...
}

如果id 格式无效,调用者将处于“未找到”响应状态,甚至无法到达您的doSmth 方法。

显然,您可以对所有相等的路径值使用字符串常量。

final static String ID_RES = "objects/{id:\\d+}";

@POST
@Path(ID_RES)
public Response postSmth(@PathParam("id") String id) {
...
}
...
@GET
@Path(ID_RES)
public Object getSmth(@PathParam("id") String id) {
...
}

也可以读取full descriptionPath#value参数

解决方案 2

使用需要 URI 检查的 filter 方法在您的 REST 服务器 javax.ws.rs.container.ContainerRequestFilter 实现中创建和注册。

单个过滤器参数具有来自女巫的ContainerRequestContext 类型,您可以调用getUriInfo 来获取URI 和方法abortWith(Response response),如果您的资源ID 验证失败,可以使用该方法中止调用方请求。

参见泽西手册的Chapter 10. Filters and Interceptors 章节。

【讨论】:

  • 我已经研究过使用正则表达式来解决我的问题。我看到的缺点是我必须将所有检查逻辑放入一个正则表达式中,如果出现额外的约束,这使得维护变得更加困难。另外我想区分ID not foundID semantically incorrect
  • 过滤方法可以工作。但据我了解,这意味着我必须将端点路径结构放在两个地方?过滤器必须知道路径的上下文,以及带注释的函数本身。或者我可以以某种方式从过滤器中引用@PathParam 变量吗?似乎使用异常最适合不重复逻辑。感谢您提供对替代方案的见解!
猜你喜欢
  • 1970-01-01
  • 2011-11-19
  • 2015-02-07
  • 1970-01-01
  • 2016-05-11
  • 1970-01-01
  • 1970-01-01
  • 2015-12-05
  • 1970-01-01
相关资源
最近更新 更多