异步任务的消息与的Java Servlet交流 [英] Async task's messages exchange with Java Servlet
问题描述
我有过一个异步任务,其后台的Servlet一个简单的应用程序进行通信。 我有一些很难理解如何将邮件包裹起来,以及如何处理这些消息的数据结构。 我想要做的是接受或多个对象,或多个异构的信息呢。 我的code:
I have a simple app communicating with its Servlet backend through an Async task. I have some trouble understanding how the messages are wrapped up and how to manipulate the data structures of these messages. What I want to do is to receive either multiple objects, or multiple heterogeneous information anyway. My code:
public class MyServlet extends HttpServlet {
ArrayList<Tour> 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<Tour> m_tours = getTours(); //returns a populated ArrayList of custom Tour objects
resp.getWriter().print(m_tours);
}
private void getTours(){
//some code here
}
}`
和我的异步任务等级:
class ServletPostAsyncTask extends AsyncTask<Pair<Context, String>, Void, String> {
private Context context;
@Override
protected String doInBackground(Pair<Context, String>... 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<NameValuePair> 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文本:
The response message returns ArrayList as text:
Response: yay name received
packagename@objectkey1
packagename@objectkey2
packagename@objectkey3
...
packagename@objectkeyn
但是,相反,我要的是保存它,因为它是作为一个ArrayList。 我该如何配置我的异步任务领取我的m_tours ArrayList和存储在某个地方作进一步使用? 此外,如何配置它来接收多个对象?
But instead, what I want is to store it as it is, as an ArrayList. How can I configure my Async task to receive my m_tours ArrayList and store it somewhere for further use? Furthermore, how can I configure it to receive multiple objects?
*编辑*
我已经用GSON尝试所建议的@orip,设置异步任务如下:
I've tried by using Gson as suggested by @orip, setting the Async task as follows:
@Override
protected String doInBackground(Pair<Context, String>... 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<NameValuePair> 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<Tour> 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);
}
}
但我得到一个错误:
but I get an error:
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));
我该怎么办错了?
What do I do wrong?
* EDIT2 * 解决:
错误:致:com.google.gson.stream.MalformedJsonException:使用JsonReader.setLenient(真)接受畸形的JSON
是由于这样的事实,我在呼唤 resp.getWriter()的print()
的两倍,所建议的@orip。谢谢!
The error: Caused by: com.google.gson.stream.MalformedJsonException: Use JsonReader.setLenient(true) to accept malformed JSON
was due to the fact that I was calling resp.getWriter().print()
two times, as suggested by @orip. Thank you!
推荐答案
设置servlet的内容类型为应用程序/ JSON
,并返回一个JSON字符串(例如,使用GSON或杰克逊序列化的结果。
Set the servlet's content type to application/json
and return a JSON string (e.g using Gson or Jackson to serialize the result.
在Android的一面,你可以反序列化的JSON字符串,或者使用Android的内置JSON类或(最好)使用您在你的servlet中使用的相同的库。
On the Android side you can deserialize the JSON string, either using Android's built-in JSON classes or (better) using the same libraries you used in your servlet.
例如,如果旅游
是这样的:
public class Tour {
// some simple int/string/list fields
}
您可以建立一个响应等级,如:
You can build a response class like:
public class Tours {
private List<Tour> tours;
// ...
}
然后在服务器端(见<一href="http://stackoverflow.com/questions/2010990/how-do-you-return-a-json-object-from-a-java-servlet">this问题,我使用 GSON 这里):
List<Tour> 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
,你可能会结束了更简单,更强大的code。
There are some optimizations to be made, but that could get you started.
Also, consider using OkHttp for your HTTP connections instead of using HttpClient
, you'll probably end up with simpler and more robust code.
这篇关于异步任务的消息与的Java Servlet交流的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!