retrofit的请求头添加从添加方式来说可以分为三种情况,静态、动态和全局。
静态添加
静态添加是用于在定义请求时就明确知道需要添加那些请求头
比如下面的接口需要添加一个apikey的请求头及一个cityname的url请求参数
public interface WeatherService {
@Headers("apikey:b86c2269fe6588bbe3b41924bb2f2da2")
@GET
Call<WeatherWrapper> weather(@Url String url, @Query("cityname") String cityName);
}
如果有多个请求头也可以定义成键值对的样式
@Headers({
"key1:value1",
"key2:value2"
})
上面的两种写法,适用于键和值都明确的情况。在值还不确定的时候我们可以把请求头像请求参数一样写到括号里,加上@Header注解就可以。算是一种狭义上的伪动态写法
@GET
Call<WeatherWrapper> weather(@Header("apikey") String apikey, @Url String url, @Query("cityname") String cityName);
动态添加
动态添加用于请求头是变化的,键和值都需要根据具体的情况才能确定,这时我们会需要@HeaderMap ,用一个map来提供请求头,具体写法如下
@GET
Call<WeatherWrapper> weather(@HeaderMap Map<String, String> headers, @Url String url, @Query("cityname") String cityName);
全局添加
全局添加用于所有请求都需要带上的请求头,如手机型号、APP版本等等,这种显然不适合在每个请求上去添加@Header注解。全局添加需要用到拦截器
okHttpClientBuilder.addInterceptor(new Interceptor() {
@Override
public Response intercept(Chain chain) throws IOException {
Request original = chain.request();
Request.Builder requestBuilder = original.newBuilder()
.header("token", "xxx")
.header("token", "yyy");
Request request = requestBuilder.build();
return chain.proceed(request);
}
});
需要注意的是这里的.header
会导致重写,如果之前在url里定义了一个相同键的请求头,那么在这里会被从新赋值。如果不希望被覆盖,使用.addHeader()
方法替换就可以了
延伸
既然用到了拦截器,添加公共请求头。那能不能一次性给所有请求头添加一个一样的参数?当然可以
如下:给每个请求添加一个access_token
参数
okHttpClientBuilder.addInterceptor(new Interceptor() {
@Override
public Response intercept(Chain chain) throws IOException {
Request originalRequest = chain.request();
HttpUrl originalHttpUrl = originalRequest.url();
HttpUrl url = originalHttpUrl.newBuilder()
.addQueryParameter("access_token", AccessTokenKeeper.readAccessToken(MyApplication.getInstance()).getToken())
.build();
Request request = originalRequest.newBuilder()
.url(url)
.method(originalRequest.method(), originalRequest.body())
.build();
return chain.proceed(request);
}
});