2

AndroidアプリケーションでrestTemplate(Spring Androidフレームワークから)を使用して、ポストでレストサーバーに接続しています。AsyncTaskを使用してリクエストを送信し、POJOである2つのクラスRequestとResponseを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 の非常に正常な動作でしょうか?

4

3 に答える 3

5

java.io.EOFExceptionサーバー側に疑いの余地はありません。サーバー側でキープアライブを使用している場合は、次のようにオフにします。

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

またはこれ:System.setProperty("http.keepAlive", "false");

もう 1 つの解決策は、http クライアントを変更することです。Spring for Android では、デフォルトの HTTP クライアントはRestTemplate 、デバイス上の Android のバージョンによって決まります。API 9 以降の用途HttpURLConnection、古い用途HTTPClient。クライアントを明示的に古いものに設定するには、次を使用します yourRestTemplate.setRequestFactory(new HttpComponentsClientHttpRequestFactory());

これを参照してください: http://static.springsource.org/spring-android/docs/1.0.1.RELEASE/reference/htmlsingle/#d4e34

SpringRestTemplateは理想的な REST クライアントではありません。残念ながら、本番コードには多くの問題があります。

于 2013-07-10T09:18:23.233 に答える
0

最近、REST テンプレートからリクエストを送信するときに同じ問題に直面しました。HTTP ヘッダーに「http.keepAlive」を追加することを何度も試みましたが、機能する場合と機能しない場合があります。最後に、次のコードで「Accept-Language」ヘッダーを設定した後、この問題を解決できました。

HttpHeaders headers = new HttpHeaders();
headers.set("Accept-Language", "en-US,en;q=0.8");
于 2014-04-28T10:45:08.260 に答える
0

新しい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 として自動的に構成します。

于 2015-09-17T11:14:52.620 に答える