Background process in Servlet [duplicate]

2020-06-06 06:48发布

问题:

Is it possible to implement a background process in a servlet!?

Let me explain. I have a servlet that shows some data and generate some reports. The generation of the report implies that the data is already present, and it is this: someone else upload these data.

In addition to report generation, I should implement a way to send an email on arrival of new data (uploaded).

回答1:

The functional requirement is unclear, but to answer the actual question: yes, it's possible to run a background process in servletcontainer.

If you want an applicationwide background thread, use ServletContextListener to hook on webapp's startup and shutdown and use ExecutorService to run it.

@WebListener
public class Config implements ServletContextListener {

    private ExecutorService executor;

    public void contextInitialized(ServletContextEvent event) {
        executor = Executors.newSingleThreadExecutor();
        executor.submit(new Task()); // Task should implement Runnable.
    }

    public void contextDestroyed(ServletContextEvent event) {
        executor.shutdown();
    }

}

If you're not on Servlet 3.0 yet and thus can't use @WebListener, register it as follows in web.xml instead:

<listener>
    <listener-class>com.example.Config</listener-class>
</listener>

If you want a sessionwide background thread, use HttpSessionBindingListener to start and stop it.

public class Task extends Thread implements HttpSessionBindingListener {

    public void run() {
        while (true) {
            someHeavyStuff();
            if (isInterrupted()) return;
        }
    }

    public void valueBound(HttpSessionBindingEvent event) {
        start(); // Will instantly be started when doing session.setAttribute("task", new Task());
    }

    public void valueUnbound(HttpSessionBindingEvent event) {
        interrupt(); // Will signal interrupt when session expires.
    }

}

On first creation and start, just do

request.getSession().setAttribute("task", new Task());


回答2:

Thank you! I was wondering whether this should be better done inside of an request scope like:

public class StartServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {                   
        request.getSession().setAttribute("task", new Task());     
    }
}

This way, the process is stopped when the user leaves the page.