子资源的泽西重用参数验证

时间:2016-02-26 16:02:41

标签: java api rest validation jersey

我必须在Jersey中遵循端点结构:

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

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

现在,我必须将此代码放在每个POSTPUTGETDELETE函数中,以用于{{1}的每个函数}作为参数。所以这只是意味着早日回归。

:id

(实际上,错误实体是包含有关错误的更多信息的对象)

然后对于使用if (!isIdValid(id)){ return Response.status(Response.StatusType.BAD_REQUEST) .entity("The ID you've provided is invalid") .build(); } :field参数的每个函数,代码类似。必须每次都复制此检查和错误处理行为。当我开始复制粘贴的东西时,我开始思考:应该有更好的方法吗?

我想将:subfield检查代码放在:id级别,然后假设所有其他嵌套级别都具有有效ID。其他参数进一步嵌套相同。

我一直在研究使用子资源定位器,但是你创建了一个返回子资源新实例的函数。如果验证失败,我无法在该级别上条件返回/objects/:id - 对象。

Response

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

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

我是否遗漏了应该实施子资源的方式?

1 个答案:

答案 0 :(得分:0)

解决方案1 ​​

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

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

如果格式为id格式无效,则调用者将无法获得“未找到”的响应状态,甚至无法使用doSmth方法。

显然,您可以将String常量用于所有相等的路径值。

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) {
...
}

还可以阅读Path#value参数

full description

解决方案2

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

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

请参阅泽西岛手册的Chapter 10. Filters and Interceptors章节。