#java #rest #jersey
#java #rest #джерси
Вопрос:
Справочная информация: некоторое время назад мы создали RESTful API с использованием Jersey, где мы сопоставляем uri /items.json с массивом идентификаторов json, а /items/{id}.json — с объектом json одного элемента. Теперь мы хотим создать список с некоторыми метаданными для каждого элемента и хотели бы использовать селектор типа /items.data.json , аналогичный apache sling.
Пока что: я просто расширил UriConnegFilter для анализа uri на наличие дополнительных суффиксов, что-то вроде этого:
public class UriSelectorFilter extends UriConnegFilter {
protected List<String> selectors; // this list is populated in the constructor
public ContainerRequest filter(ContainerRequest request) {
super.filter(request);
// search for suffix in last path segment, see http://java.net/projects/jersey/sources/svn/content/trunk/jersey/jersey-server/src/main/java/com/sun/jersey/api/container/filter/UriConnegFilter.java?rev=5034
final String[] suffixes = segment.getPath().split("\.");
for (int i = suffixes.length - 1; i >= 1; i--) {
final String suffix = suffixes[i];
if(selectors.contains(suffix)) {
request.getQueryParameters().putSingle("selector", suffix);
final int index = path.lastIndexOf('.' suffix);
path = new StringBuilder(path).delete(index, index suffix.length() 1).toString();
suffixes[i] = "";
}
}
if (length != path.length()) {
request.setUris(
request.getBaseUri(),
request.getRequestUriBuilder().replacePath(path).build());
}
return request;
}
}
Этот фильтр работает идеально, он находит часть селектора моего uri и добавляет параметр запроса к объекту запроса. Но в моем ресурсе я добавил атрибут @QueryParam, который заполняется только значением по умолчанию, а не добавленным значением запроса:
@GET
@Produces(MediaType.APPLICATION_JSON)
public Response getItemsJSON(@DefaultValue("id") @QueryParam("selector") String selector) {
// query param is not filled with the selector that was found in the UriSelectorFilter
}
У кого-нибудь есть предложения, как я могу предоставить моему ресурсу селектор, который был обнаружен? Есть ли способ лучше, чем использование параметра запроса? (Примечание: если я добавлю запрос к своему URL-адресу типа ‘?selector =something’, то атрибут будет заполнен правильно.)
Любая помощь очень ценится.
Ответ №1:
Вам нужен другой аргумент, который снабжен аннотацией с помощью @PathParam
, и вам нужно указать в вашей @Path
аннотации (к методу или классу), как связать эти биты вместе. Например, для работы с таким путем, как /items/foobar42/data.json
вы могли бы сделать это:
@GET
@Path("/items/{item}/data.json")
@Produces(MediaType.APPLICATION_JSON)
public Response getItemsJSON(@PathParam("item") String itemId,
@DefaultValue("id") @QueryParam("selector") String selector) {
// Now you've got an itemId and a possible selector...
}
Пытаюсь выполнить все сопоставление с фильтром… это кажется мне сложным, учитывая, что вместо этого есть хороший декларативный способ сделать это. Вы даже можете указать регулярное выражение в @Path
разделе, позволяющем сопоставлять более сложные переменные; Я делаю это в своем собственном коде, чтобы создать метод, который может обслуживать целую иерархическую файловую систему.
(Обратите внимание, что {
связанный }
элемент в @Path
должен соответствовать имени в @PathParam
аннотации, и при необходимости вы можете сопоставить несколько элементов из пути; просто используйте несколько @PathParam
аргументов с аннотациями.)