【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/
,区别在哪呢?下面听我仔细说:
-
https://api.github.com
的格式可以看成scheme://host[:port]
(此种类型是不是以 /(斜线) 结尾都可以,均不会抛出IllegalArgumentException
异常); -
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/
,如下图:
而场景2中自然不会做处理,若场景2中写成https://api.github.com/repos
未以 /(斜线) 结尾,此时HttpUrl.parse(baseUrl)
也不会对此做处理,那么就会抛出IllegalArgumentException
异常。如下图:
注意:建议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。