Создайте исполняемую войну (tomcat) с плагином maven и shadow

Я хочу создать исполняемый файл войны (java -jar x.war), который также можно развернуть на обычном сервере приложений, например Tomcat или JBoss.

Чтобы выполнить эту работу, мне нужно создать военный файл со структурой по умолчанию и файлами классов, расположенными в папке x.jar->WEB-INF/classes.

Поскольку я хочу включить все зависимости, я использую плагин maven-shade для создания uber-войны.

Q1: Как сделать так, чтобы подключаемый модуль Shade находил все классы в каталоге /WEB-INF/classes, а не в корневой папке war-файла?

Q2: как мне нужно установить путь к классам в МАНИФЕСТЕ, чтобы сделать его работоспособным и не создавать исключение ClassNotFoundException?

Заранее спасибо, Нео


person NeoP5    schedule 01.06.2015    source источник


Ответы (1)


Хорошо, я нашел решение и опишу его здесь для других, у которых такая же проблема. Надеюсь, это может помочь кому-то.

Зависимости

<dependency>
    <groupId>org.eclipse.jetty</groupId>
    <artifactId>jetty-webapp</artifactId>
    <version>8.1.17.v20150415</version>
</dependency>
<dependency>
    <groupId>org.eclipse.jetty</groupId>
    <artifactId>jetty-plus</artifactId>
    <version>8.1.16.v20140903</version>
</dependency>

Настройки сборки

<build>
    <plugins>
        <plugin>
            <artifactId>maven-antrun-plugin</artifactId>
            <executions>
                <execution>
                    <id>classes-copy</id>
                    <phase>prepare-package</phase>
                    <configuration>
                        <tasks>
                            <move
                                todir="${project.build.directory}/${project.artifactId}-${project.version}/">
                                <fileset dir="${project.build.directory}/classes/">
                                    <include name="**/warLauncher/**" />
                                    <include name="log4j.xml" />
                                </fileset>
                            </move>
                        </tasks>
                    </configuration>
                    <goals>
                        <goal>run</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-dependency-plugin</artifactId>
            <version>2.3</version>
            <executions>
                <execution>
                    <id>jetty-classpath</id>
                    <phase>prepare-package</phase>
                    <goals>
                        <goal>unpack-dependencies</goal>
                    </goals>
                    <configuration>
                        <includeGroupIds>org.eclipse.jetty,javax.servlet,org.slf4j,log4j,org.log4j</includeGroupIds>
                        <outputDirectory>${project.build.directory}/${project.artifactId}-${project.version}</outputDirectory>
                        <excludes>**\/ECLIPSEF.*</excludes>
                    </configuration>
                </execution>
            </executions>
        </plugin>
        <plugin>
            <artifactId>maven-war-plugin</artifactId>
            <version>2.6</version>
            <configuration>
                <warName>${project.artifactId}-${project.version}</warName>
                <warSourceDirectory>src\main\webapp\WEB-INF</warSourceDirectory>
                <webXml>src\main\webapp\WEB-INF\web.xml</webXml>
                <archive>
                    <manifest>
                        <mainClass>your.package.warLauncher.WarLauncher</mainClass>
                        <addClasspath>true</addClasspath>
                    </manifest>
                </archive>
            </configuration>
            <executions>
                <execution>
                    <id>default-war</id>
                    <phase>package</phase>
                    <goals>
                        <goal>war</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

Классы

WarLauncher

package your.package.warLauncher;

import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.server.Handler;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.bio.SocketConnector;
import org.eclipse.jetty.server.handler.ContextHandlerCollection;
import org.eclipse.jetty.server.handler.HandlerCollection;

public class WarLauncher{

  public static void main(String[] args) throws Exception {
      JettyServerContext context = new JettyServerContext();
      Server server = new Server();

      // Create connector
      SocketConnector connector = new SocketConnector();
      connector.setMaxIdleTime(1000 * 60 * 60);
      connector.setSoLingerTime(-1);
      connector.setPort(8080);

      // Create handler collection
      ContextHandlerCollection contextHandlerCollection = new   ContextHandlerCollection();
      HandlerCollection handlerCollection = new HandlerCollection();
      handlerCollection.setHandlers(new Handler[] { contextHandlerCollection });

      // Add webapp context
      context.setServer(server);
      contextHandlerCollection.addHandler(context);

      server.setConnectors(new Connector[] { connector });
      server.setHandler(handlerCollection);
      server.start();
  }
}

Контекст JettyServer

package your.package.warLauncher;

import java.net.URL;
import java.security.ProtectionDomain;

import org.eclipse.jetty.webapp.WebAppContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class JettyServerContext extends WebAppContext {

  private static Logger logger = LoggerFactory.getLogger(JettyServerContext.class);

  protected static final String[] JETTY_PLUS_CONFIGURATION_CLASSES;

  static {
    JETTY_PLUS_CONFIGURATION_CLASSES = new String[7];
    JETTY_PLUS_CONFIGURATION_CLASSES[0] = "org.eclipse.jetty.webapp.WebInfConfiguration";
    JETTY_PLUS_CONFIGURATION_CLASSES[1] = "org.eclipse.jetty.webapp.WebXmlConfiguration";
    JETTY_PLUS_CONFIGURATION_CLASSES[2] = "org.eclipse.jetty.webapp.MetaInfConfiguration";
    JETTY_PLUS_CONFIGURATION_CLASSES[3] = "org.eclipse.jetty.webapp.FragmentConfiguration";
    JETTY_PLUS_CONFIGURATION_CLASSES[4] = "org.eclipse.jetty.plus.webapp.EnvConfiguration";
    JETTY_PLUS_CONFIGURATION_CLASSES[5] = "org.eclipse.jetty.plus.webapp.PlusConfiguration";
    JETTY_PLUS_CONFIGURATION_CLASSES[6] = "org.eclipse.jetty.webapp.JettyWebXmlConfiguration";
  }

  public JettyServerContext() {
    setConfigurationClasses(JETTY_PLUS_CONFIGURATION_CLASSES);
    setContextPath("/");
    setWar(getWarLocation());
  }

  /**
   * Returns the location of the war (a trick, which is necessary for executable
   * wars please see: <a target="_blank" href=
   * "http://uguptablog.blogspot.de/2012/09/embedded-jetty-executable-war-with.html"
   * >Embedded Jetty with executable WAR</a>).
   * 
   * @return The war location.
   */
  protected String getWarLocation() {
    ProtectionDomain protectionDomain = JettyServerContext.class.getProtectionDomain();
    URL location = protectionDomain.getCodeSource().getLocation();
    return location.toExternalForm();
  }
}
person NeoP5    schedule 15.04.2016