为什么Retrofit会向所有网址添加尾部斜杠?

时间:2014-12-04 21:12:35

标签: android retrofit

编辑问题并提供更多详细信息:

我理解在Retrofit中使用服务接口。我想调用这样的URL: http://a.com/b/c(稍后使用服务接口附加查询参数)。

我的局限是:

  1. 不能使用/ b / c作为服务接口的一部分(作为路径参数)。我需要它作为基本网址的一部分。我详细说明了以下原因。

  2. 无法能够对http://a.com/b/c/?key=val进行调用。我需要的是http://a.com/b/c?key=val(“c”之后的斜杠是为我的API创建问题)。更多详情如下。

  3. 我的服务器API经常更改,我在客户端使用Retrofit遇到了麻烦。主要问题是我们不能将动态值(非最终)传递给路径参数的@GET或@POST注释(就像查询参数一样)。例如,即使API更改时路径参数的数量也会发生变化。每次API更改时,我们都无法承受不同的接口。

    一种解决方法是通过形成完整的URL,即带有Base_Url + Path_Parameters的端点。

    但我想知道为什么Retrofit会强制在基本网址上添加一个斜杠(“/”):

            String API_URL = "https://api.github.com/repos/square/retrofit/contributors";
            if (API_URL.endsWith("/")) {
                API_URL = API_URL.substring(0, API_URL.length() - 1);
            }
            System.out.println(API_URL);   //prints without trailing "/"
    
            RestAdapter restAdapter = new RestAdapter.Builder()
            .setEndpoint(API_URL)
            .build();
    

    内部通过Retrofit将API_URL重置为https://api.github.com/repos/square/retrofit/contributors/(通过记录请求确认)

    一种解决方法是手动添加“?”最后是为了防止添加“/”:https://api.github.com/repos/square/retrofit/contributors

    很遗憾,我们的API不会接受此类请求。

    1. 为什么Retrofit会强制这种行为?
    2. 对于像我这样不想要拖尾斜线的人有解决方案吗?
    3. 我们可以将变量参数(非最终)传递给Retrofit @GET或@POST注释吗?

1 个答案:

答案 0 :(得分:2)

您需要将基本网址传递给setEndpoint(...)并在服务界面中定义/repos/...

快速演示:

class Contributor {

    String login;

    @Override
    public String toString() {
        return String.format("{login='%s'}", this.login);
    }
}

interface GitHubService {

    @GET("/repos/{organization}/{repository}/contributors")
    List<Contributor> getContributors(@Path("organization") String organization,
                                      @Path("repository") String repository);
}

然后在您的代码中,您执行以下操作:

GitHubService service = new RestAdapter.Builder()
        .setEndpoint("https://api.github.com")
        .build()
        .create(GitHubService.class);

List<Contributor> contributors = service.getContributors("square", "retrofit");
System.out.println(contributors);

将打印:

[{login='JakeWharton'}, {login='pforhan'}, {login='edenman'}, {login='eburke'}, {login='swankjesse'}, {login='dnkoutso'}, {login='loganj'}, {login='rcdickerson'}, {login='rjrjr'}, {login='kryali'}, {login='holmes'}, {login='adriancole'}, {login='swanson'}, {login='crazybob'}, {login='danrice-square'}, {login='Turbo87'}, {login='ransombriggs'}, {login='jjNford'}, {login='icastell'}, {login='codebutler'}, {login='koalahamlet'}, {login='austynmahoney'}, {login='mironov-nsk'}, {login='kaiwaldron'}, {login='matthewmichihara'}, {login='nbauernfeind'}, {login='hongrich'}, {login='thuss'}, {login='xian'}, {login='jacobtabak'}]
  

我们可以将变量参数(非最终)传递给Retrofit @GET或@POST注释吗?

不,必须将(Java)注释中的值声明为final。但是,您可以 定义变量路径,正如我在演示中所示。

编辑:

注意杰克在评论中的评论:

  

值得注意的是,原始问题中链接的代码处理了当你传递https://api.github.com/(注意尾部斜杠)并且它加入/ repos / ...时的情况(注意前导斜杠)。 Retrofit强制对相对URL注释参数进行前导斜杠,以便在API网址上有一个尾部斜杠时进行减少。