我有一个Rest端点类,如下所示:
@Path("/sports")
public interface SportsEndpoint {
@GET
List<Player> getPlayersOfSports(@QueryParam("sportId") String sportId, @QueryParam("sportName") String sportName);
@GET
List<Player> getPlayersOfSports(@QueryParam("sportId") String sportId, @QueryParam("sportName") String sportName, @QueryParam("country") String country);
}
正如您所看到的,我有两个GET
方法具有几乎相同的签名,但第二种方法需要额外的QueryParam
。
我尝试使用url访问这些端点:
http://localhost:8080/rest/api/sports?sportId=100&sportName=badminton
http://localhost:8080/rest/api/sports?sportId=100&sportName=badminton&country=japan
这两个网址都在解析使用第一个方法签名。理想情况下,我期望对于第一个url,将调用第一个方法签名,对于第二个url,将调用第二个方法(具有3个查询参数的方法)。 但看起来在这两种情况下第一种方法都被调用了。
我知道Rest资源是由路径唯一标识的,而不是查询参数。但是,即使查询参数的数量不同,其余端点也不会被唯一标识,这也是正确的吗? 有人能指出一些规范/文章/文档,在设计rest api端点时我能理解多态吗?
仅供参考:我正在使用RestEasy。
答案 0 :(得分:1)
据我所知,Java rest API是Jax-R的实现,所以你可以阅读Jax-Rs specification,
Jax-Rs映射资源方法的路径。资源方法必须具有唯一的路径。查询参数不被视为路径的一部分。资源方法是使用请求方法指示符注释的资源类的方法。当两个方法共享相同的指示符和路径时,规范不会确定应该发生什么,但大多数实现只使用其中一个并且不会报告错误。
(符合URL specs。)
这意味着您无法使用重载。
允许继承。来自Jax-Rs规范:
JAX-RS注释可用于超类或实现接口的方法和方法参数。这样的注释由相应的子类或实现类方法继承,前提是该方法及其参数没有自己的任何JAX-RS注释。超类上的注释优先于已实现接口上的注释。如果子类或实现方法具有任何JAX-RS注释,则忽略超类或接口方法上的所有注释。 E.g:
答案 1 :(得分:1)
QueryParams是可选参数
你正确地说我知道Rest资源是唯一的 由路径而不是查询参数确定
并回答你的问题,
是的,即使查询参数的数量不同,其余的 端点不会被唯一标识?因为它是由 路径不是查询参数。
如果您希望根据querystring
中的输入数量调用您的方法
最好创建一个方法,根据您的要求获取所有queryparam
,并根据提供的输入数量,分别调用每个方法。
所以在你的情况下,它可以改写如下: -
@Path("/sports")
public interface SportsEndpoint {
@GET
List<Player> getPlayers(@QueryParam("sportId") String sportId, @QueryParam("sportName") String sportName , @QueryParam("country") String country){
if(sportId ! =null && sportName!=null)
{
getPlayersOfSports(sportId,sportName);
}
else if (sportId ! =null && sportName!=null && country!=null)
{
getPlayersOfSports(sportId,sportName,country);
}
}
并且
然后在业务逻辑中定义方法重载 将有2个重载方法,这些方法因没有参数而异。 这样就可以实现多态性。