我正在使用Reform在Spring启动应用程序中执行HTTP调用。
每当API调用被执行时,我都试图找到一种让我的自定义代码运行的方法。
在我的自定义代码的上下文中,我需要知道哪个方法调用了这个API调用。
我能想出三个解决方案,但每一个都有问题。
让我们使用下面的示例代码,假设我有
public interface MyClient {
@GET("myurl")
Call<MyDto> getInfo();
}
@Bean
public MyClient getMyClient() {
Retrofit myRetrofit = new Retrofit.Builder()
.baseUrl(myBaseUrl)
.client(oauthOkHttpClient())
.addConverterFactory(jacksonConverterFactory)
.build();
return myRetrofit.create(MyClient.class);
}
Call<MyDto> apiCall = myClient.getInfo();
apiCall.clone().execute()
我希望我的代码在调用execute后运行。
三种解决方案:
1.使用@Aspect
这有可能让我访问调用方法并运行自定义逻辑。
问题是,虽然接口是一个Spring组件,但执行调用的代码不是。
还有办法让这样的东西发挥作用吗?
@Aspect
@Order(3)
@GlobalComponent
public class MyAspect {
@Around("execution(* retrofit2.Call.execute())(..))")
public void runLogic(ProceedingJoinPoint joinPoint) {
do(...)
}
}
2.实现okhttp3拦截器
由于myReform使用oauthOkHttpClient(请参阅构建器(,因此在进行调用时会激活拦截器。
这里的问题是,我在拦截器中只有okhttp3响应,我看不出谁是调用方法和类(MyClient.getInfo(
3.提供回电
apiCall.enqueue(new Callback<>() {
@Override
public void onResponse(Call<MyDto> call, Response<MyDto> response) {}
@Override
public void onFailure(Call<MyDto> call, Throwable t) {}
});
is选项的问题与第二个选项类似。找不到获取调用程序的方法。
有什么想法吗?
我找到了一种方法。
您需要创建自己的CallAdapter.Factory,并在创建客户端时将其传递给改装生成器。
这里有一个例子:
Retrofit accountsRetrofit = new Retrofit.Builder()
.baseUrl(baseUrl)
.client(client)
.addConverterFactory(converterFactory)
.addCallAdapterFactory(new MyAdapterFactory())
.build();
定制工厂:
public class MyAdapterFactory extends CallAdapter.Factory {
@Nullable
@Override
public CallAdapter<?, ?> get(@NotNull Type returnType, @NotNull Annotation[] annotations, Retrofit retrofit) {
CallAdapter<?, ?> nextCallAdapter = retrofit.nextCallAdapter(this, returnType, annotations);
return new MonitorCallAdapter<>(nextCallAdapter);
}
private static final class MonitorCallAdapter<R, T> implements CallAdapter<R, T> {
private final CallAdapter<?, ?> nextCallAdapter;
private MonitorCallAdapter(CallAdapter<?, ?> nextCallAdapter) {
this.nextCallAdapter = nextCallAdapter;
}
@NotNull
@Override
public Type responseType() {
return nextCallAdapter.responseType();
}
@NotNull
@Override
public T adapt(@NotNull Call<R> call) {
return (T) nextCallAdapter.adapt(new MonitoredCall(call));
}
}
private static final class MonitoredCall<T> implements Call<T> {
private final Call<T> wrappedCall;
private MonitoredCall(Call<T> call) {
this.wrappedCall = call;
}
@NotNull
@Override
public Response<T> execute() throws IOException {
////PUT_CUSTOM_LOGIC_HERE
return wrappedCall.execute();
}
@Override
public void enqueue(@NotNull Callback<T> callback) {
wrappedCall.enqueue(new Callback<T>() {
@Override
public void onResponse(@NotNull Call<T> call, @NotNull Response<T> response) {
callback.onResponse(call, response);
}
@Override
public void onFailure(@NotNull Call<T> call, @NotNull Throwable t) {
callback.onFailure(call, t);
}
});
}
@Override
public boolean isExecuted() {
return wrappedCall.isExecuted();
}
@Override
public void cancel() {
wrappedCall.cancel();
}
@Override
public boolean isCanceled() {
return wrappedCall.isCanceled();
}
@Override
public Call<T> clone() {
return new MonitoredCall<T>(wrappedCall.clone());
}
@Override
public Request request() {
return wrappedCall.request();
}
}
}