2015-10-30 2 views
4

В моей нынешней архитектуре, у меня есть ресурс JAX-RS, который находится позади:Как перенаправить запрос REST на другой ресурс?

/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 (или, в конечном итоге, третьим классом, я думаю).

Я использую @Context и другие аннотации в моих реализациях ресурсов, поэтому прямой new ProductResourcesAPI().getProducts() не будет работать, я думаю.

Есть ли способ переслать один путь ресурса в другой в рамках JAX-RS (или Джерси)? Какие у меня есть другие варианты? Я хотел бы сохранить все это легко, если это возможно, и поэтому я выбрал один ресурс для каждого корневого пути с субресурсами внутри.

+0

Ну, если вы не можете положить его вместе с JAX-RS, то вы можете подумать об использовании простых сервлетов (с маршрутизацией в web.xml) и использовать GSON (или нечто подобное), чтобы создать выход JSON. Возможно, вам понадобится немного больше рукописного кода, но вы получите гибкость. – erosb

+1

@erosb Не вариант: помимо простоты, предлагаемой этими фреймворками, я использую [Swagger] (http://swagger.io/) для документации API, которая интегрируется с ними для создания документов. – watery

ответ

7

Для этого вы можете использовать Sub-resource locators, что в основном метод класса ресурсов, который возвращает другой класс ресурсов. Дело о примерах в ссылке, что они экземпляр класса ресурса себя, например

@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. Он должен работать, хотя если вы вместо этого вводите в параметр param.

Чтобы обойти это, есть 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 обсуждения и another one и another one

+1

FYI - вы можете просто вернуть класс (вместо использования resourceContext) –

Смежные вопросы