Как использовать Servlet 3 @WebServlet & async с помощью Spring MVC 3?

Я хотел бы интегрировать поддержку асинхронного сервлета 3.0 с помощью spring MVC. Что-то вроде:

@RequestMapping("/chat")
@WebServlet(name="myServlet", asyncSupported=true)
public String getMessage(String userName) {
      ......
}

Возможно ли это?

Ответ 1

Не так быстро, не так просто реализовать хороший длинный опрос. Метод, о котором вы говорили, работает хорошо, но есть серьезная проблема "голодания нитью"

Каждый длинный опрос будет использовать один поток, если у вас есть 1000 одновременных пользователей, вам понадобится 1000 потоков для обслуживания длинного запроса опроса (который большую часть времени обновляет статус сервера на клиентском браузере)

Jetty 6 имеет шаблон продолжения, который умело освобождает поток длинного запроса на опрос, который будет использоваться реальной логикой приложения.

Ответ 2

Пока не реализовано в Spring Framework 3.x. См. https://jira.springframework.org/browse/SPR-5587 и https://jira.springsource.org/browse/SPR-8517

Если вам нужна поддержка кометы (long-poll ajax), вы можете "попробовать" CometD (http://cometd.org/documentation/cometd-java/server/services/integration-spring). Но я предупреждаю вас, что я его бросил, это просто раздулось! (Такая простая вещь, как длительный опрос, требует дней конфигурации?!)

Я бы просто реализовал себе некоторые контроллеры RESTful в Spring3 и запрограммировал себе длинный опрос. Сделайте свой запрос типа Ajax на сервер, ваш контроллер держит его открытым, пока у сервера нет новых данных для отправки в браузер. Браузер инициирует новый длинный запрос опроса, чтобы получить последующие события. Чтобы избежать тайм-аутов соединений, просто возвращайте фиктивные значения, которые заставляют клиента повторять запрос.

Обычный простой способ - это наиболее оптимальные решения.

Ответ 3

Вопрос довольно старый, но все еще без ответа. Автору нужна поддержка async в Spring MVC, и решение по-прежнему не задано.

Как было сказано в предыдущем ответе, запрос поддержки async был отправлен в Spring community bugtracker и должен был быть реализован в Spring 3.1.0. Это было выпущено недавно, но в соответствии с примечаниями к выпуску "Servlet 3.0 support" планируется сделать в версии 3.2.0: https://jira.springsource.org/browse/SEC-1685

Мне нужно очень эффективное COMET для моего приложения. Моя текущая реализация основана на следующем примере: http://code.google.com/p/jquery-stream/wiki/EchoExample, но мне интересно переместить его в контроллер Spring MVC. На данный момент я только что улучшил пример и вручную ввел туда Spring beans, чтобы разрешить связь с остальной частью приложения. У меня были некоторые проблемы с этим, описанные в моем вопросе: Неудача обработки Tomcat 7 Async - только один запрос обрабатывался одновременно. На данный момент он работает нормально.

Я нашел пример, в котором используются решения jboss: http://docs.jboss.org/resteasy/docs/1.0.0.GA/userguide/html/Asynchronous_HTTP_Request_Processing.html, но использование jboss для меня не является решением. JBoss слишком велик, слишком медленный и слишком сложный, чтобы развиваться.

Ответ 5

Поддержка ассемблера Servlet 3.0 в настоящее время рассматривается. Если у вас есть конкретные сценарии, которые вы хотели бы увидеть, прокомментируйте в SPR-8517 или просмотрите билет и следуйте дискуссиям.

Ответ 6

Да, вы можете использовать сейчас. Вы должны добавить класс ApplicationInitializer, который расширяет класс AbstractAnnotationConfigDispatcherServletInitializer.

package co.tellmehow.config
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
public class ApplicationInitializer extends
AbstractAnnotationConfigDispatcherServletInitializer {

  @Override
    protected Class<?>[] getRootConfigClasses () {
        return null;
    }

    @Override
    protected Class<?>[] getServletConfigClasses () {
        return new Class<?>[]{ApplicationWebConfig.class};
    }
    @Override
    protected String[] getServletMappings () {
        return new String[]{"/"};
    }
}

Мы хотим расширить класс AbstractAnnotationConfigDispatcherServletInitializer, который используется, когда иерархия контекста приложения не требуется, приложения могут возвращать всю конфигурацию через getRootConfigClasses() и возвращать значение null из getServletConfigClasses().

Теперь вы можете использовать аннотацию @WebServlet с приложением Spring.

Полный исходный код с пояснениями представлен здесь.

@WebServlet(name = "myServlet", urlPatterns = "/myServlet")
public class MyServlet extends HttpServlet {


    private static final long serialVersionUID = 7088410241741084414L;

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

        System.out.println("-- In MyServlet --");
        PrintWriter writer = resp.getWriter();
        writer.println("Tell Me How: MyServlet running now");
    }
}