问题描述
我正在玩 Jersey 2.21
我想知道是否有可能存在或不存在的可选参数请求服务器。
I'm playing around with Jersey 2.21
and I'd like to know if it's possible to have an "optional" param which can, or not, be present in the request made to the server.
我想成功访问这两种方法:
I want to successfully access this two methods:
http://localhost:8080/my_domain/rest/api/myMethod/1
http://localhost:8080/my_domain/rest/api/myMethod
正如你所看到的,我正在尝试制作整数( id
)参数一个可选的。
As you can see, I'm trying to make the integer (id
) param an optional one.
我已声明 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/
但这不起作用,我不明白为什么。它会抛出 404 Not Found
错误:
but this won't work and I don't understand why. It throws a 404 Not Found
error:
http://localhost:8080/my_domain/rest/api/myMethod
你能指出我的正确方向吗?出来吗?我不喜欢斜线在我所有的REST方法调用中都是强制性的,并且如果可能的话就想压制它。
Can you point me in the right direction to work this out? I don't like the slash being mandatory on all my REST method calls and would like to suppress it if possible.
推荐答案
所以在一些涉及的一些答案之后,问题在于使用这个
So after some dabbling around with some of the answers in Optional @PathParam in Jax-RS, the problem is that using this
@Path("/myMethod{id: (/\\d+)?}")
public Response get(@PathParam("id") int id) {}
导致 /
将在捕获组中。因此,当Jersey尝试解析 / 1
时,它将获得一个异常并发送一个404.我们可以使用一个String,但随后它变得丑陋,因为我们需要摆脱领先的 /
和自己解析它。
causes the /
to be in the capture group. So when Jersey tries to parse /1
it will get an exception and send a 404. We could use a String, but then it gets ugly, as we need to get rid of the leading /
and parse it ourselves.
@Path("/myMethod{id: (/\\d+)?}")
public Response get(@PathParam("id") String id) {
id = id.replace("/", "");
int parsed = Integer.parseInt(id);
}
我提出的另一个解决方案(适用于OP的解决方案) ,是将 /
与数字分成两个不同的路径表达式,这样就不会捕获前导 /
实际的id并且在解析时不会失败
The other solution I came up with (the one that works for the OP), is to separate the /
from the digits into two different path expressions, so that the leading /
is not captured in the actual id and doesn't fail in parsing
@Path("/method{noop: (/)?}{id: ((?<=/)\\d+)?}")
public Response get(@PathParam("id") int id) {}
{noop:(/)?}
捕获可选的 /
。 {id :((?< = /)\\d +)?}
使用,说数字( \\d + /
时才允许$ c>)((?< = /)
)。这是必要的,因为 /
是可选的。如果我们没有使用这个断言,则允许 / myMethod123
。
The {noop: (/)?}
captures the optional /
. And the {id: ((?<=/)\\d+)?}
uses a positive lookbehind, saying that the numbers (\\d+
) are allowed if and only if there is a /
before it ((?<=/)
). This is necessary as the /
is optional. If we didn't use this assertion, then /myMethod123
would be allowed.
这是一个完整的测试用例使用
Here is a complete test case using Jersey Test Framework
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
。
EDIT
For the tests, it would be better to use a boxed Integer
instead of an int
as the method parameter. With the former you would be able to do a null check, instead of receiving the default 0
for the primitive.
这篇关于使用Jersey 2.21在REST API请求中的可选参数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!