Async Servlet - preferred implementation

末鹿安然 提交于 2019-12-05 02:02:25

问题


Lately, during my research about asynchronous processing in Servlets, I came across at at least three ways to implement some functionality using this approach.

The questions are:

  1. Which one is the best?
  2. Maybe some of these approaches are not recommended?
  3. Maybe there is another one approach better than all of mentioned below?

Found approaches:

  1. Using AsyncContext.start(Runnable).

    This approach is quite simple and straightforward. But many serwers executes such a job in thread pool created for HTTP requests (more about it here http://www.nurkiewicz.com/2012/05/javaxservletservletrequeststartasync.html)

  2. Using custom threads pool created during Servlet context initialization

    (sample here: http://www.journaldev.com/2008/async-servlet-feature-of-servlet-3). But can I create my own threads in Servlet container? It was not recommended (or even prohibited) in EJB (before JavaEE7). Can I use JavaSE Executors or should I use ManagedExecutors from JavaEE7 (assuming that I use JavaEE7)?

  3. Using EJB and @Asynchronious annotation

    (example here: https://github.com/wildfly/quickstart/tree/master/servlet-async/src/main/java/org/jboss/as/quickstarts/servlet/async). But here I have no control over threads executing my task (i.e. how many thread should by created etc.)

I would by glad to hear your thoughts on this issue and your experience with AsyncContext.


回答1:


All will have the same performance, at the backend all threads are replacing the request processing thread to another thread, so that more requests can be served.

Below you'll find a simple implementation:

@WebServlet(urlPatterns = "/AsyncLongRunningServlet", asyncSupported = true)
public class AsyncLongRunningServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;

    protected void doGet(HttpServletRequest request,
        HttpServletResponse response) throws ServletException, IOException {
        System.out.println("Request Processing Thread "+Thread.currentThread().getName());

        request.setAttribute("org.apache.catalina.ASYNC_SUPPORTED", true);
        response.setContentType("text/html");
        PrintWriter printWriter=response.getWriter();
        printWriter.println("<html><head><title>Asynchronous servlet</title></head><body>");
        printWriter.println("Request Processing Thread "+Thread.currentThread().getName());
        printWriter.println("<br>");
        printWriter.println("<progress id='progress' max='100')></progress>");
        printWriter.println("<br>");

        AsyncContext asyncCtx = request.startAsync();
        asyncCtx.addListener(new AppAsyncListener());
        asyncCtx.setTimeout(12000);
        //release of request processing thread
        asyncCtx.start(() ->{
            printWriter.println("<br>");
            printWriter.println("Async thread Name "+Thread.currentThread().getName());
            printWriter.println("<br>");

            int i=0;
            while(i<100)
            {
                printWriter.println("<script>document.getElementById('progress').value=\""+i+"\";</script>");
                printWriter.flush();
                try {
                    Thread.sleep(100);
                } catch (Exception e) {
                }
                i++;
            }
            printWriter.println("</body></html>");
            asyncCtx.complete();
        }

    );
        printWriter.println("<br>");
        printWriter.println("End of response");
    }

}



package com.journaldev.servlet.async;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.AsyncEvent;
import javax.servlet.AsyncListener;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebListener;

@WebListener
public class AppAsyncListener implements AsyncListener {

    @Override
    public void onComplete(AsyncEvent asyncEvent) throws IOException {
        System.out.println("AppAsyncListener onComplete");
        // we can do resource cleanup activity here
    }

    @Override
    public void onError(AsyncEvent asyncEvent) throws IOException {
        System.out.println("AppAsyncListener onError");
        //we can return error response to client
    }

    @Override
    public void onStartAsync(AsyncEvent asyncEvent) throws IOException {
        System.out.println("AppAsyncListener onStartAsync");
        //we can log the event here
    }

    @Override
    public void onTimeout(AsyncEvent asyncEvent) throws IOException {
        System.out.println("AppAsyncListener onTimeout");
        //we can send appropriate response to client
        ServletResponse response = asyncEvent.getAsyncContext().getResponse();
        PrintWriter out = response.getWriter();
        out.write("TimeOut Error in Processing");
    }

}


来源:https://stackoverflow.com/questions/23240497/async-servlet-preferred-implementation

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!