使用 RoboSpice 有没有办法从异常中获取 HTTP 错误代码?
Posted
技术标签:
【中文标题】使用 RoboSpice 有没有办法从异常中获取 HTTP 错误代码?【英文标题】:Using RoboSpice is there a way to get the HTTP Error Code out of an exception? 【发布时间】:2013-01-29 15:28:52 【问题描述】:我正在编写一个使用 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 );
【问题讨论】:
【参考方案1】:对于那些无法将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。而且我还没有验证是否可以删除任何铸件...
【讨论】:
RetrofitError 是 Retrofit 1.6.1 中定义的类。如果您使用的是 2.x,它可能不再存在。路径:retrofit-1.6.1-sources.jar!/retrofit/RetrofitError.java public class RetrofitError extends RuntimeException ...【参考方案2】:这比所有其他答案都容易。
对我来说@Scrotos 的回答是有问题的,因为要捕获 401 的全部要点是向身份验证端点发出请求,然后再次发出主要请求。这样您就只能返回带有所需数据或一些“真实”错误的 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()
【讨论】:
如何处理多个并发请求?此代码将执行多个身份验证请求,不是吗。 这取决于您对 auth store 的实现。我使用帐户管理器。如果其中一个并发请求得到 401,它会更新 AccountManager 中的令牌,并且所有后续请求都将从此时获得适当的令牌。但我从来没有真正尝试过使用这段代码并发请求【参考方案3】:使用适用于 java 的 google http 客户端,您还可以像这样拦截错误响应:
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】:我正在使用带有 RoboSpice 的 google http 客户端,并且遇到了同样的问题,但使用 request.setThrowExceptionOnExecuteError(false);
并检查生成的 HttpResponse
对象上的响应代码很容易解决
编辑:请求的代码片段
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");
【讨论】:
【参考方案5】:我仔细查看了 Spring-Android,似乎 getRestTemplate().getForObject(...) 在发生 401 或任何网络错误时抛出 HttpClientErrorException。
查看 Robo Spice 在哪里捕获该异常,我发现他们在 processRequest 函数的 RequestProcessor.java 中捕获它。他们将 Spring-Android 异常作为继承自 Java 异常类的 SpiceException 中的 throwable 传递。
因此,您只需在 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");
【讨论】:
我在使用equals()
比较状态码和HttpStatus
时遇到了一些不一致的问题。相反,我开始毫无问题地比较它们:exception.getStatusCode().value() == HttpStatus.SC_BAD_REQUEST
。希望对您有所帮助。
HttpClientErrorException
无法解析为类型。
我得到一个 HttpResponseException 而不是 HttpClientErrorException
它是特定于 Apache HTTP 客户端后端的,不是吗?以上是关于使用 RoboSpice 有没有办法从异常中获取 HTTP 错误代码?的主要内容,如果未能解决你的问题,请参考以下文章
有没有办法强制 Java VM 立即执行从 JNI 发送的异常?
有没有办法使用 Video.js 从视频标签中获取当前字幕的文本?