错误无法找到或加载主类

时间:2015-09-21 07:46:50

标签: java maven maven-3 embedded-jetty

我有一个嵌入式jetty java应用程序,它启动并在上述路由上提供请求。虽然测试它运作良好。现在我想通过war文件部署这个java应用程序,它给了我一些问题。

  1. 正在运行java -jar server--1.0-SNAPSHOT.war:错误为Error: Could not find or load main class com.server.core.App

  2. 这个问题将在修复第一个问题之后出现,如何将所有依赖项包含在war文件中。

  3. 这是我的 pom.xml https://gist.github.com/shadow-fox/24ec2c7d40f4b0e6aae5

    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0                    http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
    
        <groupId>com.server</groupId>
        <artifactId>server</artifactId>
        <version>1.0-SNAPSHOT</version>
        <packaging>war</packaging>
    
        <dependencies>
            <dependency>
                <groupId>org.eclipse.jetty</groupId>
                <artifactId>jetty-server</artifactId>
                <version>${jetty-version}</version>
            </dependency>
    
            <dependency>
                <groupId>org.eclipse.jetty</groupId>
                <artifactId>jetty-servlet</artifactId>
                <version>${jetty-version}</version>
            </dependency>
    
            <dependency>
                <groupId>org.eclipse.jetty</groupId>
                <artifactId>jetty-util</artifactId>
                <version>${jetty-version}</version>
            </dependency>
    
            <dependency>
                <groupId>org.glassfish.jersey.containers</groupId>
                <artifactId>jersey-container-servlet-core</artifactId>
                <version>${jersey-version}</version>
            </dependency>
    
            <dependency>
                <groupId>org.glassfish.jersey.core</groupId>
                <artifactId>jersey-server</artifactId>
                <version>${jersey-version}</version>
            </dependency>
    
            <dependency>
                <groupId>org.glassfish.jersey.containers</groupId>
                <artifactId>jersey-container-jetty-http</artifactId>
                <version>${jersey-version}</version>
            </dependency>
    
            <dependency>
                <groupId>org.glassfish.jersey.media</groupId>
                <artifactId>jersey-media-moxy</artifactId>
                <version>${jersey-version}</version>
            </dependency>
    
            <dependency>
                <groupId>org.glassfish.jersey.core</groupId>
                <artifactId>jersey-client</artifactId>
                <version>${jersey-version}</version>
            </dependency>
    
            <dependency>
                <groupId>com.fasterxml.jackson.core</groupId>
                <artifactId>jackson-core</artifactId>
                <version>${jackson-version}</version>
            </dependency>
    
            <dependency>
                <groupId>com.fasterxml.jackson.core</groupId>
                <artifactId>jackson-databind</artifactId>
                <version>${jackson-version}</version>
            </dependency>
    
            <dependency>
                <groupId>com.fasterxml.jackson.core</groupId>
                <artifactId>jackson-annotations</artifactId>
                <version>${jackson-version}</version>
            </dependency>
    
            <dependency>
                <groupId>org.apache.logging.log4j</groupId>
                <artifactId>log4j-core</artifactId>
                <version>${log4j-version}</version>
            </dependency>
    
            <dependency>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
                <version>${junit-version}</version>
                <scope>test</scope>
            </dependency>
        </dependencies>
    
        <properties>
            <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
            <jdk-version>1.8</jdk-version>
            <jetty-version>9.3.3.v20150827</jetty-version>
            <jersey-version>2.21</jersey-version>
            <junit-version>4.12</junit-version>
            <jackson-version>2.6.1</jackson-version>
            <log4j-version>2.3</log4j-version>
            <mvn-compiler>3.3</mvn-compiler>
            <mvn-war>2.6</mvn-war>
        </properties>
    
        <build>
            <plugins>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-compiler-plugin</artifactId>
                    <version>${mvn-compiler}</version>
                    <configuration>
                        <source>${jdk-version}</source>
                        <target>${jdk-version}</target>
                    </configuration>
                </plugin>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-war-plugin</artifactId>
                    <version>${mvn-war}</version>
                    <configuration>
                        <failOnMissingWebXml>false</failOnMissingWebXml>
                        <archive>
                            <manifest>
                                <addClasspath>true</addClasspath>
                                <classpathPrefix>lib/</classpathPrefix>
                                <mainClass>com.server.core.App</mainClass>
                            </manifest>
                        </archive>
                    </configuration>
                </plugin>
            </plugins>
        </build>
    </project>
    

    我可能搞砸了:classpathPrefix不确定在这里设置什么。我的类默认为目标dir(使用IDEA Intellij)。 mainClass确实存在于同一条路径上。

    App.java

    package com.server.core;
    
    import com.server.core.filters.RequestFilter;
    
    import org.apache.logging.log4j.LogManager;
    import org.apache.logging.log4j.Logger;
    import org.eclipse.jetty.server.Server;
    import org.eclipse.jetty.server.ServerConnector;
    import org.eclipse.jetty.servlet.ServletContextHandler;
    import org.eclipse.jetty.servlet.ServletHolder;
    import org.glassfish.jersey.servlet.ServletContainer;
    
    import java.util.EnumSet;
    
    import javax.servlet.DispatcherType;
    
    public class App {
    
        private static final Logger logger = LogManager.getLogger(App.class);
    
        public static void main(String[] args) throws Exception {
    
            Server server = new Server();
            ServerConnector connector = new ServerConnector(server);
            connector.setPort(8080);
            server.addConnector(connector);
    
            ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS);
            context.setContextPath("/");
            context.addFilter(RequestFilter.class, "/*", EnumSet.of(DispatcherType.INCLUDE,
                    DispatcherType.REQUEST, DispatcherType.ASYNC, DispatcherType.ERROR,
                    DispatcherType.FORWARD));
            server.setHandler(context);
    
            ServletHolder servletHolder = new ServletHolder(ServletContainer.class);
            servletHolder.setInitOrder(0);
            servletHolder.setInitParameter("jersey.config.server.provider.packages", "com/server/core/endpoints");
            context.addServlet(servletHolder, "/*");
    
            try {
                server.start();
                logger.debug("Server started");
                logger.debug(server);
                server.join();
            } catch (Throwable t) {
                logger.error(System.err);
            } finally {
                server.destroy();
            }
        }
    }
    

    有很多类似的问题,但无法找到这个用例。

2 个答案:

答案 0 :(得分:0)

使用Jetty自行执行WAR是可能的,但设置起来有点棘手,因为各种maven插件倾向于撤消自执行WAR的工作。

Jetty项目维护着这样一个示例项目。

https://github.com/jetty-project/embedded-jetty-live-war

关键是如何组装。

该项目有4个主要部分:

  • /thewebapp/ - 这是WAR文件,即webapp,因为它以原生格式存在,具有正常的maven war和生成的工件,它只是一个不是自己的WAR文件-executing。
  • /theserver/ - 这是您自定义的嵌入式Jetty服务器jetty.livewar.ServerMain.main(String args[]),用于初始化您的Jetty服务器及其WebApp。此项目也是您自定义JDBC服务器库,JNDI,日志记录等内容的地方。此项目生成一个具有运行服务器所需的所有依赖项的超级jar。使用maven-shade-plugin特别注意合并META-INF/services/个文件。
  • /server-bootstrap/ - 这包含2个小类,它们从实时WAR中的内容设置LiveWarClassLoader,然后从这个新的ClassLoader运行jetty.livewar.ServerMain.main(String args[])。该项目还包含实时WAR需要/使用的实时META-INF/MANIFEST.MF
  • /livewar-assembly/ - 这是将上述3个项目绑定到Live / Executable WAR文件中的项目。来自上述3个项目的工件由maven-assembly-plugin解压缩并放置在最具功能性(且安全)的位置。例如,来自/theserver/的服务器类放在/WEB-INF/jetty-server/中,以使访问WAR文件的Web客户端无法访问它们。

注意:您应该注意新组装的WAR文件中有3个文件,因为如果您使用此设置,Web客户端可以将这些文件作为静态内容下载。

/jetty/bootstrap/JettyBootstrap.class
/jetty/bootstrap/LiveWarClassLoader.class
/META-INF/MANIFEST.MF

示例项目的设置方式使得这些引导程序文件中的信息不会泄露有关您的服务器或其操作的私有或敏感信息。仅仅是Web应用程序可以作为Live / Executable WAR文件启动。

让4个模块产生1个可执行工件可能看起来很奇怪,但你必须明白你正在处理3个事情来设置这个环境。

  1. WebApp本身(包含所有类和jar) - 这是/thewebapp/
  2. 表示Server Main的类及其要求。 (不要与WebApp类混合) - 这是/theserver/
  3. Main-Class可执行文件,智能地将上述2绑定在一起(以免给自己造成安全问题) - 这是/server-bootstrap/
  4. 最后一个模块/livewar-assembly/只是将这三个部分联系在一起。

    我知道使用maven-shade-plugin可能很有吸引力,但是你无法完成以下所有要求(你可以完成其中一些要求,然后尝试修复其他要求,但最终打破了其他人,玩了一场无休止的怪人游戏...... ...

    1. 将服务器jar放置在无法通过Live WebApp访问的位置。
    2. 智能地合并服务器端(仅限服务器端)META-INF/services
    3. 将BootStrap类添加到WAR的根目录。
    4. 使用适用于引导程序的自定义META-INF/MANIFEST.MF(不会从所有服务器依赖项中获取META-INF/MANIFEST.MF文件的合并副本)

答案 1 :(得分:-1)

更新::现在已经过时了。因为我已经开始了@ joakim-erdfelt的建议。 正如@Jens在评论中所提到的,我已经将包装从war更改为jar并使用maven-shaded-plugin我能够毫无问题地运行应用程序。 这是base::as.Date(42010, origin = "1900-01-01") ## [1] "2015-01-08" zoo::as.Date(42010, origin = "1900-01-01") ## [1] "2015-01-08"

的修改版本
pom.xml

请注意,我也已从插件列表中删除了maven-jar-plugin。