我在我的android应用程序上使用restTemplate(来自spring android框架)与post联系休息服务器,我使用AsyncTask发送请求和两个类请求和响应,这些是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;
}
}
正如您所看到的,代码非常简单,并且在大多数情况下工作正常,但不是按特定顺序执行:
然后,服务器重启后的第一个请求(步骤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的一个非常正常的行为?
答案 0 :(得分:4)
服务器端不会出现疑问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客户端,不幸的是它在生产代码中存在很多问题。
答案 1 :(得分:0)
最近,我在从REST模板发送请求时遇到了同样的问题。我们尝试了很多添加&#34; http.keepAlive&#34;在HTTP标头中,但它工作了一些时间,有时它没有工作。最后,我们能够在设置&#34; Accept-Language&#34;之后解决这个问题。标题包含以下代码:
HttpHeaders headers = new HttpHeaders();
headers.set("Accept-Language", "en-US,en;q=0.8");
答案 2 :(得分: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>
或gradle
dependencies {
compile('org.apache.httpcomponents:httpclient-android:4.3.5.1')
}
如果Spring for Android检测到HttpClient 4.3,那么它会 自动将其配置为默认的ClientHttpRequestFactory