Дополнительные параметры в запросе REST API с использованием Джерси 2.21
Я играю с Jersey 2.21
и я хотел бы знать, возможно ли иметь "необязательный" параметр, который может или нет присутствовать в запросе, сделанном на сервер.
Я хочу успешно получить доступ к этим двум методам:
http://localhost:8080/my_domain/rest/api/myMethod/1
http://localhost:8080/my_domain/rest/api/myMethod
как вы можете видеть, я пытаюсь сделать целое число (id
) param необязательный.
я объявил myMethod
следующим образом:
@GET
@Path("myMethod/{id}")
@Produces(MediaType.APPLICATION_JSON + ";charset=UTF-8")
public String myMethod(@PathParam("id") Integer id, @Context HttpHeaders hh)
это работает:
http://localhost:8080/my_domain/rest/api/myMethod/1
и это работает тоже:
http://localhost:8080/my_domain/rest/api/myMethod/
но это не будет работать и я не понимаю, почему. Он бросает!--8--> ошибка:
http://localhost:8080/my_domain/rest/api/myMethod
можете ли вы мне точку в правильном направлении, чтобы решить эту проблему? Мне не нравится, что косая черта обязательна для всех моих вызовов метода REST, и я хотел бы подавить ее, если это возможно.
2 ответов
Итак, после некоторого баловства с некоторыми ответами в необязательно @PathParam в Jax-RS проблема в том, что, используя этот
@Path("/myMethod{id: (/\d+)?}")
public Response get(@PathParam("id") int id) {}
вызывает /
быть в группе захвата. Поэтому, когда Джерси пытается разобрать /1
он получит исключение и отправит 404. Мы могли бы использовать строку, но потом она становится уродливой, так как нам нужно избавиться от ведущего /
и разберем сами.
@Path("/myMethod{id: (/\d+)?}")
public Response get(@PathParam("id") String id) {
id = id.replace("/", "");
int parsed = Integer.parseInt(id);
}
другое решение, которое я придумал с (тот, который работает для OP), должен отделить /
из цифр в два разных выражения пути, так что ведущий /
не захватывается в фактическом id и не терпит неудачу в разборе
@Path("/method{noop: (/)?}{id: ((?<=/)\d+)?}")
public Response get(@PathParam("id") int id) {}
на {noop: (/)?}
захватывает факультативного /
. И {id: ((?<=/)\d+)?}
использует положительный lookbehind, говоря, что числа (\d+
) допускаются, если и только если есть /
прежде чем он ((?<=/)
). Это необходимо как /
is необязательный. Если мы не использовали это утверждение, то /myMethod123
будет разрешено.
вот полный тестовый случай с помощью Джерси Тест Рамки
public class OptionalParamTest extends JerseyTest {
@Path("optional")
public static class Resource {
@GET
@Path("/method{noop: (/)?}{id: ((?<=/)\d+)?}")
public String get(@PathParam("id") int id) {
return String.valueOf(id);
}
}
@Override
public ResourceConfig configure() {
return new ResourceConfig(Resource.class);
}
@Test
public void should_return_id_1() {
Response response = target("optional/method/1").request().get();
System.out.println("status=" + response.getStatus());
assertEquals("1", response.readEntity(String.class));
}
@Test
public void should_return_id_0_with_no_id() {
Response response = target("optional/method").request().get();
assertEquals(200, response.getStatus());
assertEquals("0", response.readEntity(String.class));
}
@Test
public void should_return_404_with_numbers_and_no_slash() {
Response response = target("optional/method12").request().get();
assertEquals(404, response.getStatus());
}
@Test
public void should_return_404_with_numbers_and_letters() {
Response response = target("optional/method/12b").request().get();
assertEquals(404, response.getStatus());
}
@Test
public void should_return_404_with_only_letters() {
Response response = target("optional/method/ab").request().get();
assertEquals(404, response.getStatus());
}
}
вот зависимость для теста
<dependency>
<groupId>org.glassfish.jersey.test-framework.providers</groupId>
<artifactId>jersey-test-framework-provider-grizzly2</artifactId>
<version>${jersey2.version}</version>
<scope>test</scope>
</dependency>
редактировать
для тестов, было бы лучше использовать коробочную Integer
вместо int
в качестве параметра метода. С первым вы сможете сделать нулевую проверку, вместо того, чтобы получать значение по умолчанию 0
для примитив.
есть путь более простой способ сделать это:
@GET
@Path("myMethod/{id}")
public String myMethod(@PathParam("id") Integer id) {
}
@GET
@Path("myMethod")
public String myMethod() {
return myMethod(null);
}
не требуется сложное регулярное выражение.