当我在 VSCode 中 运行 时程序 运行 没问题,但是 Maven 扩展构建的包没有 运行

Program runs fine when I run in VSCode, but the package the maven extension builds doesn't run

背景:我正在使用 VS Code 和 VS Code Java 扩展包(其中包括一个 maven 扩展)编写一个使用 htmlunit 的项目。目前,我只是在使用别人的代码,看看能否让我的环境正常工作。我是 Maven 和 VS Code 的菜鸟,也是 Java.

的半菜鸟

当我 运行 我的程序使用 VS Code 运行 选项卡时,它 运行 符合预期*。当我使用 maven package 命令构建可执行 jar 时,jar 构建正常但是当我 运行 它与 java -jar ___.jar 我得到一个错误:

Exception in thread "main" java.lang.NoClassDefFoundError: com/gargoylesoftware/htmlunit/FailingHttpStatusCodeException
        at reliant.Main.main(Main.java:44)
Caused by: java.lang.ClassNotFoundException: com.gargoylesoftware.htmlunit.FailingHttpStatusCodeException
        at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:581)
        at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:178)
        at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:522)
        ... 1 more 

这是使用 htmlunit 的代码:

package reliant; //I know now this is not how package naming conventions work, but I don't think it causes a problem
import java.io.IOException;

import com.gargoylesoftware.htmlunit.BrowserVersion;
import com.gargoylesoftware.htmlunit.FailingHttpStatusCodeException; //the import that seems to be buggy
import com.gargoylesoftware.htmlunit.WebClient;
import com.gargoylesoftware.htmlunit.html.HtmlForm;
import com.gargoylesoftware.htmlunit.html.HtmlPage;

public class RedditClient {
    
    private final WebClient CLIENT = new WebClient(BrowserVersion.CHROME);
    private final String username;
    private char[] password;

    public RedditClient(String username, char[] password) {
        this.username = username;
        this.password = password;
     
        CLIENT.getCookieManager().setCookiesEnabled(true);
    }

    public void checkLogin() {
        System.out.println(username + ", " + new String(password));
    }

    public void login() {
        String loginURL = "https://www.reddit.com/login";

        try {
            HtmlPage loginPage = CLIENT.getPage(loginURL);

            HtmlForm loginForm = loginPage.getFirstByXPath("//form[@id='login-form']");
            //System.out.println(loginPage.getWebResponse().getContentAsString());
            loginForm.getInputByName("user").setValueAttribute(username);
            loginForm.getInputByName("passwd").setValueAttribute(new String(password));

            loginForm.getElementsByTagName("button").get(0).click();

        } catch (FailingHttpStatusCodeException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } 
    }

    public String getHTML(String url) {
        try {
            return CLIENT.getPage(url).getWebResponse().getContentAsString();
        } catch (FailingHttpStatusCodeException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

        return null;
    }

    public void close() {
        CLIENT.close();
    }
}

这里是 Main.java 的第 44 行:

RedditClient c = new RedditClient(username, password);

这对我来说似乎是正确的,我将 htmlunit 添加到我的 maven 依赖项中。如果你愿意,我可以给你看一个 Maven 依赖项的屏幕截图,但我现在省略了它,因为它有点 long/hard 难以阅读。

这是 pom 文件:

<?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>reliant</groupId>
  <artifactId>redditlogin</artifactId>
  <version>2.0</version>

  <name>redditlogin</name>
  <!-- FIXME change it to the project's website -->
  <url>http://www.example.com</url>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>11</maven.compiler.source>
    <maven.compiler.target>11</maven.compiler.target>
  </properties>

  <dependencies>

    <dependency>
      <groupId>htmlunit</groupId>
      <artifactId>htmlunit</artifactId>
      <version>1.14</version>
    </dependency>


   <dependency>
     <groupId>org.jsoup</groupId>
     <artifactId>jsoup</artifactId>
     <version>1.13.1</version>
   </dependency>


    <dependency>
      <groupId>net.sourceforge.htmlunit</groupId>
      <artifactId>htmlunit</artifactId>
      <version>2.41.0</version>
    </dependency>

    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.11</version>
      <scope>test</scope>
    </dependency>
  </dependencies>

  <build>
    <pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
      <plugins>
        <!-- clean lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#clean_Lifecycle -->
        <plugin>
          <artifactId>maven-clean-plugin</artifactId>
          <version>3.1.0</version>
        </plugin>
        <!-- default lifecycle, jar packaging: see https://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_jar_packaging -->
        <plugin>
          <artifactId>maven-resources-plugin</artifactId>
          <version>3.0.2</version>
        </plugin>
        <plugin>
          <artifactId>maven-compiler-plugin</artifactId>
          <version>3.8.0</version>
        </plugin>
        <plugin>
          <artifactId>maven-surefire-plugin</artifactId>
          <version>2.22.1</version>
        </plugin>
        <plugin>
          <artifactId>maven-jar-plugin</artifactId>
          <version>3.0.2</version>
          <configuration>
            <archive>
              <manifest>
                <addClasspath>true</addClasspath>
                  <mainClass>reliant.Main</mainClass>
              </manifest>
            </archive>
          </configuration>
        </plugin>
        <plugin>
          <artifactId>maven-install-plugin</artifactId>
          <version>2.5.2</version>
        </plugin>
        <plugin>
          <artifactId>maven-deploy-plugin</artifactId>
          <version>2.8.2</version>
        </plugin>
        <!-- site lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#site_Lifecycle -->
        <plugin>
          <artifactId>maven-site-plugin</artifactId>
          <version>3.7.1</version>
        </plugin>
        <plugin>
          <artifactId>maven-project-info-reports-plugin</artifactId>
          <version>3.0.0</version>
        </plugin>
      </plugins>
    </pluginManagement>
  </build>
</project>

jar 文件出错但 运行在 VS Code 中按预期进行*这一事实对我来说毫无意义。

此外,在不相关的说明中,为什么“class 未找到”错误是 运行 时错误?为什么maven能够成功构建包?

*我说“符合预期”是因为我正在使用的代码中存在错误,但这是一个非常具体的 运行 时间错误。基本上,我使用的代码旨在在 reddit 获得 OAuth 之前登录到 reddit,所以现在尝试获取登录表单 returns null 的行并破坏了它的其余部分。关键是,我看不出为什么在 VS Code 中 运行ning 与在 jar 中 运行ning 应该有任何不同的结果。我什至不知道从哪里开始这样的事情。

感谢您的帮助,如果我可以添加任何内容以使这个问题更容易回答,请告诉我。

好吧,事实证明这很愚蠢。基本上,类路径列出了我的依赖项(因为我如何设置 pom)但这并不意味着它指定了这些依赖项的路径。事实上,它根本没有指定路径,所以每当 java 尝试 运行 jar 时,它都会在当前目录中查找依赖项。我知道这是因为当我将依赖项与 jar 放在同一目录中时,它起作用了。这里更好的解决方案是修改 pom 以向类路径添加前缀,以便 java 知道在哪里可以找到依赖项。不幸的是,我的依赖项在不同的地方,所以这对我来说不是一个真正的选择;相反,我将尝试找出如何制作 fat/uber 罐子。