使用RoboSpice有一种方法可以从异常中获取HTTP错误代码吗?

时间:2013-02-13 22:31:45

标签: android http-status-code-401 robospice

我正在编写一个使用RoboSpice的应用程序。在请求侦听器onRequestFailure(SpiceException arg0)中是否有一种方法可以确定错误是由于发生了401 HTTP错误?

我有一个后端服务,当令牌过期时返回401错误,当发生这种情况时,我需要提示用户重新输入他们的凭据。

无论如何都知道特别发生了401 HTTP错误?

以下是我的请求示例。

   public class LookupRequest extends SpringAndroidSpiceRequest <Product> {

public String searchText;
public String searchMode;

public LookupRequest() {
    super( Product.class );
}

@Override
public Product loadDataFromNetwork() throws Exception {
    String url = String.format("%s/Lookup?s=%s&m=%s", Constants.BASE_URL, searchText, searchMode);
    Ln.d("Calling URL: %s", url);
    return getRestTemplate().getForObject(url, Product.class );
}

5 个答案:

答案 0 :(得分:20)

我看着Spring-Android更近了,似乎getRestTemplate()。getForObject(...)在发生401或任何网络错误时抛出HttpClientErrorException。

看看Robo Spice他们捕获该异常的位置,我发现他们在processRequest函数的RequestProcessor.java中捕获它。它们将Spring-Android异常作为源自SpiceException的throwable传递,该异常类继承自Java异常类。

因此,您只需在RoboSpice RequestListener中执行以下操作,以查看它是否为401 UNAUTHORIZED异常。

    private class MyRequestListener implements RequestListener<RESULT> {

    public void onRequestFailure( SpiceException arg0 ) {

        if(arg0.getCause() instanceof HttpClientErrorException)
        {
            HttpClientErrorException exception = (HttpClientErrorException)arg0.getCause();
            if(exception.getStatusCode().equals(HttpStatus.UNAUTHORIZED))
            {
                Ln.d("401 ERROR");
            }
            else
            {
                Ln.d("Other Network exception");
            }
        }
        else if(arg0 instanceof RequestCancelledException)
        {
            Ln.d("Cancelled");
        }
        else
        {
            Ln.d("Other exception");
        }
    };

    public void onRequestSuccess( RESULT result ) {
        Ln.d("Successful request");
    }
}

答案 1 :(得分:2)

我正在使用带有RoboSpice的google http客户端并遇到同样的问题,但很容易通过request.setThrowExceptionOnExecuteError(false);解决并检查生成的HttpResponse对象上的响应代码

编辑:代码按要求snippit

HttpRequest request = getHttpRequestFactory().buildPostRequest(new GenericUrl(URL), content);
request.setThrowExceptionOnExecuteError(false);
HttpResponse response = request.execute();

switch(response.getStatusCode())
    {
        case HttpStatusCodes.STATUS_CODE_UNAUTHORIZED:
            return new MyBaseResponse(responseBody);
        default:
            throw new RuntimeException("not implemented yet");
    }

答案 2 :(得分:2)

对于那些无法将HttpClientErrorException解析为某种类型,并且无法在线找到任何文档的人(就是我),这是我的方法:

在我的片段中,这是我的听众:

private final class MyRequestListener extends RequestListener<MyResponse> {

  @Override
  public void onRequestFailure(SpiceException spiceException) {
    super.onRequestFailure(spiceException);
    if (spiceException instanceof NetworkException) {
      NetworkException exception = (NetworkException) spiceException;
      if (exception.getCause() instance RetrofitError) {
        RetrofitError error = (RetrofitError) exception.getCause();
        int httpErrorCode = error.getResponse().getStatus();
        // handle the error properly...
        return;
      }
    }
    // show generic error message
  }

}

希望这对某人有帮助。

我会将整个if子句移动到静态函数中,以便可以重用它。如果异常不匹配,则返回0。我还没有确认是否可以拆除任何铸件......

答案 3 :(得分:0)

使用google http client for java,您也可以截取错误响应,如下所示:

public static class InitIntercept implements 
    HttpRequestInitializer, HttpUnsuccessfulResponseHandler {

    @Override
    public boolean handleResponse(
        HttpRequest request, 
        HttpResponse response, 
        boolean retrySupported) throws IOException {

        if (response.getStatusCode() == HttpStatusCodes.STATUS_CODE_UNAUTHORIZED) {
            ...
        }

        return false;
    }

    @Override
    public void initialize(HttpRequest request) throws IOException {
        request.setUnsuccessfulResponseHandler(this);
    }
}

并在您的GoogleHttpClientSpiceService中:

@Override
public HttpRequestFactory createRequestFactory() {
    return AndroidHttp
        .newCompatibleTransport().createRequestFactory(new InitIntercept());
}

答案 4 :(得分:0)

它比所有其他答案都容易。

对我来说@Scrotos的回答是有问题的,因为要捕获的401的全部要点是向auth端点发出请求,然后再次发出主要请求。因此,您只返回具有所需数据或某些“真实”错误的UI。 所以它不应该在回调中完成,而是在loadDataFromNetwork()本身内部。

我这样做了:

@Override
public SubscriptionsContainer loadDataFromNetwork() {

    //...

    ResponseEntity<SubscriptionsContainer> response = null;
    try {
        response = getRestTemplate().exchange(
        //your request data                    
        );
    } catch (HttpClientErrorException e) {
        HttpStatus statusCode = e.getStatusCode();
        //check the exception, if it's 401, make call to auth and repeat loadDataFromNetwork()
    }