запуск подпроцесса jvm из веб-приложения war - PullRequest
1 голос
/ 30 марта 2012

У меня есть интересные настройки. У меня есть веб-приложение, которое регистрирует веб-сервис. По сути, веб-сервис является интерфейсом к множеству классов, которые выполняют следующее:

  1. настройка сервера RMI
  2. запустить подпроцесс, используя jvm с указанным классом, чтобы выполнить некоторую работу

Обычно для разрешения пути к классу я читаю System.getProperty ("java.class.path"); и я установил это для параметра -cp. Однако, с военными файлами это бесполезно.

Вот так выглядит моя функция, которая запускает определенный класс из пути к классам:

public static Process launchClassProcess(@SuppressWarnings("rawtypes") Class c, String[] javaArgs, String[] programArgs) throws Exception {
    String separator = System.getProperty("file.separator");
    String classpath = System.getProperty("java.class.path");
    String home = System.getProperty("java.home");
    String path = home + separator + "bin" + separator + "java";
    String[] jvmArgs = new String[] { path, "-cp", classpath };
    String[] classArgs = new String[] { c.getName() };
    String[] processBuilderArgs = new String[jvmArgs.length + javaArgs.length + classArgs.length + programArgs.length];
    int i = 0;

    for (String arg:jvmArgs) {
        processBuilderArgs[i++] = arg;
    }

    for (String arg:javaArgs) {
        processBuilderArgs[i++] = arg;
    }

    for (String arg:classArgs) {
        processBuilderArgs[i++] = arg;
    }

    for (String arg:programArgs) {
        processBuilderArgs[i++] = arg;
    }

    ProcessBuilder processBuilder = new ProcessBuilder(processBuilderArgs);
    StringBuilder command = new StringBuilder();
    int j = 0;

    for (String part:processBuilder.command()) {
        if (j++ != 0) {
            command.append(" ");
        }

        command.append(part);
    }

    LogUtils.recordMessage("executing: " + command.toString());

    processBuilder.redirectErrorStream(true);

    return (new ProcessBuilder(processBuilderArgs)).start();
}

Как я могу заставить эту функцию работать, но с файлами war? Я думаю, что мне нужно каким-то образом найти, где мой файл war был распакован в файловой системе, и найти папку libs, из которой я могу собрать полный путь к классам.

Ответы [ 2 ]

1 голос
/ 30 марта 2012

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

Нам нужен следующий сервлет, назовем его InitServlet

public class InitServlet extends HttpServlet {

    public void init() throws ServletException {
        String libRealPath = getServletContext().getRealPath("/WEB-INF/lib/");

        if (libRealPath == null) {
            throw new ServletException("cannot find web-inf lib path");
        }

        ArrayList<String> libs = new ArrayList<String>();
        File libDir = new File(libRealPath);

        for (String file:libDir.list(new FilenameFilter() {

            public boolean accept(File dir, String file) {
                return file.endsWith(".jar");
            }

        })) {
            libs.add(libRealPath + System.getProperty("file.separator") + file);
        }

        System.setProperty("java.class.path", System.getProperty("java.class.path") + System.getProperty("path.separator") + ProcessUtils.joinPaths(libs));
    }

}

Затем нам нужно зарегистрировать сервлет в web.xml, чтобы творить чудеса:

<servlet>
    <servlet-name>init-servlet</servlet-name>
    <servlet-class>InitServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
</servlet>
0 голосов
/ 30 марта 2012

Вы можете получить содержимое папки lib из ServletContext:

ServletContext context = ....;
Set< String > libs = context.getResourcePaths( "/WEB-INF/lib" );
...