当前位置: 首页 > 面试题库 >

使用Jersey 2.21的REST API请求中的可选参数

归俊捷
2023-03-14
问题内容

我在玩Jersey 2.21,我想知道是否有可能在向服务器发出的请求中包含“可选”参数。

我想成功访问这两种方法:

http://localhost:8080/my_domain/rest/api/myMethod/1
http://localhost:8080/my_domain/rest/api/myMethod

如您所见,我正在尝试使integer(id)参数成为可选参数。

我声明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错误:

http://localhost:8080/my_domain/rest/api/myMethod

您能为我指出正确的方向进行解决吗?我不希望在所有REST方法调用中都必须使用斜杠,并且希望在可能的情况下取消斜杠。


问题答案:

因此,在仔细研究了Jax-RS的Optional@PathParam中的一些答案之后,问题是使用此方法

@Path("/myMethod{id: (/\\d+)?}") 
public Response get(@PathParam("id") int id) {}

使/处于捕获组中。因此,当Jersey尝试解析时/1,它将获得一个异常并发送404。我们可以使用String,但是随后它变得很丑陋,因为我们需要摆脱前导/ 自行解析它。

@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+)?}使用正号,表示\\d+当且仅当前面有一个/(?<=/))时才允许使用数字()。这是必需的,因为/是可选的。如果我们不使用此断言,/myMethod123则将被允许。

这是使用Jersey测试框架的完整测试案例

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原始图元的默认值。



 类似资料:
  • 我创建了一个带有参数的API,如下所示: 我在body->表单数据中传递了。 然后我在《邮递员》上得到了这样一条消息: 有人知道为什么会有这个消息吗?我们如何在Rest API请求中传递一个映射作为参数?我们怎样才能通过邮递员传递地图?

  • 我正尝试在spring创建一个GETendpoint,带有多个可选的请求参数,以便从mongo(思考和查询)查询数据并返回。 我目前所拥有的-MyController.java 这是我的服务层- 如果还不是很明显的话,我会努力使用booleanBuilder构建谓词并将其传递给存储库层。映射中的键将包含QItems required字段名的名称。 另外,如何解析GET all users和GET

  • 当没有响应返回时,我需要超时我的RESTAPI。例如,当我发出请求时,如果返回响应需要5秒钟以上,则超时。 为了实现这一点,我选择了使用Hystrix的断路器。但我不确定这是否是解决此问题的正确方法,如果一切都好,是否应该对Hystrix进行更多配置? 我当前的实现看起来像, 主类 RestController 应用程序属性 当超时时,它抛出一个HystrixRunTimeException,并由

  • 我有一个客房服务,当我提出要求时,它会返回房间的详细信息http://localhost:8082/room/search/byRoomChar 现在我想从预订服务请求这个@GetMapping,因为这是用户将使用http://localhost:8081/booking/search/byRoomChar. 房间实体代码: 房间存储库代码: 但是,这不起作用,因为当从预订服务调用getmappi

  • 尝试使用PUT请求更新数据。但是,数据没有更新和返回邮递员中的以前的数据。 邮递员提出要求: 邮递员回复: 我也尝试过使用findByIdAndUpdate。没有得到结果。任何帮助都将不胜感激。 控制器: 路由器:

  • 问题内容: 我想在过滤器/ servlet中拦截请求,并向其中添加一些参数。但是,该请求不会公开’setParameter’方法,并且该参数映射在被操纵时会抛出错误,表明已被锁定。有没有其他我可以尝试的方法? 问题答案: 子类化并覆盖方法。该类的描述为: 提供HttpServletRequest接口的便捷实现,希望希望使请求适应Servlet的开发人员可以将其子类化。 在过滤器中,将请求包装在子类