当我在VSCode中运行时,程序运行正常,但是maven扩展构建的程序包未运行

时间:2020-06-25 20:49:31

标签: java maven visual-studio-code executable-jar htmlunit

背景:我正在使用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);

这似乎对我来说似乎正确,我在我的Maven依赖项中添加了htmlunit。如果需要的话,我可以向您展示Maven依赖关系的细节,但是由于它很长/很难阅读,因此我暂时将其省略。

这是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中运行按预期进行的事实对我来说毫无意义。

另外,在不相关的注释上,为什么“找不到类”错误是运行时错误?为什么Maven能够成功构建软件包?

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

谢谢您的帮助,请告诉我是否有什么可以添加的内容,以使此问题更易于回答。

1 个答案:

答案 0 :(得分:0)

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