Меня смущает функция Async, представленная в спецификации Servlet 3.0.
С сайта Oracle (http://docs.oracle.com/javaee/7/tutorial/doc/servlets012.htm):
Для создания масштабируемых веб-приложений необходимо убедиться, что никакие потоки, связанные с запросом, не простаивают, чтобы контейнер мог использовать их для обработки новых запросов.
Существует два распространенных сценария, в которых поток, связанный с запросом, может бездействовать.
1- Поток должен дождаться, пока ресурс станет доступным, или обработать данные, прежде чем строить ответ. Например, приложению может потребоваться запросить базу данных или получить доступ к данным из удаленной веб-службы, прежде чем генерировать ответ.
2- Поток должен дождаться события, прежде чем генерировать ответ. Например, приложению может потребоваться дождаться сообщения JMS, новой информации от другого клиента или новых данных, доступных в очереди, прежде чем сгенерировать ответ.
Первый элемент происходит часто (почти всегда мы всегда запрашиваем базу данных или вызываем удаленный веб-сервис, чтобы получить некоторые данные). И вызов внешнего ресурса всегда будет занимать некоторое время.
Означает ли это, что мы должны ВСЕГДА использовать асинхронную функцию servert для ВСЕХ наших серверов и фильтров?! Я тоже так могу спросить, если я напишу все свои сервлеты и фильтры асинхронно, я потеряю что-нибудь (производительность)?!
Если приведенное выше верно, скелет ВСЕХ наших сервлетов будет:
public class Work implements ServletContextListener {
private static final BlockingQueue queue = new LinkedBlockingQueue();
private volatile Thread thread;
@Override
public void contextInitialized(ServletContextEvent servletContextEvent) {
thread = new Thread(new Runnable() {
@Override
public void run() {
while (true) {
try {
ServiceFecade.doBusiness();
AsyncContext context;
while ((context = queue.poll()) != null) {
try {
ServletResponse response = context.getResponse();
PrintWriter out = response.getWriter();
out.printf("Bussiness done");
out.flush();
} catch (Exception e) {
throw new RuntimeException(e.getMessage(), e);
} finally {
context.complete();
}
}
} catch (InterruptedException e) {
return;
}
}
}
});
thread.start();
}
public static void add(AsyncContext c) {
queue.add(c);
}
@Override
public void contextDestroyed(ServletContextEvent servletContextEvent) {
thread.interrupt();
}
}