Java类中启动长时间运行的进程

项目中有时需要在Java类中启动一个长时间运行的服务进程(监听进程、监控进程等),且该进程需要在tomcat启动时启动,在tomcat停止时退出。在项目开发的过程中,我需要在Java类中启动一个监听进程,而在该进程成功启动后,一调用该监听服务进程时,该进程就挂掉(退出),现将解决方法记录如下。

ServletContextListener接口能够接收到web context初始化和销毁的消息事件,因此我们可以在该接口中事件长时间运行进程的启动和停止。代码如下:

public class MyContextListener implements ServletContextListener {    @Override    public void contextInitialized(ServletContextEvent sce) {        ClassLoader classLoader = Thread.currentThread()                .getContextClassLoader();        String scriptPath = classLoader.getResource("daemon.sh")                .getPath();        List<String> commandsList = new ArrayList<String>();        commandsList.add("sh");        commandsList.add(scriptPath);        commandsList.add("start");        ProcessBuilder processBuilder = new ProcessBuilder(commandsList);        try {            Process process = processBuilder.start();            //以下两行代码是关键            ServletContext servletContext = sce.getServletContext();            servletContext.setAttribute("daemon", process);            int exitValue = process.waitFor();            if (0 == exitValue) {                System.out.println("start daemon success.");            } else {                System.out.println("start daemon failed, exitValue: " + exitValue);            }        } catch (IOException e) {            // TODO Auto-generated catch block            e.printStackTrace();        } catch (InterruptedException e) {            // TODO Auto-generated catch block            e.printStackTrace();        }    }    @Override    public void contextDestroyed(ServletContextEvent sce) {        ClassLoader classLoader = Thread.currentThread()                .getContextClassLoader();        String scriptPath = classLoader.getResource("daemon.sh")                .getPath();        List<String> commandsList = new ArrayList<String>();        commandsList.add("sh");        commandsList.add(scriptPath);        commandsList.add("stop");        ProcessBuilder processBuilder = new ProcessBuilder(commandsList);        try {            Process process = processBuilder.start();            int exitValue = process.waitFor();            if (0 == exitValue) {                System.out.println("stop daemon success.");            } else {                System.out.println("stop daemon failed, exitValue: " + exitValue);            }        } catch (IOException e) {            // TODO Auto-generated catch block            e.printStackTrace();        } catch (InterruptedException e) {            // TODO Auto-generated catch block            e.printStackTrace();        }    }}

然后需要在web.xml的所有filtersservlets定义之前定义:

<listener>    <listener-class>org.readus.executescript.MyContextListener</listener-class></listener>

如果使用Spring,则可使用如下设置代替上面的listener-class:

<listener>    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class></listener>

在上述的实现中,最重要的概括为两点:

实现了ServletContextListener的接口将生成的长时间运行的进程写入ServletContext的属性中

Java中使用ServletContextListener接口来监听web应用的生命周期变化。其中包含的两个接口:

public void contextInitialized(ServletContextEvent sce);

该接口文档说明如下:

Receives notification that the web application initialization process is starting.All ServletContextListeners are notified of context initialization before any filters or servlets in the web application are initialized. @param sce the ServletContextEvent containing the ServletContext that is being initialized.

public void contextDestroyed(ServletContextEvent sce);

该接口的文档说明如下:

Receives notification that the ServletContext is about to be shut down. All servlets and filters will have been destroyed before any ServletContextListeners are notified of context destruction. @param sce the ServletContextEvent containing the ServletContext that is being destroyed.

本文所涉及的代码托管在了GitHub上ExecuteScriptDemo.

Java类中启动长时间运行的进程

相关文章:

你感兴趣的文章:

标签云: