在改型2之前,有一种集中处理错误的方法-
new retrofit.RestAdapter.Builder()
.setEndpoint(apiUrl)
.setLogLevel(retrofit.RestAdapter.LogLevel.FULL)
.setErrorHandler(new CustomErrorHandler(ctx))
但是现在在restfit 2中,RestAdapter已经重命名为restfit
,并且没有seterrorhandler()
。是否有一种方法可以使用retrofit.builder()
进行集中式错误处理?
那么,您所要做的就是用您的自定义回调创建一个自定义calladapter
以应对失败情况。repo有一个示例,显示了自定义的calladapter
。您可以在Regetfit/Samples中找到它。
下面的示例显示了自定义calladapter
(不适用于2.2.0之前的版本):
/*
* Copyright (C) 2015 Square, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.example.retrofit;
import java.io.IOException;
import java.lang.annotation.Annotation;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.concurrent.Executor;
import javax.annotation.Nullable;
import retrofit2.Call;
import retrofit2.CallAdapter;
import retrofit2.Callback;
import retrofit2.converter.gson.GsonConverterFactory;
import retrofit2.Response;
import retrofit2.Retrofit;
import retrofit2.http.GET;
/**
* A sample showing a custom {@link CallAdapter} which adapts the built-in {@link Call} to a custom
* version whose callback has more granular methods.
*/
public final class ErrorHandlingAdapter {
/** A callback which offers granular callbacks for various conditions. */
interface MyCallback<T> {
/** Called for [200, 300) responses. */
void success(Response<T> response);
/** Called for 401 responses. */
void unauthenticated(Response<?> response);
/** Called for [400, 500) responses, except 401. */
void clientError(Response<?> response);
/** Called for [500, 600) response. */
void serverError(Response<?> response);
/** Called for network errors while making the call. */
void networkError(IOException e);
/** Called for unexpected errors while making the call. */
void unexpectedError(Throwable t);
}
interface MyCall<T> {
void cancel();
void enqueue(MyCallback<T> callback);
MyCall<T> clone();
// Left as an exercise for the reader...
// TODO MyResponse<T> execute() throws MyHttpException;
}
public static class ErrorHandlingCallAdapterFactory extends CallAdapter.Factory {
@Override public @Nullable CallAdapter<?, ?> get(
Type returnType, Annotation[] annotations, Retrofit retrofit) {
if (getRawType(returnType) != MyCall.class) {
return null;
}
if (!(returnType instanceof ParameterizedType)) {
throw new IllegalStateException(
"MyCall must have generic type (e.g., MyCall<ResponseBody>)");
}
Type responseType = getParameterUpperBound(0, (ParameterizedType) returnType);
Executor callbackExecutor = retrofit.callbackExecutor();
return new ErrorHandlingCallAdapter<>(responseType, callbackExecutor);
}
private static final class ErrorHandlingCallAdapter<R> implements CallAdapter<R, MyCall<R>> {
private final Type responseType;
private final Executor callbackExecutor;
ErrorHandlingCallAdapter(Type responseType, Executor callbackExecutor) {
this.responseType = responseType;
this.callbackExecutor = callbackExecutor;
}
@Override public Type responseType() {
return responseType;
}
@Override public MyCall<R> adapt(Call<R> call) {
return new MyCallAdapter<>(call, callbackExecutor);
}
}
}
/** Adapts a {@link Call} to {@link MyCall}. */
static class MyCallAdapter<T> implements MyCall<T> {
private final Call<T> call;
private final Executor callbackExecutor;
MyCallAdapter(Call<T> call, Executor callbackExecutor) {
this.call = call;
this.callbackExecutor = callbackExecutor;
}
@Override public void cancel() {
call.cancel();
}
@Override public void enqueue(final MyCallback<T> callback) {
call.enqueue(new Callback<T>() {
@Override public void onResponse(Call<T> call, Response<T> response) {
// TODO if 'callbackExecutor' is not null, the 'callback' methods should be executed
// on that executor by submitting a Runnable. This is left as an exercise for the reader.
int code = response.code();
if (code >= 200 && code < 300) {
callback.success(response);
} else if (code == 401) {
callback.unauthenticated(response);
} else if (code >= 400 && code < 500) {
callback.clientError(response);
} else if (code >= 500 && code < 600) {
callback.serverError(response);
} else {
callback.unexpectedError(new RuntimeException("Unexpected response " + response));
}
}
@Override public void onFailure(Call<T> call, Throwable t) {
// TODO if 'callbackExecutor' is not null, the 'callback' methods should be executed
// on that executor by submitting a Runnable. This is left as an exercise for the reader.
if (t instanceof IOException) {
callback.networkError((IOException) t);
} else {
callback.unexpectedError(t);
}
}
});
}
@Override public MyCall<T> clone() {
return new MyCallAdapter<>(call.clone(), callbackExecutor);
}
}
}
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("http://httpbin.org")
.addCallAdapterFactory(new ErrorHandlingCallAdapterFactory())
.addConverterFactory(GsonConverterFactory.create())
.build();
HttpBinService service = retrofit.create(HttpBinService.class);
MyCall<Ip> ip = service.getIp();
ip.enqueue(new MyCallback<Ip>() {
@Override public void success(Response<Ip> response) {
System.out.println("SUCCESS! " + response.body().origin);
}
@Override public void unauthenticated(Response<?> response) {
System.out.println("UNAUTHENTICATED");
}
@Override public void clientError(Response<?> response) {
System.out.println("CLIENT ERROR " + response.code() + " " + response.message());
}
@Override public void serverError(Response<?> response) {
System.out.println("SERVER ERROR " + response.code() + " " + response.message());
}
@Override public void networkError(IOException e) {
System.err.println("NETWORK ERROR " + e.getMessage());
}
@Override public void unexpectedError(Throwable t) {
System.err.println("FATAL ERROR " + t.getMessage());
}
});
但是,使用retrofit每个请求都有其错误处理回调: 我如何在一个地方处理所有错误?
像这样的东西 此外,在这种情况下,我应该停止重试,但如果是网络问题()则保持重试。
我有三种不同的系统。我使用Spring integration来同步所有这些系统中的数据。 系统2将调用服务方法来持久化数据,如果请求有效,则返回响应,否则抛出异常 我需要发送服务方法响应到系统1和系统3,只有当操作成功。调用服务方法后,根据服务方法响应,使用Transformer生成对系统3的请求。在transformer之后,我将请求放入mq队列。 更新的JMS出站代码 如果服务类失败,我需要
场景可能是:我的期望可能是批量10个数据点,我想对{failed 5,pass 5}或其他什么给出响应。 我的逻辑是将批处理拆分为数据元素并进行验证 成功的验证将发送给aggreagtor, 失败的验证将抛出错误并通过错误通道拾取。 收件人列表路由器将错误通道作为输入通道,并连接2个过滤器,目的是过滤某些类型的错误直接发送响应(与用户输入无关的信息-服务器错误等),某些类型的客户端错误将转到聚合器
在Spring integration中,我必须处理动态通道创建,但当我调试应用程序时,我看到不同通道之间的“阻塞”问题。 我知道是一个公共通道,在父上下文中共享,但如何为每个子上下文开发一个完整的独立场景?。公共网关是问题所在吗? 我在Spring integration flow async中看到了post错误处理,但对于每个子级,我都有一个完整的分离环境,我希望利用这些动态分离的优势。这可能
我的服务器为所有请求返回一个基本的JSON结构,如下所示: 其中可以是true或false,数据可以返回许多内容,从到应用程序可能需要的数据。 需要更改/添加到我的改型API调用中的内容是什么?