我痛苦地意识到这个主题的帖子数量,但到目前为止,通过它们拖网对我没有帮助。
我有一个使用sqlite3数据库的maven项目。这在intelliJ中成功运行。但我想通过运行此命令检查它是否也能够作为jar运行:
Bradleys-MBP:general-state-machine atkinsb$ java -cp target/general-state-machine-1.0-SNAPSHOT.jar com.bradley.atkins.state.GeneralStateMachine
No suitable driver found for jdbc:sqlite:/Users/atkinsb/.general_state_machine/default/20171112105601/database/sm.db
Exception in thread "main" java.lang.ClassNotFoundException: org.sqlite.JDBC
at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:264)
at com.bradley.atkins.state.StateMachineDb.executeSqlStatement(StateMachineDb.java:82)
at com.bradley.atkins.state.StateMachineDb.createTables(StateMachineDb.java:33)
at com.bradley.atkins.state.StateMachineInit.prepareDatabase(StateMachineInit.java:54)
at com.bradley.atkins.state.StateMachineInit.prepare(StateMachineInit.java:12)
at com.bradley.atkins.state.GeneralStateMachine.main(GeneralStateMachine.java:12)
我对Java相当缺乏经验,并且很难理解为什么会失败。谷歌搜索时出现的可能答案是:
从以下代码中显式加载jar:
的Class.forName( “org.sqlite.JDBC”);
在建立连接之前......
我依赖的maven设置是:
<dependency>
<groupId>org.xerial</groupId>
<artifactId>sqlite-jdbc</artifactId>
<version>3.20.1</version>
</dependency>
虽然我的方法如下:
public static void executeSqlStatement(String sql)throws ClassNotFoundException {
Connection conn = null;
Class.forName("org.sqlite.JDBC");
try {
conn = DriverManager.getConnection(url);
Statement stmt = conn.createStatement();
stmt.execute(sql);
} catch (SQLException e) {
System.out.println(e.getMessage());
} finally {
try {
if (conn != null) {
conn.close();
}
} catch (SQLException ex) {
System.out.println(ex.getMessage());
}
}
}
就像我说的,这一切都在IntelliJ中正常运行,但我是否会确认它将以正确的方式作为一个独立的jar工作?我希望最终将这个项目编译为一个jar,其他项目可以作为导入引入。
如何确保我能达到这一点的任何建议都将非常感激。
谢谢
布拉德利
答案 0 :(得分:1)
类路径中缺少您的类(但您显然已经知道了)。问题是由您处理JAR的包装以及如何运行应用程序引起的。
当您从InteliJ(或大多数带有Maven集成的IDE)运行程序时,它会自动在类路径中包含Maven定义的所有必需JAR和依赖项,并且一切正常。但是,当您使用命令行(例如java -cp ...
)运行应用程序时,Maven依赖项不会附加到类路径中,除非您特意添加它们。由于您的类似乎没有打包在JAR中,因此在运行应用程序时它不在您的类路径中。
如果您使用命令行运行程序以准确再现IntelliJ的运行方式,那么使用target/classes
目录和所有依赖项这将是一个非常长的命令包含在cp
选项中,例如
java -cp C:/myproject/target/classes/;C:/somewhere/.m2/repository/org/xerial/sqlite-jdbc/3.20.1/sqlite-jdbc-3.20.1/sqlite-jdbc-3.20.1.jar; ... [lots of dependencies] ... ;C:/somewhere/.m2/repository/org/somepackage/someartifact.jar
我需要以某种方式将sqlite3 jar本身包含在我的项目中。 也许这是一个&#34;胖罐&#34;
我认为这是正确的方法,有点细微差别。如果您希望使用java
命令将JAR作为独立应用程序运行,那么您可能希望创建executable jar。请查看Maven Shade Plugin或Maven Assembly Plugin。一些谷歌搜索将告诉你如何用你的依赖创建你的JAR。
我希望最终将这个项目编译为其他项目的jar 可以作为导入拉入。
如果您希望其他项目将您的项目作为依赖使用Maven ,您可能不想制作JAR可执行文件或&#34;胖jar&#34;。 (它可能会导致诸如类重叠之类的各种问题)例如,如果您的JAR应该是其他项目的库或帮助程序,您可以在Maven仓库上部署您的应用程序,并使用相同的{{1}在其他项目中引用它机制。
当您定义依赖项时,Maven也会提取任何transitive dependencies(依赖项依赖项)。尝试运行mvn dependency:tree -Dverbose
以查看当前应用使用的所有依赖项。
我不知道您对Maven的熟悉程度,如果需要任何精确度,请注释我会相应地编辑我的答案;)