错误找不到或加载主类 [英] Error Could not find or load main class

查看:152
本文介绍了错误找不到或加载主类的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个嵌入式的jetty java应用程序,该应用程序会自行启动并在上述路由中处理请求.在测试时,它运行良好.现在,我想通过war文件部署此Java应用程序,这给了我很多问题.

I have a embedded jetty java application, which starts itself up and serving requests at the mentioned routes. While testing it is working good. Now that I want to deploy this java application via war file it is giving me issues.

  1. 运行java -jar server--1.0-SNAPSHOT.war时:它给我Error: Could not find or load main class com.server.core.App

此问题将在解决第一期问题后发布,该问题如何将所有依赖项包含到war文件中.

This one will come after the 1st issue is fixed, how to include all the dependencies into the war file.

这是我的 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不知道在这里设置什么.我的课程默认情况下转到目标目录(使用IDEA Intellij). mainClass确实存在于同一路径上.

Where I might have messed up: The classpathPrefix not sure what to set here. My classes goes to target dir as default (Using IDEA Intellij) . The mainClass does exist on the same path.

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();
        }
    }
}

有很多与此类似的问题,但在此用例中找不到.

There are lot of questions similar to this but couldn't find for this use-case.

推荐答案

使用Jetty可以执行自执行的WAR,但是设置起来有些棘手,因为各种Maven插件都倾向于撤消自执行WAR的工作.

A self executing WAR with Jetty is possible, however its a bit tricky to setup, as the various maven plugins tend to undo the efforts of a Self Executing WAR.

Jetty项目维护着一个示例项目.

The Jetty Project maintains such an example project.

https://github.com/jetty-project/embedded-jetty-实战

关键是它的组装方式.

该项目包含4个主要部分:

The project has 4 main parts:

  • /thewebapp/-这是WAR文件,即webapp,它以其原始格式存在,具有正常的maven战争,并且产生的工件仅是尚未(尚未)自执行的WAR文件. /li>
  • /theserver/-这是嵌入式Jetty服务器jetty.livewar.ServerMain.main(String args[]),您可以对其进行自定义以初始化Jetty服务器及其WebApp.您还可以在该项目中自定义JDBC服务器库,JNDI,日志记录等内容.此项目将生成一个uber-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客户端无法访问它们.
  • /thewebapp/ - this is the WAR file, the webapp, as it exists in its native format, with normal maven war and a produced artifact that is just a WAR file that isn't (yet) self-executing.
  • /theserver/ - this is the Embedded Jetty Server jetty.livewar.ServerMain.main(String args[]) which you customize to initialize your Jetty server and its WebApp. This project also is the place where you customize for things like JDBC servers libraries, JNDI, logging, etc. This project produces a uber-jar with all of the dependencies needed to run the server. Special care is taken with the maven-shade-plugin to merge META-INF/services/ files.
  • /server-bootstrap/ - this contains 2 small classes that sets up a LiveWarClassLoader from the content in the live WAR and then runs jetty.livewar.ServerMain.main(String args[]) from this new ClassLoader. This project also contains the live META-INF/MANIFEST.MF that the live WAR will need/use
  • /livewar-assembly/ - this is the project that ties together the above 3 projects into a Live/Executable WAR file. The artifacts from from the above 3 projects are unpacked by the maven-assembly-plugin and put into place where they will be most functional (and safe). For example, the server classes from /theserver/ are placed in /WEB-INF/jetty-server/ to make them inaccessible from Web Clients accessing the WAR file.

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

Note: there are 3 files present in your new assembled WAR file that you should be aware of, as these files can be downloaded by a Web Client as static content if you use this setup.

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

示例项目的设置方式应确保这些引导文件中存在的信息不应泄露有关您的服务器或其操作的私人或敏感信息.仅仅是Webapp可以作为实时/可执行WAR文件启动.

The example project is setup in such a way that information present in these bootstrap files should not reveal private or sensitive information about your Server or its operations. Merely that the Webapp can be started as a Live/Executable WAR file.

有4个模块产生1个可执行工件可能看起来很奇怪,但是您必须了解要处理3件事情才能设置此环境.

It might seem strange to have 4 modules result in 1 executable artifact, but you have to understand you are dealing with 3 things to set this environment up.

  1. WebApp本身(及其所有类和jar)-这是/thewebapp/
  2. 代表服务器主体的类及其要求. (不要与WebApp类混合在一起)-这是/theserver/
  3. Main-Class可执行文件,将上述2种智能地绑定在一起(以免给自己造成安全问题)-这是/server-bootstrap/
  1. The WebApp itself (with all of its classes and jars) - this is /thewebapp/
  2. The Classes representing the Server Main, and its requirements. (not to be co-mingled with the WebApp classes) - this is /theserver/
  3. The Main-Class executable that binds the above 2 together intelligently (so as to not create a security issue for yourself) - this is /server-bootstrap/

最后一个模块/livewar-assembly/只是将3个部分捆绑为一个统一的整体.

The final module, /livewar-assembly/ just ties together the 3 parts into a unified whole.

我知道可能全部使用maven-shade-plugin可能很诱人,但是您将无法满足以下所有要求(您可以满足其中一些要求,然后尝试为其他要求解决,但最终打破别人,玩无休止的古怪游戏)...

I know it might be tempting to use maven-shade-plugin for it all, but you will not be able to accomplish all of the following requirements (you can accomplish some of them, and then attempt to fix for the others, but ultimately break the others, playing an endless game of wack-a-mole) ...

  1. 将服务器jar放置在无法通过Live WebApp访问的位置.
  2. 智能地合并服务器端(并且仅限服务器端)META-INF/services.
  3. 将BootStrap类添加到WAR的根中.
  4. 使用用于引导程序的自定义META-INF/MANIFEST.MF(也不会从所有服务器依赖项中获取META-INF/MANIFEST.MF文件的合并副本)
  1. Placing the Server jars in a place where they cannot be accessed via the Live WebApp.
  2. Merging Server side (and ONLY the server side) META-INF/services intelligently.
  3. Adding the BootStrap classes to the root of the WAR.
  4. Using a custom META-INF/MANIFEST.MF meant for the bootstrap (without also getting a merged copy of the META-INF/MANIFEST.MF files from all of the Server dependencies)

这篇关于错误找不到或加载主类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆