背景:我正在使用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会有任何不同的结果。我什至不知道从哪里开始这样的事情。
谢谢您的帮助,请告诉我是否有什么可以添加的内容,以使此问题更易于回答。
答案 0 :(得分:0)
好吧,事实证明这很愚蠢。基本上,类路径列出了我的依赖项(因为我如何设置pom),但这并不意味着它指定了这些依赖项的路径。实际上,它根本没有指定路径,因此每当java尝试运行jar时,它都会在当前目录中查找依赖项。我知道,因为当我将依赖项与jar放在同一目录中时,它就起作用了。更好的解决方案是修改pom以在类路径中添加前缀,以便Java知道在哪里可以找到依赖项。不幸的是,我的依赖关系在不同的地方,所以这对我来说不是一个选择。相反,我将尝试找出如何制作一个胖胖的瓶子。