同一路径上的子资源定位器和资源方法是否非法?

Are subresource locator and resource method on same path illegal?

我们正在构建一个 RESTful JAXRS Web 服务以与 Jersey HTTP 客户端一起使用。我们希望大量使用子资源定位器来防止单个大型源文件中的代码混乱。例如。 (最小示例):

@Path("places")
public class PlacesResource {

    // Use the following to e.g. GET /places/123
    @GET @Path("{id}")
    @Produces("application/json")
    public Response getPlace(@PathParam("id") int id) {
        //...
        return Response.ok(null).build();
    }

    // Use the following to e.g. GET /places/123/comments/42
    @Path("{id}")
    public PlaceResource place(@PathParam("id") int id) {
        Place p = DAO.getInstance().getPlace(id);
        return new PlaceResource(p); // singular (a different resource class)
    }
}

这很好用。删除这些方法中的任何一个都会使对前导注释中指定的资源的调用不起作用。 (HTTP 响应 405:方法不允许)

但是,在使用此设置时,以下警告会打印到 Tomcat 日志中:

[http-nio-8084-exec-6] org.glassfish.jersey.internal.Errors.logErrors The following warnings have been detected: WARNING: The resource (or sub resource) Resource{"{id}", 0 child resources, 5 resource methods, 1 sub-resource locator, 4 method handler classes, 0 method handler instances} with path "{id}" contains (sub) resource method(s) and sub resource locator. The resource cannot have both, methods and locator, defined on same path. The locator will be ignored.

它说定位器将被忽略,但它非常有效。怎么了?顺便说一下,我更希望能够为路径 /places/{id} 使用子资源定位器。它应该只使用子资源 class 中的 @GET-注释方法;不过,如前所述,returns 是一个 405 错误代码。

是的,这是非法的。添加子资源时,它也负责管理其根路径。因此,对于路径 /places/{id} ,服务不知道要使用哪一个(方法或子资源),因为它们都声称管理该路径。子资源定位器确实被忽略了,但只针对那个不明确的路径 (/places/{id})。路径 /places/{id}/other stuff 没有歧义,因为它与 GET 方法的路径不匹配,因此不会被忽略。

要消除歧义,请尝试修改子资源以仅匹配指定地点 ID 其他路径组件的路径。我目前无法访问我的 IDE 进行测试,但像这样的东西应该可以工作:

// Use the following to e.g. GET /places/123/comments/42
@Path("{id}/{otherStuff: [a-zA-Z0-9_/]+}")
public PlaceResource place(@PathParam("id") int id) {
    Place p = DAO.getInstance().getPlace(id);
    return new PlaceResource(p); // singular (a different resource class)
}