Java 改进错误处理

Java 改进错误处理,java,android,error-handling,retrofit,Java,Android,Error Handling,Retrofit,我将我的改装代码包装在一个类中,如下所示。如果从我发布的代码中看不清楚,那么它是在与OAuth的restful服务交互 做错误处理的好方法是什么?REST服务器返回json格式的错误消息。我想通过抛出我的类中的一些异常来处理这个消息。我正在尝试做下面的事情。但是这个设计好吗?混合回调和异常抛出是一个好主意吗?有更好的办法吗 通过下面的方法,我可以从自定义异常中获取i18l消息,并将它们发送给用户 public class RestClient implements IRestClient {

我将我的改装代码包装在一个类中,如下所示。如果从我发布的代码中看不清楚,那么它是在与OAuth的restful服务交互

做错误处理的好方法是什么?REST服务器返回json格式的错误消息。我想通过抛出我的类中的一些异常来处理这个消息。我正在尝试做下面的事情。但是这个设计好吗?混合回调和异常抛出是一个好主意吗?有更好的办法吗

通过下面的方法,我可以从自定义异常中获取i18l消息,并将它们发送给用户

public class RestClient implements IRestClient {
    private IRestAPI api;

    /**
     *
     * @param accessToken
     */
    public RestClient(final String accessToken)
    {
        RequestInterceptor requestInterceptor = new RequestInterceptor()
        {
            @Override
            public void intercept(RequestFacade request) {
                request.addHeader("Authorization", "Bearer " + accessToken);
            }
        };

        RestAdapter restAdapter = new RestAdapter.Builder()
                .setEndpoint(Config.ENDPOINT)
                .setRequestInterceptor(requestInterceptor)
                .build();
        api = restAdapter.create(IRestAPI.class);
    }

    @Override
    public void requestSomething(final Callback callback) {
        api.getSomething(new Callback<Something>() {
            @Override
            public void success(Something something, Response response) {
                callback.success(something, response);
            }

            @Override
            public void failure(RetrofitError error) {
                if(error.getMessage().getId().euqals(ACCESS_TOKEN_EXPIRED))
                {
                    throw new AccessTokenExpired();
                }
                else if(error.getMessage().getId().euqals(USER_NOT_FOUND))
                {
                    throw new UsernamePasswordNotFound();
                }
                else // something else happened...
                {
                    throw error;
                }
            }
        });
    }

    @Override
    public void deleteSomething(final Callback callback) {
        api.deleteSomething(new Callback<Something>() {
            @Override
            public void success(Something something, Response response) {
                callback.success(something, response);
            }

            @Override
            public void failure(RetrofitError error) {
                if(error.getMessage().getId().euqals(SOMETHING_NOT_FOUND))
                {
                    ...
                    ...
                    Different exceptions
                }
                ...
            }
        });
    }

}
公共类RestClient实现IRestClient{
私有IRestAPI api;
/**
*
*@param accessToken
*/
公共RestClient(最终字符串accessToken)
{
RequestInterceptor RequestInterceptor=新的RequestInterceptor()
{
@凌驾
公共无效截获(请求门面请求){
request.addHeader(“授权”、“承载人”+accessToken);
}
};
RestAdapter RestAdapter=new RestAdapter.Builder()
.setEndpoint(Config.ENDPOINT)
.setRequestInterceptor(requestInterceptor)
.build();
api=restAdapter.create(IRestAPI.class);
}
@凌驾
public void requestSomething(最终回调){
getSomething(newcallback(){
@凌驾
公开无效的成功(某事、回应){
成功(某事、回应);
}
@凌驾
公共无效失败(错误){
if(error.getMessage().getId().euqals(访问令牌已过期))
{
抛出新的AccessTokenExpired();
}
else if(error.getMessage().getId().euqals(未找到用户))
{
抛出新用户名PasswordNotFound();
}
其他//发生了其他事情。。。
{
投掷误差;
}
}
});
}
@凌驾
公共void deleteSomething(最终回调){
deleteSomething(新回调(){
@凌驾
公开无效的成功(某事、回应){
成功(某事、回应);
}
@凌驾
公共无效失败(错误){
if(error.getMessage().getId().euqals(找不到的内容))
{
...
...
不同的例外
}
...
}
});
}
}

当然,我必须用一个成功的方法创建自己的回调接口。

当您构建
重新适应程序时,您可以提供一个映射到自定义异常的调用,它绕过对任何4xx/5xx的
回调中
失败的调用。作为一个真正做作的例子:

public class Scratch {
    public static void main(String[] args) {
        Endpoints e = new RestAdapter.Builder()
                .setEndpoint("http://google.com")
                .setLogLevel(RestAdapter.LogLevel.FULL)
                .setErrorHandler(new ErrorHandler() {
                    @Override
                    public Throwable handleError(RetrofitError cause) {
                        switch (cause.getResponse().getStatus()) {
                            case 400:
                                /* Handle the expected body format */
                                cause.getBody();
                                throw new RuntimeException("Bad Request");
                            default:
                                /* Things and stuff */
                                throw new RuntimeException("");
                        }
                    }
                })
                .build()
                .create(Endpoints.class);

        e.getGoogle(new Callback<Response>() {
            @Override
            public void success(Response response, Response response2) {
                System.out.println("Got it");
            }

            @Override
            public void failure(RetrofitError error) {
                System.err.println("This won't ever be seen due to the error handler.");
            }
        });
    }

    private static interface Endpoints {
        @GET("/foo/bar")
        void getGoogle(Callback<Response> callback);
    }
}
公共类刮擦{
公共静态void main(字符串[]args){
端点e=new RestAdapter.Builder()
.setEndpoint(“http://google.com")
.setLogLevel(RestAdapter.LogLevel.FULL)
.setErrorHandler(新的ErrorHandler(){
@凌驾
公共可丢弃手柄错误(错误原因){
开关(cause.getResponse().getStatus()){
案例400:
/*处理预期的正文格式*/
cause.getBody();
抛出新的RuntimeException(“错误请求”);
违约:
/*东西*/
抛出新的RuntimeException(“”);
}
}
})
.build()
.create(Endpoints.class);
e、 getGoogle(新回调函数){
@凌驾
公共无效成功(响应,响应2){
System.out.println(“明白了”);
}
@凌驾
公共无效失败(错误){
System.err.println(“由于错误处理程序的原因,这将永远不会被看到。”);
}
});
}
私有静态接口端点{
@获取(“/foo/bar”)
void getGoogle(回调);
}
}

编辑:但是,这样做可能会牺牲一个重要的原因,那就是为什么您要首先使用
回调
接口。如果这是您需要的常见用法,那么使用sync调用并返回对象类型可能更有意义。我不完全知道你说这是必要的,但这似乎更合适。

你可以在RestAdapter builder中使用改型的ErrorHandler。是的,但我希望不同的方法有不同的例外。。。或者至少我认为我是。我不能完全肯定这种方法。假设我有一个createSomething方法。这可能会引发一种早已存在的性观念。如果我有一个deleteSomething方法,它可能会抛出一些NotFoundException。。。有道理吗?我真的不认为你有道理,至少在这个层次上没有。您正在使用的任何HTTP服务都应该使用标准错误代码(或者有一些标准来告诉您请求失败的原因)。因此,在我的回答中的
开关
示例中,使用您的注释作为模板,您将
409
映射到您的
冲突异常
404
映射到您的
NotFoundException
,作为状态代码:异常映射。当你调用一个4xx/5xx的东西时,不管它是什么,你都会得到一个标准的异常。当然,消极的一面是你牺牲了一些美好的东西