Асинхронные сервлеты Java

Асинхронные сервлеты JavaДо сих пор вы видели, что можете преобразовать любой метод компонента в асин­хронный метод. Теперь вы увидите, как заставить асинхронно функционировать
сервлет. Без наличия асинхронной поддержки в сервлетах нелегко отвечать требо­ваниям асинхронности при веб-разработке.

Спецификация Servlet 3.0 (JSR 315) внесла серьезные усовершенствования в интерфейсы программирования веб-приложений (API) языка Jаvа. С появлени­ем JSR 315 спецификации сервлетов были обновлены (после длительного ожида­ния) для поддержки асинхронной модели выполнения, удобной конфигурации, подключаемости и других мелких улучшений.

Асинхронные сервлеты основываются на ключевом усовершенствовании в HyperText Traпsfer Protocol (НТТР) 1.1, сделавшем возможными постоянные со­единения. В НТТР 1.0 каждое соединение использовалось для отправки и получения только одной пары "запрос/ответ"; в то же время НТТР 1.1 позволяет веб-приложе­ниям поддерживать соединение в активном состоянии и посылать множественные запросы.

При стандартной реализации прикладная часть Java потребовала бы от­дельного потока, постоянно прикрепленного к НТТР-соединению. Однако небло­кирующее API ввода-вывода языка Java (Java Nonblocking I/O, NIO) возвращает между активными запросами потоки "в оборот" благодаря новым возможностям NIO. На сегодняшний день все совместимые со спецификациями Servlet 3.0 веб­ серверы имеют встроенную поддержку Java NIO.

Асинхронные сервлеты JavaДля чего вам может понадобиться от сервлетов подобное поведение? Для сер­верных систем характерны длительные операции, такие как соединение с другими серверами, выполнение сложных вычислений и осуществление операций транзак­ционных баз данных. Однако сущность веб-страниц требует как раз обратного.

Веб-пользователи ожидают короткого времени отклика и UI, функционирующего даже в случае незавершенных операций серверной части. AJАХ взял на себя ре­шение этой проблемы для браузеров и начал революцию Web 2.0.

Спецификация Servlet 3.0 предоставила метод startAsync(), сделавший доступными асинхронные операции. Следующий пример кода показывает пример этого:

//    startAsync()

package com.devchronicles.asynchronous;

import java.io.*;
import javax.servlet.*;
import javax.servlet.annotation.*;
import javax.servlet.http.*;

@WebServlet(urlPatterns={"/async"}, asyncSupported=true)
public class AsyncServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse res)
                         throws IOException, ServletException {

        final AsyncContext asyncContext = req.startAsync();
        final String data;

        asyncContext.addListened(new AsyncListener() {

            @Override
            public void onComplete(AsyncEvent event) throws IOException {
                 AsyncContext asyncContext = event.getAsyncContext();
                 asyncContext().getWriter().println(data);
            }

            @Override
            public void onTimeout(AsyncEvent event) throws IOException {

                //    

             }

             @Override
             public void onError(AsyncEvent event) throws IOException {

                 //    
 
              }

              @Override
              public void onStartAsync(AsyncEvent event) throws IOException {

                  //    

              }
       });

       new Thread() {

           @Override
           public void run() {
 
               asyncContext.complete();

           }

       }.start();

       res.getWriter().write("Results:");
       //     

       data = "Queried data...";

       //        ...
    }
}

Сервлет выводит Results: и далее выводит полученные из базы данные, кото­рыми в этом сценарии является простая строка. Вам необходимо инициализировать отдельный поток.

Метод onComplete класса Asynclistener выполняется только после завершения выполнения. В классе Asynclistener есть еще несколько методов жиз­ненного цикла.

  • OnStartAsync - выполняется при запуске асинхронного контекста;
  • OnTimeOut - выполняется, только если истекает время ожидания;
  • onError - выполняется, только если была получена ошибка.

Спецификация Servlet 3.1 предоставляет более простой способ реализации асинхронных сервлетов путем использования управляемых пулов потоков и сер­виса выполнения.

В следующем примере задействуется ManagedThreadFactory для создания нового потока.

//   ManagedThreadFactory
package com.devchronicles.asynchronous;

import java.io.*;
import javax.servlet.*;
import javax.servlet.annotation.*;
import javax.servlet.http.*;

@WebServlet(urlPatterns="/async", asyncSupported=true)

public class AsyncServlet extends HttpServlet {

    @Resource
    private ManagedThreadFactory factory;

    @Overrid
    protected void doGet(HttpServletRequest req, HttpServletResponse res)
                         throws ServletException, IOException {
        final AsyncContext asyncContext = req.startAsync();
        final PrintWriter writer = res.getWriter();

         Thread thread = factory.newThread(new Runnable() {

             @Override
             public void run() {
                 writer.println("Complete!");
                 asyncContext.complete();
             }
         });
         thread.start();
     }
}

Этот пример создает новый поток с процессом, требующим больших затрат времени, и наконец вызывает функцию complete из asyncContext. ManagedThreadFactory служит в качестве доступного потока из пула, который вам необходимо запустить явным образом.

Другой подход состоит в передаче ManagedExecutorServiсе асинхронного Runnable вместо создания и последующего запуска потока в сервлете. Делегирование ExecutorServiсе вопросов организации поточной обработки обеспечивает более "чистый" код, как вы увидите в следующем примере:

//   ExecutorService

package com.devchronicles.asynchronous;

import java.io.*;
import javax.servlet.*;
import javax.servlet.annotation.*;
import javax.servlet.http.*;

@WebServlet(urlPatterns="/async", asyncSupported=true)
public class AsyncServlet extends HttpServlet {

    @Resource

    private ManagedExecutorService executor;

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse res)
                         throws ServletException, IOException {

        final AsyncContext asyncContext = req.startAsync();
        final PrintWriter writer = res.getWriter();
        executor.submit(new Runnable() {
            @Override
            public void run() {

                writer.println("Complete!");
                asyncContext.complete();

            }
       });
}

Хотя это всего лишь на одну строку меньше, чем в предыдущем примере, программа делегирует создание и запуск потока ExecutorServiсе и имеет дело только с сервлетным кодом.

Асинхронные сервлеты легче для понимания и программирования и оказывают немедленный эффект на динамическое поведение, поскольку напрямую «переклю­чают» на модель асинхронного выполнения. Асинхронные сервлеты обеспечивают «чистую» реализацию без большого количества шаблонного кода.

Комментариев 3 на “Асинхронные сервлеты Java

  1. Спасибо тебе админушка за все.
    Твой проект самый лучший, очень помогает в осовении Java.
    Низкий тебе поклон.
    Мое уважение из Армении.

    • Привет Sucker.
      Рад помочь, заходи почаще, всегда публикуем интересные материалы.

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *