#java #asynchronous #jakarta-ee #comet #servlet-3.0
#java #асинхронный #джакарта-ee #comet #сервлет-3.0
Вопрос:
У меня возникли проблемы с установлением AsyncContexts для пользователей и использованием их для отправки им уведомлений. При загрузке страницы у меня есть некоторый код jQuery для отправки запроса:
$.post("TestServlet",{
action: "registerAsynchronousContext"
},function(data, textStatus, jqXHR){
alert("Server received async request"); //Placed here for debugging
}, "json");
И в «TestServlet» у меня есть этот код в методе doPost:
HttpSession userSession = request.getSession();
String userIDString = userSession.getAttribute("id").toString();
String paramAction = request.getParameter("action");
if(paramAction.equals("registerAsynchronousContext"))
{
AsyncContext userAsyncContext = request.startAsync();
HashMap<String, AsyncContext> userAsynchronousContextHashMap = (HashMap<String, AsyncContext>)getServletContext().getAttribute("userAsynchronousContextHashMap");
userAsynchronousContextHashMap.put(userIDString, userAsyncContext);
getServletContext().setAttribute("userAsynchronousContextHashMap", userAsynchronousContextHashMap);
System.out.println("Put asynchronous request in global map");
}
//userAsynchronousContextHashMap is created by a ContextListener on the start of the web-app
Однако, согласно Opera Dragonfly (средство отладки, подобное Firebug), похоже, что сервер отправляет ответ HTTP 500 примерно через 30000ms после отправки запроса.
Любые ответы, созданные с помощью userAsyncContext.GetResponse().getWriter().print(SOME_JSON) и отправленные до ответа HTTP 500, не принимаются браузером, и я не знаю почему. Использование обычного объекта response для отправки ответа (response.print(SOME_JSON)) принимается браузером ТОЛЬКО в том случае, если весь код в инструкции «if», относящейся к AsyncContext, отсутствует.
Кто-нибудь может мне помочь? У меня такое чувство, что это из-за моего непонимания того, как работает асинхронный API. Я думал, что смогу сохранить эти AsyncContexts на глобальной карте, затем извлечь их и использовать их объекты ответа для отправки чего-либо клиентам. Однако не похоже, что AsyncContexts могут выполнять обратную запись клиентам.
Любая помощь была бы принята с благодарностью.
Ответ №1:
Я решил проблему. Похоже, что в моем подходе было несколько проблем:
-
В Glassfish у всех объектов AsyncContext по умолчанию время ожидания составляет 30 000 миллисекунд (.5 минут). По истечении этого периода весь ответ передается обратно клиенту, что означает, что вы не сможете использовать его снова.
Если вы реализуете длительный опрос, это может быть не такой уж большой проблемой (поскольку в конечном итоге вы все равно отправите другой запрос после ответа), но если вы хотите реализовать потоковую передачу (отправку данных обратно клиенту без фиксации ответа), вы захотите либо увеличить время ожидания, либо избавиться от всего этого вместе. Этого можно достичь с помощью
.setTimeout()
метода AsyncContext. Обратите внимание, что, хотя в спецификации указано: «Значение тайм-аута, равное нулю или меньше, указывает на отсутствие тайм-аута»., Glassfish (на данный момент), похоже, интерпретирует 0 как «требуется немедленный ответ», а любое отрицательное число как «нет тайм-аута». -
Если вы реализуете потоковую передачу, вы должны использовать
.flush()
метод printwriter для отправки данных клиенту после того, как вы закончите использовать его методы.print()
.println()
или.write()
для записи данных. -
На стороне клиента, если вы передали данные в потоковом режиме, это вызовет readyState, равный 3 («интерактивный», что означает, что браузер находится в процессе получения ответа). Если вы используете jQuery, простого способа обработки readyStates, равного 3, не существует, поэтому вам придется вернуться к обычному Javascript, чтобы одновременно отправлять запрос и обрабатывать ответ, если вы реализуете потоковую передачу.
Ответ №2:
Я заметил, что в Glassfish, если вы используете AsyncContext и используете .setTimeout () с отрицательным числом, соединение все равно прерывается, чтобы исправить это, мне пришлось зайти в мой веб-конфигуратор администратора Glassfish: asadmin set configs.config.server-config.network-config.protocols.protocol.http-listener-1.http. И установите время ожидания равным -1. Все это для того, чтобы glassfish не завершал соединения через 30 секунд.