Подтвердить что ты не робот

Можем ли мы иметь более одной аннотации @Path для того же метода REST

Можем ли мы иметь более одной аннотации @Path для того же метода REST, то есть выполняемый метод одинаков, но он выполняется при доступе к нескольким URL-адресам?

Например: Я хочу запустить метод searchNames() как на http://a/b/c, так и на http://a/b.

4b9b3361

Ответ 1

Вы не можете иметь mutliple @Path аннотации для одного метода. Это приводит к синтаксической ошибке "дублирования аннотации".

Однако существует несколько способов эффективного сопоставления двух путей к методу.

Регулярные выражения в аннотации @Path

Аннотация @Path в JAX-RS принимает параметры, значения которых могут быть ограничены с помощью регулярных выражений.

Эта аннотация:

@Path("a/{parameter: path1|path2}")

позволит использовать метод для запросов как для /a/path1, так и для /a/path2. Если вам нужно работать с субпатами, выполните слэши: {a:path1\\/subPath1|path2\\/subPath2}

Выполнение ответов с кодом статуса перенаправления

В качестве альтернативы вы можете настроить перенаправление. Здесь можно сделать это в Джерси (эталонная реализация JAX-RS), определив еще один субресурс. Это просто пример, если вы предпочитаете другой способ обработки перенаправления, не стесняйтесь использовать его.

@Path("basepath")
public class YourBaseResource {

  //this gets injected after the class is instantiated by Jersey    
  @Context
  UriInfo uriInfo; 

  @Path("a/b")
  @GET
  public Responce method1(){
    return Response.ok("blah blah").build();
  }

  @Path("a/b/c")
  @GET
  public Response method2(){
    UriBuilder addressBuilder = uriInfo.getBaseUriBuilder();
    addressBuilder.path("a/b");
    return Response.seeOther(addressBuilder.build()).build();
  }

}

Использование фильтра сервлета для перезаписи URL

Если вам понадобится такая функциональность часто, я предлагаю перехватить входящие запросы с помощью фильтра сервлета и переписать пути "на лету". Это должно помочь вам сохранить все перенаправления в одном месте. В идеале вы можете использовать готовую библиотеку. UrlRewriteFilter может сделать трюк, если у вас все в порядке с лицензией BSD (подробности см. на сайте своего сайта Google).

Другой вариант - обработать это с помощью прокси, настроенного перед вашим Java-приложением. Вы можете настроить сервер Apache, чтобы предлагать основные правила кэширования и перезаписи без сложностей с вашим кодом Java.

Ответ 2

Как объяснено в Tom answer, вы не можете использовать более одного аннотации @Path для одного метода, потому что во время компиляции вы будете работать в error: duplicate annotation.

Я думаю, что самый простой способ обойти это - использовать перегрузку метода:

@Path("{foo}")
public Response rest(@PathParam("foo") final String foo) {
    return this.rest(foo, "");
}

@Path("{foo}/{bar}")
public Response rest(@PathParam("foo") final String foo,
                     @PathParam("bar") final String bar) {
    return Response.ok(foo + " " + bar).build();
}

Вы также можете использовать более разные имена методов, если вы столкнетесь с тем, что несколько перегруженных методов имеют подпись.

Ответ 3

Другое решение для вашего конкретного примера:

Предположим, что:

  • /a для класса ресурсов
  • /b/c и /b - пути для методов

потому что полный путь выглядит следующим образом:

<protocol><host><port><app><url-pattern><resource-path><method-path>.

Использовать необязательный параметр

@Path("/b{c : (/c)?}")
public Response searchNames(@PathParam("c") String val) {
    ...
}

Пример выше работает для всех примеров, таких как:

  • /b
  • /b/
  • /b/c
  • /b/c/

но когда c предоставляется, val является /c (перед ним есть /).

Если вы хотите решить проблему выше (чтобы избежать разбора Java), вам нужно что-то более сложное:

@Path("/b{slash : (/)?}{c:((?<=/).*)?}")

который вернет только c (не /c) для точки 3 rd но для 4 th маркерной точки он вернет c/ который должен анализироваться на Java.

Но для вашего случая ( "метод выполнен один и тот же" ), не беспокойтесь о разборе, потому что у вас нет разных действий.