当前位置: 首页 > 面试题库 >

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

陈业
2023-03-14
问题内容

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

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:

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

但是,我想要的是将它按原样存储为ArrayList。如何配置异步任务以接收我的m_tours
ArrayList并将其存储在某个地方以备将来使用?此外,如何配置它以接收多个对象?

编辑

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

@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);
    }

}

但我得到一个错误:

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));

我做错了什么?

编辑2 解决:

错误: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中使用的库相同的库。

例如,if Tour是这样的:

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

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

public class Tours {
  private List<Tour> tours;
  // ...
}

然后在服务器端(请参阅此问题,我在这里使用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,您最终可能会得到更简单,更可靠的代码。



 类似资料:
  • 本文向大家介绍Python的Tornado框架的异步任务与AsyncHTTPClient,包括了Python的Tornado框架的异步任务与AsyncHTTPClient的使用技巧和注意事项,需要的朋友参考一下 高性能服务器Tornado Python的web框架名目繁多,各有千秋。正如光荣属于希腊,伟大属于罗马。Python的优雅结合WSGI的设计,让web框架接口实现千秋一统。WSGI 把应用

  • 我试图在这个类中实现异步任务,但问题是我在我的程序中调用了函数,该函数返回一个值,我不知道该把它放在哪里。在异步任务中,我应该在哪里定义?我得到以下例外 以下是我的主要课程: 这是我的解析类:公共类解析{ List headlines列出链接;列表描述;列出lstDate列出新日期;//字符串a,b,c,d;public InputStream getInputStream(URL URL){ t

  • 我正在计划开发一个基于微服务的架构应用程序,当我阅读Ronnie Mitra的书《微服务架构》时,我决定使用Kafka进行内部通信;马特·麦克拉蒂;迈克·阿蒙森;伊拉克利·纳达雷什维利说: 让微服务直接与消息代理(如RabbitMQ等)交互很少是个好主意。如果两个微服务通过消息队列通道直接通信,那么它们共享一个数据空间(通道),我们已经详细讨论了两个微服务共享一个数据空间的弊病。相反,我们可以做的

  • 我有一个BE服务a,它正在使用假客户端向microservice B发送Rest JSON消息: 终点: Rest Endpoint正在向AWS Ses邮件或其他邮件提供商发送邮件。 问题是来自飞格的第一个呼叫可能需要5秒或更长时间。我需要使其异步,以便FE客户端不要等待邮件发送。 我如何可以使从飞度异步发出的Rest调用到超文本传输协议响应OK没有等待时间可以预期?是否有一些更好的解决方案来实现

  • 一、HandlerThread 的使用场景和用法? HandlerThread 本质上是一个在子线程的handler(HandlerThread=Handler+Thread); 步骤1:创建HandlerThread实例对象 步骤2:启动线程 步骤3:创建工作线程Handler&复写handleMessage () 步骤4:使用工作线程Handler向工作线程的消息队列发送消息 步骤5:结束线程

  • 和响应的侦听器 它不想进入侦听器中的这个句柄消息。和应用程序容器显示消息