使用Jersey 2.21在REST API请求中的可选参数 [英] Optional params in REST API request using Jersey 2.21

查看:102
本文介绍了使用Jersey 2.21在REST API请求中的可选参数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在玩 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.

推荐答案

所以在一些涉及 Jax-RS中的可选@PathParam 的一些答案之后,问题在于使用这个

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请求中的可选参数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆