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

查看:25
本文介绍了使用 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 如下:

I've declared myMethod as follows:

@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.

推荐答案

所以在对 Optional @ 中的一些答案进行了一些尝试之后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.我们可以使用一个字符串,但它会变得丑陋,因为我们需要摆脱领先的 / 自己解析.

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+)?} 使用 positive lookbehind,表示当且仅当存在 时才允许使用数字 (\d+)/ 在它之前((?<=/)).这是必要的,因为 / 是可选的.如果我们不使用这个断言,那么 /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.

这是一个完整的测试用例,使用 Jersey 测试框架

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天全站免登陆