18

我刚刚开始构建 Java 应用程序(我确实有 .NET 经验),我正在尝试构建一个小型测试应用程序,其整个代码是这样的:

package com.company;

import com.microsoft.sqlserver.jdbc.SQLServerDataSource;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

public class Main {

    public static void main(String[] args) throws SQLException {
        System.out.println("Buna lume!");

        SQLServerDataSource ds = new SQLServerDataSource();
        ds.setIntegratedSecurity(true);
        ds.setServerName("localhost");
        ds.setPortNumber(1433);
        ds.setDatabaseName("Test");
        Connection con = ds.getConnection();

        String SQL = "SELECT * FROM Test WHERE ID = ?";
        PreparedStatement stmt = con.prepareStatement(SQL);
        stmt.setInt(1, 2);
        ResultSet rs = stmt.executeQuery();

        while (rs.next()) {
            System.out.println(rs.getInt(1) + ", " + rs.getString(2));
        }
        rs.close();
        stmt.close();

        con.close();
    }
}

如果我在 IDE(IntelliJ IDEA 12.1.6 社区版)中运行应用程序,并且 SQL Server 可用,则应用程序运行良好,完全符合它的要求。

SQL Server 驱动程序从 Microsoft 下载并添加为外部库。我创建了一个工件作为 JAR 文件:

在此处输入图像描述

现在,如果我在 cliTest.jar(我的 JAR)中包含 sqljdbc4.jar,则生成的 JAR 很胖(550kB 并且还包含该 JAR 中的类)。或者我可以排除它。不管怎样,跑步

java -jar cliTest.jar

结果是

Buna lume!
Exception in thread "main" java.lang.NoClassDefFoundError: com/microsoft/sqlserv
er/jdbc/SQLServerDataSource
        at com.company.Main.main(Main.java:15)
Caused by: java.lang.ClassNotFoundException: com.microsoft.sqlserver.jdbc.SQLSer
verDataSource
        at java.net.URLClassLoader$1.run(Unknown Source)
        at java.net.URLClassLoader$1.run(Unknown Source)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.net.URLClassLoader.findClass(Unknown Source)
        at java.lang.ClassLoader.loadClass(Unknown Source)
        at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
        at java.lang.ClassLoader.loadClass(Unknown Source)
        ... 1 more

我敢打赌我错过了一些非常基本的东西,但我只是无法弄清楚究竟是什么原因造成的。

LE1:我尝试在包含 JAR 的目录中添加 sqljdbc4.jar(虽然它似乎没有必要)和 sqljdbc_auth.dll,但仍然没有变化。

后来编辑2:根据尼古拉的回答,我做了以下事情:

  1. 删除了现有的工件
  2. 像这样创建了一个新的工件:

在此处输入图像描述

在此处输入图像描述

..结果如下:

在此处输入图像描述

  1. 构建 -> 构建工件 -> cliTest.jar -> 重建

  2. 在包含以下内容的文件夹中的 CMD 提示:

[生成了 cliTest.jar 566 KB]

java -jar cliTest.jar

现在我得到:

Exception in thread "main" java.lang.SecurityException: Invalid signature file d
igest for Manifest main attributes
    at sun.security.util.SignatureFileVerifier.processImpl(Unknown Source)
    at sun.security.util.SignatureFileVerifier.process(Unknown Source)
    at java.util.jar.JarVerifier.processEntry(Unknown Source)
    at java.util.jar.JarVerifier.update(Unknown Source)
    at java.util.jar.JarFile.initializeVerifier(Unknown Source)
    at java.util.jar.JarFile.getInputStream(Unknown Source)
    at sun.misc.URLClassPath$JarLoader$2.getInputStream(Unknown Source)
    at sun.misc.Resource.cachedInputStream(Unknown Source)
    at sun.misc.Resource.getByteBuffer(Unknown Source)
    at java.net.URLClassLoader.defineClass(Unknown Source)
    at java.net.URLClassLoader.access$100(Unknown Source)
    at java.net.URLClassLoader$1.run(Unknown Source)
    at java.net.URLClassLoader$1.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(Unknown Source)
    at java.lang.ClassLoader.loadClass(Unknown Source)
    at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
    at java.lang.ClassLoader.loadClass(Unknown Source)
    at sun.launcher.LauncherHelper.checkAndLoadMain(Unknown Source)
4

3 回答 3

7

使用java -cp而不是java -jar将所有依赖项 jar 放入类路径。

另一种方法是将所有依赖项打包到单个 jar 中,允许您使用java -jar.

编辑:

在 Java 中 *.jar 文件包含大量的类。当您构建自己的应用程序时,通常结果 jar 文件仅包含您的类,但仍必须从您使用的外部库(所谓的依赖项)加载类。

它可以通过两种不同的方式完成:

  1. 您为您的应用程序创建一个文件夹,例如,调用lib并将您的应用程序 jar 和所有依赖项放入其中。然后您使用java -cp lib:/\* com.company.Main或(感谢@NilsH,我想念这个变体)运行应用程序,您制作MANIFEST.MF文件并在其中指定Main-Class和属性,如此Classpath所述

  2. 您使用特殊工具(如 maven-dependency-plugin,如果您使用 maven 进行构建)来打包所有类,无论是您自己的,还是单个 jar 外部的。你有一个巨大的文件,可以使用java -jar cliTest.jar.

通常,首选第一种方法,并且使用MANIFEST.MF文件是一种很好的形式。

于 2013-11-03T19:58:07.163 回答
6

好吧,我应该在没有嵌入 sqljdbc4.jar 的情况下构建 JAR。

第二件事我应该像这样运行命令:

java -classpath sqljdbc4.jar;cliTest.jar com.company.Main

..然后一切正常!

于 2013-11-03T21:03:17.527 回答
0

build.gradle我对, where <packageName>is进行了以下更改package <packageName>

这出现在文件的顶部Main.ktMain.java

  manifest {
-    attributes "Main-Class": "MainKt"
+    attributes "Main-Class": "<packageName>.MainKt"
  }
  from {
    configurations.runtimeClasspath.collect {
      f -> f.isDirectory() ? f : zipTree(f)
    }
  }
  archiveName "pipeline-server.jar"
}

于 2021-01-21T19:10:37.460 回答