如何将 REST 请求转发到另一个资源?
How to forward a REST request to another resource?
在我当前的架构中,我有一个位于后面的 JAX-RS 资源:
/categories
/categories/{catId}
实现方式如下:
@Path("/categories")
@Produces("application/json")
public class CategoryResourcesApi {
@GET
public Response getCategories() {
// ...
}
@GET @Path("/{catId}")
public Response getCategory(@PathParam("catId") String catId) {
// ...
}
// ...
}
和另一个服务:
/products
/products/{prodId}
并有类似的实现:
@Path("/products")
@Produces("application/json")
public class ProductResourcesApi {
@GET
public Response getProducts() {
// ...
}
// ...
}
除了这些简单的路径,我还需要服务这些:
/categories/{catId}/products
/categories/{catId}/products/{prodId}
这将是与特定类别相关的产品。
最自然的做法是让 ProductResourcesApi
为它们提供服务,但据我了解 JAX-RS 注释结构,这只能由 CategoryResourcesApi
(或最终由第三个 class,我想)。
我在我的资源实现中使用了 @Context
和其他注释,所以我猜直接 new ProductResourcesAPI().getProducts()
是行不通的。
有没有办法在 JAX-RS(或 Jersey)框架内从一个资源路径转发到另一个资源路径?我还有哪些其他选择?如果可能的话,我想保持所有这些易于维护,这就是为什么我为每个根路径选择一个资源,其中包含子资源。
为此,您可以使用 Sub-resource locators,这基本上是资源 class 中的一种方法,returns 另一个资源 class。 link 中的示例是它们自己实例化资源 class,例如
@Path("/item")
public class ItemResource {
@Path("content")
public ItemContentResource getItemContentResource() {
return new ItemContentResource();
}
}
public class ItemContentResource {
@PUT
@Path("{version}")
public void put(@PathParam("version") int version)
}
}
有效,但我不确定它是否保留注入,例如,如果您想将 @Context UriInfo
注入 ItemContentResource
中的字段。如果您改为注入方法参数,它应该可以工作。
为了解决这个问题,可以使用 ResourceContext
,它在使用时应该保留所有注入。例如在你目前的情况下,你可以做
@Path("/categories")
@Produces("application/json")
public static class CategoryResourcesApi {
@Context
private ResourceContext resourceContext;
@Path("/{catId}/products")
public ProductResourcesApi getProducts() {
return resourceContext.getResource(ProductResourcesApi.class);
}
}
@Path("/products")
@Produces("application/json")
public static class ProductResourcesApi {
@Context
private UriInfo info;
@GET
@Path("/{id}")
public Response getProducts(
@PathParam("id") String prodId,
@PathParam("catId") String catId) {
}
}
getProducts
将映射到 URI /categories/{catId}/products/{prodId}
。您只需要检查 catId
是否为空(仅当您需要它进行任何查找时)我想确定该请求是对根产品资源还是对父类别资源的请求。我想为代码重用付出的代价很小。
而且只看您的评论,我相信 Swagger 过去不支持子资源定位器,但我相信现在他们支持了。如果您有任何问题,您可能需要四处搜索任何讨论。 Here's a discussion, and another one, and another one
在我当前的架构中,我有一个位于后面的 JAX-RS 资源:
/categories
/categories/{catId}
实现方式如下:
@Path("/categories")
@Produces("application/json")
public class CategoryResourcesApi {
@GET
public Response getCategories() {
// ...
}
@GET @Path("/{catId}")
public Response getCategory(@PathParam("catId") String catId) {
// ...
}
// ...
}
和另一个服务:
/products
/products/{prodId}
并有类似的实现:
@Path("/products")
@Produces("application/json")
public class ProductResourcesApi {
@GET
public Response getProducts() {
// ...
}
// ...
}
除了这些简单的路径,我还需要服务这些:
/categories/{catId}/products
/categories/{catId}/products/{prodId}
这将是与特定类别相关的产品。
最自然的做法是让 ProductResourcesApi
为它们提供服务,但据我了解 JAX-RS 注释结构,这只能由 CategoryResourcesApi
(或最终由第三个 class,我想)。
我在我的资源实现中使用了 @Context
和其他注释,所以我猜直接 new ProductResourcesAPI().getProducts()
是行不通的。
有没有办法在 JAX-RS(或 Jersey)框架内从一个资源路径转发到另一个资源路径?我还有哪些其他选择?如果可能的话,我想保持所有这些易于维护,这就是为什么我为每个根路径选择一个资源,其中包含子资源。
为此,您可以使用 Sub-resource locators,这基本上是资源 class 中的一种方法,returns 另一个资源 class。 link 中的示例是它们自己实例化资源 class,例如
@Path("/item")
public class ItemResource {
@Path("content")
public ItemContentResource getItemContentResource() {
return new ItemContentResource();
}
}
public class ItemContentResource {
@PUT
@Path("{version}")
public void put(@PathParam("version") int version)
}
}
有效,但我不确定它是否保留注入,例如,如果您想将 @Context UriInfo
注入 ItemContentResource
中的字段。如果您改为注入方法参数,它应该可以工作。
为了解决这个问题,可以使用 ResourceContext
,它在使用时应该保留所有注入。例如在你目前的情况下,你可以做
@Path("/categories")
@Produces("application/json")
public static class CategoryResourcesApi {
@Context
private ResourceContext resourceContext;
@Path("/{catId}/products")
public ProductResourcesApi getProducts() {
return resourceContext.getResource(ProductResourcesApi.class);
}
}
@Path("/products")
@Produces("application/json")
public static class ProductResourcesApi {
@Context
private UriInfo info;
@GET
@Path("/{id}")
public Response getProducts(
@PathParam("id") String prodId,
@PathParam("catId") String catId) {
}
}
getProducts
将映射到 URI /categories/{catId}/products/{prodId}
。您只需要检查 catId
是否为空(仅当您需要它进行任何查找时)我想确定该请求是对根产品资源还是对父类别资源的请求。我想为代码重用付出的代价很小。
而且只看您的评论,我相信 Swagger 过去不支持子资源定位器,但我相信现在他们支持了。如果您有任何问题,您可能需要四处搜索任何讨论。 Here's a discussion, and another one, and another one