如何将REST请求转发到另一个资源?

wat*_*ery 7 java rest jax-rs jersey

在我目前的架构中,我有一个JAX-RS资源,它位于后面:

/categories
/categories/{catId}
Run Code Online (Sandbox Code Playgroud)

这是这样实现的:

@Path("/categories")
@Produces("application/json")
public class CategoryResourcesApi {

    @GET
    public Response getCategories() {
        // ...
    }

    @GET @Path("/{catId}")
    public Response getCategory(@PathParam("catId") String catId) {
        // ...
    }

    // ...

}
Run Code Online (Sandbox Code Playgroud)

和另一个服务:

/products
/products/{prodId}
Run Code Online (Sandbox Code Playgroud)

并有类似的实现:

@Path("/products")
@Produces("application/json")
public class ProductResourcesApi {

    @GET
    public Response getProducts() {
        // ...
    }

    // ...

}
Run Code Online (Sandbox Code Playgroud)

除了这些直截了当的路径,我还需要服务于这些:

/categories/{catId}/products
/categories/{catId}/products/{prodId}
Run Code Online (Sandbox Code Playgroud)

这将是与特定类别相关的产品.

最自然的事情就是ProductResourcesApi为它们服务,但顺便说一下,我理解JAX-RS注释结构,这只能由CategoryResourcesApi(或者最终由第三类,我认为)提供.

@Context在我的资源实现中使用和其他注释,所以直接new ProductResourcesAPI().getProducts()无法工作,我想.

有没有办法在JAX-RS(或Jersey)框架内从一个资源路径转发到另一个资源路径?我还有其他选择吗?如果可能的话,我想保持所有这些易于维护,这就是为什么我为每个根源路径选择一个资源,其中包含子资源.

Pau*_*tha 9

为此,您可以使用子资源定位器,它基本上是资源类中返回另一个资源类的方法.例如,关于链接中的示例的事情是它们自己实例化资源类

@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)
    }
}
Run Code Online (Sandbox Code Playgroud)

这是有效的,但我不确定它是否保留注射,例如,如果你想注入@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) {
    }
}
Run Code Online (Sandbox Code Playgroud)

getProducts会映射到URI /categories/{catId}/products/{prodId}.您只需要检查是否catId为null(仅当您需要它进行任何查找时)我想确定请求是对根产品资源还是父类别资源的请求.我想,代码重用需要付出很小的代价.

只看你的评论,我相信过去Swagger不支持子资源定位器,但我相信现在他们这样做了.如果您遇到问题,可能需要搜索任何讨论.这是一个讨论,另一个,另一个