异步任务的消息与Java Servlet交换

我有一个简单的应用程序通过Async任务与其Servlet后端通信。 我很难理解消息是如何被包装的以及如何操纵这些消息的数据结构。 我想要做的是接收多个对象或多个异构信息。 我的代码:

public class MyServlet extends HttpServlet { ArrayList m_tours; @Override public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException { resp.setContentType("text/plain"); resp.getWriter().println("Please use the form to POST to this url"); } @Override public void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException { String order = req.getParameter("order"); resp.setContentType("text/plain"); if (order == null) { resp.getWriter().println("Please enter a name"); } resp.getWriter().println("yay name received"); ArrayList m_tours = getTours(); //returns a populated ArrayList of custom Tour objects resp.getWriter().print(m_tours); } private void getTours(){ //some code here } }` 

我的Async任务类:

 class ServletPostAsyncTask extends AsyncTask<Pair, Void, String> { private Context context; @Override protected String doInBackground(Pair... params) { context = params[0].first; String order = params[0].second; String[] url = new String[3]; url[0] = "http://192.168.169.85:8080/hello"; url[1] = "http://10.0.2.2:8080/hello"; url[2] = "http://192.168.1.102:8080/hello"; HttpClient httpClient = new DefaultHttpClient(); HttpPost httpPost = new HttpPost(url[2]); List nameValuePairs = new ArrayList(1); nameValuePairs.add(new BasicNameValuePair("order", order)); try { // Add name data to request httpPost.setEntity(new UrlEncodedFormEntity(nameValuePairs)); // Execute HTTP Post Request HttpResponse response = httpClient.execute(httpPost); HttpEntity entity = response.getEntity(); if (response.getStatusLine().getStatusCode() == 200) { return EntityUtils.toString(entity); } return "Error: " + response .getStatusLine() .getStatusCode() + " " + response .getStatusLine().getReasonPhrase(); } catch (ClientProtocolException e) { return e.getMessage(); } catch (IOException e) { return e.getMessage(); } } @Override protected void onPostExecute(String result) { String result1 = "Response: "+result; Toast.makeText(context, result1, Toast.LENGTH_LONG).show(); } } 

响应消息将ArrayList作为文本返回:

  Response: yay name received packagename@objectkey1 packagename@objectkey2 packagename@objectkey3 ... packagename@objectkeyn 

但相反,我想要的是将它原样存储为ArrayList。 如何配置我的异步任务以接收我的m_tours ArrayList并将其存储在某处以供进一步使用? 此外,如何配置它以接收多个对象?

*编辑*

我按照@orip的建议尝试使用Gson,设置Async任务如下:

 @Override protected String doInBackground(Pair... params) { context = params[0].first; String order = params[0].second; String[] url = new String[3]; url[0] = "http://192.168.169.85:8080/hello"; url[1] = "http://10.0.2.2:8080/hello"; url[2] = "http://192.168.1.102:8080/hello"; // HttpPost httpPost = new HttpPost("http://semiotic-art-88319.appspot.com/hello"); HttpClient httpClient = new DefaultHttpClient(); //127.0.0.1 - 10.201.19.153 HttpPost httpPost = new HttpPost(url[2]); List nameValuePairs = new ArrayList(1); nameValuePairs.add(new BasicNameValuePair("order", order)); try { // Add name data to request httpPost.setEntity(new UrlEncodedFormEntity(nameValuePairs)); // Execute HTTP Post Request HttpResponse response = httpClient.execute(httpPost); if (response.getStatusLine().getStatusCode() == 200) { HttpEntity entity = response.getEntity(); return EntityUtils.toString(entity); } return "Error: " + response .getStatusLine() .getStatusCode() + " " + response .getStatusLine().getReasonPhrase(); } catch (ClientProtocolException e) { return e.getMessage(); } catch (IOException e) { return e.getMessage(); } } @Override protected void onPostExecute(String jsonResponse) { Gson gson = new Gson(); tours = (gson.fromJson(jsonResponse, Tours.class)); Toast.makeText(context, jsonResponse, Toast.LENGTH_LONG).show(); } 

在服务器端:

 @Override public void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException { String asyncMessage = req.getParameter("order"); if(asyncMessage.equals("tours")){ m_tours = getTours(); //ArrayList m_tours; Tours tours = new Tours(m_tours); resp.setContentType("application/json"); PrintWriter out = resp.getWriter(); out.print(new Gson().toJson(tours)); out.flush(); resp.getWriter().print(m_tours); } } 

但是我收到一个错误:

 03-23 13:27:09.523 32387-32387/madapps.bicitourbo E/AndroidRuntime﹕ FATAL EXCEPTION: main Process: madapps.bicitourbo, PID: 32387 com.google.gson.JsonSyntaxException: com.google.gson.stream.MalformedJsonException: Use JsonReader.setLenient(true) to accept malformed JSON at line 1 column 692 path $ at com.google.gson.Gson.assertFullConsumption(Gson.java:786) at com.google.gson.Gson.fromJson(Gson.java:776) at com.google.gson.Gson.fromJson(Gson.java:724) at com.google.gson.Gson.fromJson(Gson.java:696) at madapps.bicitourbo.ServletPostAsyncTask.onPostExecute(ServletPostAsyncTask.java:92) at madapps.bicitourbo.ServletPostAsyncTask.onPostExecute(ServletPostAsyncTask.java:36) at android.os.AsyncTask.finish(AsyncTask.java:632) at android.os.AsyncTask.access$600(AsyncTask.java:177) at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:645) at android.os.Handler.dispatchMessage(Handler.java:102) at android.os.Looper.loop(Looper.java:149) at android.app.ActivityThread.main(ActivityThread.java:5257) at java.lang.reflect.Method.invokeNative(Native Method) at java.lang.reflect.Method.invoke(Method.java:515) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:609) at dalvik.system.NativeStart.main(Native Method) Caused by: com.google.gson.stream.MalformedJsonException: Use JsonReader.setLenient(true) to accept malformed JSON at line 1 column 692 path $ 

该行发生此错误:

 Tour tours = (gson.fromJson(jsonResponse, Tours.class)); 

我做错了什么?

* EDIT2 *已解决:

错误: Caused by: com.google.gson.stream.MalformedJsonException: Use JsonReader.setLenient(true) to accept malformed JSON以下原因Caused by: com.google.gson.stream.MalformedJsonException: Use JsonReader.setLenient(true) to accept malformed JSON是因为我正在调用resp.getWriter().print()两次,如建议的那样通过@orip。 谢谢!

将servlet的内容类型设置为application/json并返回JSON字符串(例如,使用Gson或Jackson来序列化结果。

在Android端,您可以使用Android的内置JSON类反序列化JSON字符串,或者(更好)使用您在servlet中使用的相同库。

例如,如果Tour类似于:

 public class Tour { // some simple int/string/list fields } 

您可以构建一个响应类,如:

 public class Tours { private List tours; // ... } 

然后在服务器端(看到这个问题 ,我在这里使用Gson ):

 List listOfTours = ...; Tours tours = new Tours(listOfTours); response.setContentType("application/json"); PrintWriter out = response.getWriter(); out.print((new Gson()).toJson(tours)); out.flush(); 

在客户端:

 String jsonResponse = ...; Tours tours = (new Gson()).fromJson(jsonResponse, Tours.class); 

有一些优化要做,但这可以让你开始。 另外,考虑使用OkHttp进行HTTP连接而不是使用HttpClient ,您可能最终会得到更简单,更健壮的代码。