Nit*_*mer 15 java annotations header retrofit retrofit2
我的Retrofit 2(2.0.2当前)客户端需要为请求添加自定义标头.
我正在使用an Interceptor将这些标头添加到所有请求中:
OkHttpClient httpClient = new OkHttpClient();
httpClient.networkInterceptors().add(new Interceptor() {
@Override
public Response intercept(Chain chain) throws IOException {
final Request request = chain.request().newBuilder()
.addHeader("CUSTOM_HEADER_NAME_1", "CUSTOM_HEADER_VALUE_1")
.addHeader("CUSTOM_HEADER_NAME_2", "CUSTOM_HEADER_VALUE_2")
...
.addHeader("CUSTOM_HEADER_NAME_N", "CUSTOM_HEADER_VALUE_N")
.build();
return chain.proceed(request);
}
});
Retrofit retrofitClient = new Retrofit.Builder()
.baseUrl(baseUrl)
.client(httpClient)
.build();
Run Code Online (Sandbox Code Playgroud)
我总是想添加一些标头,但是我只需要根据特定端点的要求添加一些标头,例如用户是否需要进行身份验证.
我希望能够在api级别控制它,例如使用注释,例如:
public interface MyApi {
@NO_AUTH
@POST("register")
Call<RegisterResponse> register(@Body RegisterRequest data);
@GET("user/{userId}")
Call<GetUserResponse> getUser(@Path("userId") String userId);
}
Run Code Online (Sandbox Code Playgroud)
发送请求时register无需添加身份验证令牌,但缺少@NO_AUTH注释的请求将具有令牌头.
根据我的理解,Retrofit 2不支持自定义注释,虽然我发现使用Retrofit 2的自定义注释的这种解决方法,但它看起来有点太多了.
我想避免每个请求传递这些标头的需要,例如:
public interface MyApi {
@POST("register")
Call<RegisterResponse> register(@Body RegisterRequest data);
@GET("user/{userId}")
Call<GetUserResponse> getUser(@Header("AuthToken") String token, @Path("userId") String userId);
}
Run Code Online (Sandbox Code Playgroud)
每次调用方法而不是在拦截器中执行此操作时都会感到多余(因为我可以静态访问标头值).
我只是需要在我的Interceptor.intercept实现中知道这个特定的请求是否应该有一个特定的标题.
知道如何让这个工作吗?
我更喜欢通用解决方案而不仅仅是auth令牌案例,但也欢迎特定的解决方案.谢谢
Nit*_*mer 29
我提出了一个非常简单和优雅(在我看来)解决我的问题的方法,可能还有其他方案.
我使用Headers注释来传递我的自定义注释,并且由于OkHttp要求它们遵循Name: Value格式,我决定我的格式为:@: ANNOTATION_NAME.
所以基本上:
public interface MyApi {
@POST("register")
@HEADERS("@: NoAuth")
Call<RegisterResponse> register(@Body RegisterRequest data);
@GET("user/{userId}")
Call<GetUserResponse> getUser(@Path("userId") String userId);
}
Run Code Online (Sandbox Code Playgroud)
然后我可以拦截请求,检查我是否有一个带有名称的注释@.如果是这样,我获取值并从请求中删除标头.
即使您想要多个"自定义注释",这也很有效:
@HEADERS({
"@: NoAuth",
"@: LogResponseCode"
})
Run Code Online (Sandbox Code Playgroud)
以下是如何提取所有这些"自定义注释"并将其从请求中删除:
new OkHttpClient.Builder().addNetworkInterceptor(new Interceptor() {
@Override
public okhttp3.Response intercept(Chain chain) throws IOException {
Request request = chain.request();
List<String> customAnnotations = request.headers().values("@");
// do something with the "custom annotations"
request = request.newBuilder().removeHeader("@").build();
return chain.proceed(request);
}
});
Run Code Online (Sandbox Code Playgroud)
也许你可以通过像这样创建不同的 Retrofit 对象工厂方法来做到这一点。
public class RestClient {
public static <S> S createService(Class<S> serviceClass) {
OkHttpClient.Builder httpClient = new OkHttpClient.Builder();
OkHttpClient client = httpClient.build();
Retrofit retrofit = new Retrofit.Builder().baseUrl(APIConfig.BASE_URL)
.client(client)
.build();
return retrofit.create(serviceClass);
}
public static <S> S createServiceWithAuth(Class<S> serviceClass) {
Interceptor interceptor = new Interceptor() {
@Override
public Response intercept(Chain chain) throws IOException {
final Request request = chain.request().newBuilder()
.addHeader("CUSTOM_HEADER_NAME_1", "CUSTOM_HEADER_VALUE_1")
.addHeader("CUSTOM_HEADER_NAME_2", "CUSTOM_HEADER_VALUE_2")
.build();
return chain.proceed(request);
}
};
OkHttpClient.Builder httpClient = new OkHttpClient.Builder();
httpClient.addInterceptor(interceptor);
OkHttpClient client = httpClient.build();
Retrofit retrofit = new Retrofit.Builder().baseUrl(APIConfig.BASE_URL)
.client(client)
.build();
return retrofit.create(serviceClass);
}
}
Run Code Online (Sandbox Code Playgroud)
如果你想在没有头认证的情况下调用 api,你可以调用 createService 方法:
YourApi api = RestClient.createService(YourApi.class);
Run Code Online (Sandbox Code Playgroud)
如果要使用身份验证调用 api,请使用 createServiceWithAuth 方法:
YourApiWithAuth api = RestClient.createServiceWithAuth(YourApiWithAuth.class);
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
21639 次 |
| 最近记录: |