【问题标题】:restTemplate ResourceAccessException on server reboot服务器重新启动时的restTemplate ResourceAccessException
【发布时间】:2013-07-08 03:16:55
【问题描述】:

我在我的 android 应用程序上使用 restTemplate(来自 spring android 框架)通过 post 联系休息服务器,我使用 AsyncTask 发送请求和两个类 Request 和 Response,它们是 POJO 以 Json 形式发送.

public class RequestSender extends AsyncTask<Object, Void, Response> {
    private RestTemplate restTemplate = new RestTemplate();
    private static final String SERVER_REQUEST_PATH = "/path/to/rest/service";

    @Override
    protected Response doInBackground(Object... args) {
        String url = (String) args[0] + SERVER_REQUEST_PATH;
        Request requestArgs = (Request) args[1];
            Response response = null;

        restTemplate.getMessageConverters().add(new MappingJackson2HttpMessageConverter());
        try {
               response = restTemplate.postForObject(url, requestArgs, Response.class);
        } catch (RestClientException e) {
            e.printStackTrace();
            response = null;
        }
        return response;
    }
}

如您所见,代码非常简单,大部分时间都可以正常工作,但不是按特定顺序:

  1. 我向服务器发出第一个(或更多)请求;
  2. 我没有重启应用就重启了服务器;
  3. 我向服务器发出新请求;

那么服务器重启后的第一个请求(第 3 步)不会通过 postForObject(...) 方法发送到服务器,但下一个请求是。这第一个请求给我一个错误:

07-10 10:24:13.402: W/System.err(4827): org.springframework.web.client.ResourceAccessException: I/O error: null; nested exception is java.io.EOFException
    07-10 10:24:13.402: W/System.err(4827):     at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:491)
    07-10 10:24:13.402: W/System.err(4827):     at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:439)
    07-10 10:24:13.402: W/System.err(4827):     at org.springframework.web.client.RestTemplate.postForObject(RestTemplate.java:317)
    07-10 10:24:13.402: W/System.err(4827):     at com.myapp.servercommunication.RequestSender.doInBackground(RequestSender.java:42)
    07-10 10:24:13.406: W/System.err(4827):     at com.myapp.servercommunication.RequestSender.doInBackground(RequestSender.java:1)
    07-10 10:24:13.406: W/System.err(4827):     at android.os.AsyncTask$2.call(AsyncTask.java:287)
    07-10 10:24:13.406: W/System.err(4827):     at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305)
    07-10 10:24:13.406: W/System.err(4827):     at java.util.concurrent.FutureTask.run(FutureTask.java:137)
    07-10 10:24:13.406: W/System.err(4827):     at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:230)
    07-10 10:24:13.406: W/System.err(4827):     at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1076)
    07-10 10:24:13.406: W/System.err(4827):     at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:569)
    07-10 10:24:13.406: W/System.err(4827):     at java.lang.Thread.run(Thread.java:856)
    07-10 10:24:13.409: W/System.err(4827): Caused by: java.io.EOFException
    07-10 10:24:13.413: W/System.err(4827):     at libcore.io.Streams.readAsciiLine(Streams.java:203)
    07-10 10:24:13.417: W/System.err(4827):     at libcore.net.http.HttpEngine.readResponseHeaders(HttpEngine.java:560)
    07-10 10:24:13.417: W/System.err(4827):     at libcore.net.http.HttpEngine.readResponse(HttpEngine.java:813)
    07-10 10:24:13.417: W/System.err(4827):     at libcore.net.http.HttpURLConnectionImpl.getResponse(HttpURLConnectionImpl.java:274)
    07-10 10:24:13.417: W/System.err(4827):     at libcore.net.http.HttpURLConnectionImpl.getResponseCode(HttpURLConnectionImpl.java:486)
    07-10 10:24:13.417: W/System.err(4827):     at org.springframework.http.client.SimpleClientHttpResponse.getRawStatusCode(SimpleClientHttpResponse.java:54)
    07-10 10:24:13.417: W/System.err(4827):     at org.springframework.http.client.SimpleClientHttpResponse.getStatusCode(SimpleClientHttpResponse.java:80)
    07-10 10:24:13.421: W/System.err(4827):     at org.springframework.web.client.DefaultResponseErrorHandler.hasError(DefaultResponseErrorHandler.java:46)
    07-10 10:24:13.421: W/System.err(4827):     at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:477)
    07-10 10:24:13.421: W/System.
    err(4827):  ... 11 more

即使用例并不重要,我想知道为什么会抛出这个错误,是我的实现有问题,还是 RestTemplate 的行为很正常?

【问题讨论】:

    标签: android resttemplate spring-android


    【解决方案1】:

    如果你使用新的spring-android v.2.0.0.M3 它需要包含 maven

            <dependency>
                <groupId>org.apache.httpcomponents</groupId>
                <artifactId>httpclient-android</artifactId>
                <version>4.3.5.1</version>
            </dependency>
    

    或分级

    dependencies {
        compile('org.apache.httpcomponents:httpclient-android:4.3.5.1')
    }
    

    如果 Spring for Android 检测到 HttpClient 4.3,那么它将 自动将其配置为默认的 ClientHttpRequestFactory

    【讨论】:

      【解决方案2】:

      最近我在从 REST 模板发送请求时遇到了同样的问题。我们尝试了很多在 HTTP 标头中添加“http.keepAlive”,但它有时会起作用,有时它不起作用。最后,我们在使用以下代码设置“Accept-Language”标头后解决了这个问题:

      HttpHeaders headers = new HttpHeaders();
      headers.set("Accept-Language", "en-US,en;q=0.8");
      

      【讨论】:

      • 试着扩展你的答案,像你这样简短的答案也可以作为评论。
      【解决方案3】:

      毫无疑问java.io.EOFException 出现在服务器端。如果您在服务器端使用 keep-alive - 像这样关闭它:

       HttpHeaders headers = new HttpHeaders();
       headers.set("Connection", "Close");
      

      或者这个:System.setProperty("http.keepAlive", "false");

      另一个解决方案是更改 http 客户端。在 Spring for Android 中,RestTemplate 的默认 HTTP 客户端由设备上的 Android 版本决定。 API 9 或更高版本使用HttpURLConnection,旧版本使用HTTPClient。要将客户端显式设置为旧客户端,请使用 yourRestTemplate.setRequestFactory(new HttpComponentsClientHttpRequestFactory());

      请参考:http://static.springsource.org/spring-android/docs/1.0.1.RELEASE/reference/htmlsingle/#d4e34

      Spring RestTemplate 不是一个理想的 REST 客户端,不幸的是,它在生产代码中存在很多问题。

      【讨论】:

      • 强制使用 HttpClient 会使错误在我的设备上消失,但它会在旧设备上产生问题吗?
      • @Antoine 正如我所说,RestTemplate 不是很稳定,所以我可以提供任何保证。在不同的 Android 主要版本(ICS、Jelly Bean、Gingerbread 和 HoneyComb)上测试它的唯一方法。Based on this recommendation RestTemplate checks the version of Android on which your app is running and uses the appropriate ClientHttpRequestFactory. .但是RestTemplate选择不够好,所以我建议在不同Android版本上测试后手动选择它。
      猜你喜欢
      • 2011-04-21
      • 2019-08-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-10-13
      • 1970-01-01
      • 2015-08-19
      相关资源
      最近更新 更多