37

我们能否为同一个 REST 方法提供多个@Path注释,即执行的方法是相同的,但它是在访问多个 URL 时执行的?

例如:我想在和上运行该searchNames()方法。http://a/b/chttp://a/b

4

4 回答 4

50

@Path一个方法不能有多个注释。它会导致“重复注释”语法错误。

但是,有很多方法可以有效地将两条路径映射到一个方法。

@Path 注解中的正则表达式

JAX-RS 中的@Path注释接受参数,可以使用正则表达式限制其值。

这个注释:

@Path("a/{parameter: path1|path2}")

将使对/a/path1和的请求都可以访问该方法/a/path2。如果您需要使用子路径,请转义斜杠:{a:path1\\/subPath1|path2\\/subPath2}

使用重定向状态代码提供响应

或者,您可以设置重定向。这是在 Jersey(JAX-RS 的参考实现)中通过定义另一个子资源来实现的方法。这只是一个示例,如果您更喜欢处理重定向的不同方式,请随意使用它。

@Path("basepath")
public class YourBaseResource {

  //this gets injected after the class is instantiated by Jersey    
  @Context
  UriInfo uriInfo; 

  @Path("a/b")
  @GET
  public Responce method1(){
    return Response.ok("blah blah").build();
  }

  @Path("a/b/c")
  @GET
  public Response method2(){
    UriBuilder addressBuilder = uriInfo.getBaseUriBuilder();
    addressBuilder.path("a/b");
    return Response.seeOther(addressBuilder.build()).build();
  }

}

使用 servlet 过滤器重写 URL

如果您经常需要这样的功能,我建议使用 servlet 过滤器拦截传入的请求并动态重写路径。这应该可以帮助您将所有重定向保存在一个地方。理想情况下,您可以使用现成的库。UrlRewriteFilter可以做到这一点,只要你对 BSD 许可证没问题(查看他们的谷歌代码网站了解详细信息)

另一种选择是使用在 Java 应用程序前面设置的代理来处理此问题。您可以设置一个 Apache 服务器来提供基本的缓存和重写规则,而不会使您的 Java 代码复杂化。

于 2013-06-08T17:52:04.170 回答
21

正如汤姆的回答@Path中所解释的,您不能在一个方法上使用多个注释,因为您将error: duplicate annotation在编译时遇到。

我认为解决这个问题的最简单方法是使用方法重载:

@Path("{foo}")
public Response rest(@PathParam("foo") final String foo) {
    return this.rest(foo, "");
}

@Path("{foo}/{bar}")
public Response rest(@PathParam("foo") final String foo,
                     @PathParam("bar") final String bar) {
    return Response.ok(foo + " " + bar).build();
}

如果遇到多个重载方法具有签名的情况,您还可以使用更多不同的方法名称。

于 2013-10-29T14:08:09.293 回答
12

您的特定示例的另一个解决方案:

让我们假设:

  • /a用于资源类
  • /b/c并且/b是方法的路径

因为完整路径如下所示:

<protocol><host><port><app><url-pattern><resource-path><method-path>.

使用可选参数

@Path("/b{c : (/c)?}")
public Response searchNames(@PathParam("c") String val) {
    ...
}

上面的示例适用于所有示例,例如:

  • /b
  • /b/
  • /b/c
  • /b/c/

但是当c提供时,val/c(它有一个/之前)。

如果你想解决上面的问题(避免 Java 解析),你需要一些更复杂的东西:

@Path("/b{slash : (/)?}{c:((?<=/).*)?}")

它将仅返回c(不/c)第 3 个要点,但对于第 4要点,它将返回c/必须在 Java 中解析的内容。

但是对于您的情况(“执行的方法是相同的”),不必担心解析,因为您没有不同的操作。

于 2015-12-29T08:05:35.553 回答
0

如果您使用的是 Spring,请尝试

@RequestMapping(value = {"/def", "/abc"}, method = RequestMethod.POST)

这对 /abc 和 /def 都有效。

sSaroj 2017年11 月 17 日在 10:13

于 2020-11-19T17:24:32.707 回答