Использование асинхронных сервлетов для уведомлений Web Pu sh - PullRequest
0 голосов
/ 18 июня 2020

Я пытаюсь использовать асинхронные сервлеты для Web Pu sh Уведомления, используя этот пример здесь, на странице oracle

Код, упомянутый в примере на этой странице, использует почтовый запрос для добавления новых данных и последующей последовательной отправки запроса с помощью get для проверки наличия новых данных и последующего отображения их во всех экземплярах браузера.

В моем случае я бы получал данные из базы данных, поэтому я решил создать простой счетчик для имитации новых данных на самом сервере и по мере увеличения счетчика отображать их во всех экземплярах браузера

Like : 1 2 3 4 5 6 7 8 9 

, но это не работает, в чем я ошибаюсь?

Сервлет

@WebServlet(urlPatterns = {"/shoutServlet"}, asyncSupported=true)

public class ShoutServlet extends HttpServlet {
    private List<AsyncContext> contexts = new LinkedList<>();

@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {
    final AsyncContext asyncContext = request.startAsync(request, response);
    asyncContext.setTimeout(10 * 60 * 1000);
    contexts.add(asyncContext);
}

@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {
    List<AsyncContext> asyncContexts = new ArrayList<>(this.contexts);

    this.contexts.clear();
    int counter=10;
    int i =0;
    while(i<counter) {

         ServletContext sc = request.getServletContext();
         if (sc.getAttribute("messages") == null) {
             sc.setAttribute("messages", i);
         } else {
             String currentMessages = (String) sc.getAttribute("i");
             sc.setAttribute("messages", i + currentMessages);
         }
         for (AsyncContext asyncContext : asyncContexts) {
             try (PrintWriter writer = asyncContext.getResponse().getWriter()) {
                 writer.println(i);
                 writer.flush();
                 asyncContext.complete();
             } catch (Exception ex) {
             }
         }
         i++;
    }
}
}

JSP

 <%@page contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>JSP Page</title>
    </head>
    <body>
        <h1>SHOUT-OUT!</h1>
        <form method="POST" action="shoutServlet">
            <table>
                <tr>
                    <td>Your name:</td>
                    <td><input type="text" id="name" name="name"/></td>
                </tr>
                <tr>
                    <td>Your shout:</td>
                    <td><input type="text" id="message" name="message" /></td>
                </tr>
                <tr>
                    <td><input type="submit" value="SHOUT" /></td>
                </tr>
            </table>
        </form>
        <h2> Current Shouts </h2>
        <div id="content">
            <% if (application.getAttribute("messages") != null) {%>
            <%= application.getAttribute("messages")%>
            <% }%>
        </div>
         <script>
            var messagesWaiting = false;
            function getMessages(){
                if(!messagesWaiting){
                    messagesWaiting = true;
                    var xmlhttp = new XMLHttpRequest();
                    xmlhttp.onreadystatechange=function(){
                        if (xmlhttp.readyState==4 && xmlhttp.status==200) {
                            messagesWaiting = false;
                            var contentElement = document.getElementById("content");
                            contentElement.innerHTML = xmlhttp.responseText + contentElement.innerHTML;
                        }
                    }
                    xmlhttp.open("GET", "shoutServlet?t="+new Date(), true);
                    xmlhttp.send();
                }
            }
            setInterval(getMessages, 1000);
        </script>
    </body>
</html>

1 Ответ

0 голосов
/ 19 июня 2020

Мне кажется, вы не совсем поняли, как работают сервлеты asyn c. Идея состоит в том, что вы освобождаете веб-поток (обычно в пуле потоков http, размер которого можно настроить на сервере приложений), а затем завершаете sh работу запроса в каком-то другом потоке. В конце вы должны вызвать AsyncContext.complete(), чтобы на самом деле завершить sh запрос и вернуть ответ клиенту (который все еще ждет).

Обратите внимание, что весь поток не будет быстрее ( на самом деле это будет немного медленнее, чем при нормальной синхронной обработке. Преимущество этого заключается в том, что вы можете освободить поток HTTP раньше, чтобы он мог обрабатывать другие запросы HTTP. Обычно поток HTTP блокируется на все время работы вашего метода doGet / Post, и если вы выполняете там обширную обработку и / или ввод-вывод, это может заполнить пул потоков HTTP, и когда это произойдет, ваше приложение будет не сможет больше обрабатывать HTTP-запросы. (Или, точнее, клиентское соединение будет зависать до тех пор, пока один из потоков HTTP не станет снова доступен для обработки запроса.)

Однако в вашем коде я не вижу, куда вы звоните AsyncContext.complete() или заканчивая doGet() logi c, вроде вернуть какие-то данные клиенту. Могут быть и другие проблемы, но это наиболее очевидная причина, по которой он не работает.

Помимо этого, я думаю, у вас есть опечатка в doPost(), где вы делаете sc.getAttribute("i");. Атрибут i нигде не установлен, поэтому он всегда будет возвращать null, что вызовет NPE в следующей строке i + currentMessages.

Кроме того, на всякий случай вы ожидаете, что это будет сумма двух числа вместе - не будет. Он добавит их, поскольку currentMessages - это String, а + в String выполняет конкатенацию, независимо от того, какой тип имеет другой операнд.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...