【问题标题】:Asynchronous behavior in Java Servlet?Java Servlet 中的异步行为?
【发布时间】:2014-04-30 14:09:34
【问题描述】:

我第一次尝试设计一个 Java Servlet。 这是我的最终目标行为。

  1. Servlet 收到请求。
  2. Servlet 向另一台服务器发出 HTTP 请求(我们称之为 MServer)。
  3. MServer 可以在接下来的 20-25 分钟内异步发送回复到我的 Servlets 请求。
  4. 我想在 Servlet 收到此数据后立即将此数据发送回用户(在步骤 1 中向 servlet 发出请求的用户)。

知道我该怎么做吗?

到目前为止,我刚刚制作了一个“Hello World”Java Servlet。与 MServer 通信的代码也已准备就绪。但我不知道如何实现这种异步行为。

任何帮助将不胜感激。

【问题讨论】:

  • 可能你需要在 Servlet1 上创建一些消息队列并使用长轮询stackoverflow.com/questions/11077857/…
  • 所以您假设用户将在页面等待加载时将选项卡保持打开 25 分钟?同意 user979349,轮询系统(换句话说:异步设计以匹配您的问题的异步性质)是要走的路。
  • @Gimby - 是的,我假设用户将保持连接打开大约 25 分钟。
  • @user979349 - 我不希望用户进行定期轮询,因为在智能手机中这可能会影响电源效率。我希望 servlet 从 MServer 获取任何数据后立即通知用户。
  • @Gimby - 还有一件事,我不想在 25 分钟结束时得到一个回复​​。我想要对同一个请求进行多个实时回复。类似的东西 - 用户请求 @ 0 分钟。 Servlet 在 2 分钟后发送一些数据。然后可能在 7 分钟后,servlet 再次发送一些数据,而用户没有任何操作。这每隔几分钟就会发生一次。 25 分钟后,客户端 - servlet 连接终止。而且我不想从客户端轮询。

标签: java servlets asynchronous httprequest httpresponse


【解决方案1】:

我认为您应该使用asynchronous servlet。我假设有一个看起来像这样的 MServer 外观:

interface MServer {
    void getStuff(Observer observer);
}

interface Observer {
    void onNewStuff(String stuff);
    void onThatWasAllStuff();
}

class MServerSingleton {
    MServer getInstance() {
        // Code that returns an MServer.
    }
}

然后你可以像这样实现你的servlet:

public class TheServlet extends HttpServlet {
    protected void doGet(HttpServletRequest req, final HttpServletResponse resp) {
        resp.setContentType("text/plain");
        final AsyncContext context = req.startAsync();
        MServerSingleton.getInstance().getStuff(new Observer() {
            void onNewStuff(String stuff) {
                try {
                    resp.getWriter().write(stuff + "\n\n");
                    resp.getWriter().flush();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

            void onThatWasAllStuff() {
                context.complete();
            }
        });
    }
}

您可能需要调整超时才能使其正常工作。

您可能需要考虑使用Server Sent Events

【讨论】:

    【解决方案2】:

    这是一个示例,希望对您有所帮助。它假定您有一个浏览器作为客户端并实现 jQuery Ajax 调用。如果您从 Mserver 长时间运行的调用已完成并且数据可供客户端使用,它每 5 秒检查一次。希望对你有帮助:)

    您的 servlet 代码:

    public class TestServlet extends HttpServlet {
        private static final long serialVersionUID = 1L;
    
        @Override
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            String data = Mserver.getInstance().getData();
    
            response.setContentType("text/html;charset=UTF-8");
            response.setCharacterEncoding("UTF-8");
    
            PrintWriter out = response.getWriter();
            out.println(data);
        }
    }
    

    示例 Mserver 代码:

    public class Mserver {
        private String data;
        private static final Mserver mserver = new Mserver();
    
        public static Mserver getInstance() {
            return mserver;
        }
    
        private Mserver() {
            new Thread() {
                @Override
                public void run() {
                    computeData();
                }
            }.start();
        }
    
        // Computing data by making multiple server calls etc..
        private void computeData() {
            try {
                System.out.println("Waiting for 20 seconds simulating long running call");
                Thread.sleep(20000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            data = "Computed Data is ready now.";
        }
    
        public String getData() {
            return data;
        }
    }
    

    使用 jQuery Ajax 调用的 HTML 页面:

    <!DOCTYPE html>
    <html>
    <head>
    <meta http-equiv="content-type" content="text/html; charset=utf-8" />
    <script src="js/jquery.min.js"></script>
    <script type="text/javascript" charset="utf-8">
        $(document).ready(function() {
            setInterval(function() {
                $.ajax({
                    type:"get",
                    url: "checkDataFromMserver",
                    async: false,
                    success: function (data) {
                        $("#response").html(data);
                    }
                });
            }, 5000);
        });
    </script>
    </head>
    <body>
        Getting data using jQuery Ajax
        <div id="response"></div>
    </body>
    </html>
    

    我测试了它并且它有效。客户端每 5 秒轮询一次以检查数据是否准备好。 20 秒后,它从 Mserver 获取数据。

    希望你觉得它有用!

    【讨论】:

    • 如果这个答案对你所做的任何事情都有帮助,请接受它作为答案。
    【解决方案3】:

    您可能必须在客户端实施连续检查,并在服务器端实施队列。换句话说,客户端将每 1-2 分钟联系一次 servlet 以检查发给他的新消息。 servlet 还应该有一个方法来异步获取数据,然后将接收到的数据存储在队列中。可以通过多种方式实现这样的队列,例如将来自 MServer 的响应存储在数据库表中。

    【讨论】:

    • 这不能使用普通的 Servlet 解决,因为 Servlet 处理单个请求并提交单个响应。您可以使用 WebSockets 代替 HTML 5 或类似 Atmosphere 的框架来实现这一点。
    猜你喜欢
    • 1970-01-01
    • 2017-02-09
    • 1970-01-01
    • 1970-01-01
    • 2011-07-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-30
    相关资源
    最近更新 更多