Retrofit2 的baseUrl 真的必须以 /(斜线) 结尾吗?

【Retrofit GitHub】: https://github.com/square/retrofit
版本:2.4.0

Retrofit retrofit = new Retrofit.Builder()
        .baseUrl(baseUrl)
        .addConverterFactory(GsonConverterFactory.create())
        .build();

最近刚好想看看Retrofit源码了,之前看过好多博文都提到注意Retrofit2 的baseUrl 必须以 /(斜线) 结束,不然会抛出一个IllegalArgumentException异常
个人感觉这段话说的不严谨,并不是所有的baseUrl不以 /(斜线) 结尾就会抛出一个IllegalArgumentException异常,这里就需要讲述一下Url的格式了,往往一个Url格式为scheme://host[:port]/path[?query],

  • scheme协议,常用的协议是http、https
  • host 主机地址,可以是域名,也可以是IP地址
  • port 端口 http协议默认端口是:80端口,如果不写默认就是:80端口,https默认端口443端口
  • path 路径 网络资源在服务器中的指定路径
  • query 查询字符串 如果需要从服务器那里查询内容
public static final String API_URL = "https://api.github.com";
public interface GitHub {
    @GET("/repos/{owner}/{repo}/contributors")
    Call<List<Contributor>> contributors(
        @Path("owner") String owner,
        @Path("repo") String repo);
  }

现在以https://api.github.com/repos/{owner}/{repo}/contributors这个接口为例,此处的

  • https为scheme,
  • api.github.com为host,此处端口没写(https默认443),
  • repos/{owner}/{repo}/contributors为path,

关于Retrofit中的baseUrl并没有强制怎么写,我可以写成https://api.github.com也可以写成 https://api.github.com/repos/,区别在哪呢?下面听我仔细说:

  1. https://api.github.com的格式可以看成scheme://host[:port](此种类型是不是以 /(斜线) 结尾都可以,均不会抛出IllegalArgumentException异常);
  2. https://api.github.com/repos/的格式可以看成scheme://host[:port]/path(此种类型必须以/(斜线) 结尾,否则会抛出IllegalArgumentException异常).

下面关于baseUrl的问题来看看Retrofit.java中的源码:

public Builder baseUrl(String baseUrl) {
     checkNotNull(baseUrl, "baseUrl == null");
     HttpUrl httpUrl = HttpUrl.parse(baseUrl);
     if (httpUrl == null) {
       throw new IllegalArgumentException("Illegal URL: " + baseUrl);
     }
     return baseUrl(httpUrl);
 }
​
public Builder baseUrl(HttpUrl baseUrl) {
     checkNotNull(baseUrl, "baseUrl == null");
     List<String> pathSegments = baseUrl.pathSegments();
     if (!"".equals(pathSegments.get(pathSegments.size() - 1))) {
       throw new IllegalArgumentException("baseUrl must end in /: " + baseUrl);
     }
     this.baseUrl = baseUrl;
     return this;
 }

可以看到第二个baseUrl方法中会在一定场景下抛出IllegalArgumentException异常,但是在第一个baseUrl方法中HttpUrl.parse(baseUrl)会对baseUrl做处理转换成对应的HttpUrl,区别就在这里了,对于场景1中https://api.github.com会自动转换成https://api.github.com/,如下图:

场景1.png

而场景2中自然不会做处理,若场景2中写成https://api.github.com/repos未以 /(斜线) 结尾,此时HttpUrl.parse(baseUrl)也不会对此做处理,那么就会抛出IllegalArgumentException异常。如下图:

场景2.png

抛异常.png

注意:建议BaseUrl以/(斜线) 结尾。scheme://host[:port]/path类型的baseUrl必须以/(斜线) 结尾。

路径整合规则:

BaseUrl Path形式 Path对应的值 最后Url
http://host:port/a/b/ 绝对路径 /apath http://host:port/apath
http://host:port/a/b/ 相对路径 apath http://host:port/a/b/apath
http://host:port/a/b/ 完整路径 http://host:port/aa/apath http://host:port/aa/apath
  • Path中提供的url是绝对路径,即以 / 开头,则请求的url为baseUrl的主机部分(或加上端口);
  • Path对应的值Path中提供的url是相对路径,即不以 / 开头,则请求的url为baseUrl;
  • Path对应的值Path中提供的url是完整路径,则url将作为最终请求的url。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,859评论 18 139
  • # Python 资源大全中文版 我想很多程序员应该记得 GitHub 上有一个 Awesome - XXX 系列...
    aimaile阅读 26,553评论 6 427
  • afinalAfinal是一个android的ioc,orm框架 https://github.com/yangf...
    passiontim阅读 15,489评论 2 45
  • 那是十几年前的事了。舅舅家的孩子刚在太原参加工作。我也师范刚毕业,暑假里到舅舅家玩。表哥顺便请我到太原玩,我很高兴...
    海鱼缘阅读 344评论 5 3
  • 1 那天,正当深夜零时,她忙完手中的工作,在睡梦中几近徘徊,意识飘忽。 所以当电话的震动与铃声响起,她也能迷迷糊糊...
    目觉阅读 731评论 1 22