繁体   English   中英

在Maven项目中使用Apache POI运行.jar文件

[英]Running .jar file using Apache POI in Maven project

我正在努力运行一个使用Apache POI创建Excel文档的简单程序。 这也是我第一次参与Maven项目,因此可能与它有关:

我的pom.xml看起来像这样:

<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/maven-v4_0_0.xsd">

  <modelVersion>4.0.0</modelVersion>
  <groupId>com.mycompany.app</groupId>
  <artifactId>calendar</artifactId>
  <packaging>jar</packaging>
  <version>1.0-SNAPSHOT</version>
  <name>calendar</name>
  <url>http://maven.apache.org</url>

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

    <dependency>
          <groupId>org.apache.poi</groupId>
          <artifactId>poi</artifactId>
          <version>3.10-FINAL</version>
    </dependency>


    <dependency>
        <groupId>org.apache.poi</groupId>
        <artifactId>poi-ooxml</artifactId>
        <version>3.10-FINAL</version>
    </dependency>

  </dependencies>
</project>

据我所知,我的依赖关系还不错。

这是我的Java代码,我跳过了import语句,但是它们都在那里,根据我的判断,此代码中没有错误:

public class App 
{

    private static final String FILE_NAME = "/tmp/MyFirstExcel.xlsx";

    public static void main( String[] args ) throws IOException
    {
        XSSFWorkbook workbook = new XSSFWorkbook();
        XSSFSheet sheet = workbook.createSheet("Datatypes in Java");

        Object[][] datatypes = {
            {"Datatype", "Type", "Size(in bytes)"},
            {"int", "Primitive", 2},
            {"float", "Primitive", 4},
            {"double", "Primitive", 8},
            {"char", "Primitive", 1},
            {"String", "Non-Primitive", "No fixed size"}    
        };

        int rowNum = 0;
        System.out.println("Creating excel");
        for(Object[] datatype : datatypes) {
            Row row = sheet.createRow(rowNum++);
            int colNum = 0;
            for(Object field : datatype) {
                Cell cell = row.createCell(colNum++);
                if(field instanceof String) {
                    cell.setCellValue((String) field);
                }
                else if(field instanceof Integer) {
                    cell.setCellValue((Integer) field);
                }
            }
        }

        try {
            FileOutputStream outputStream = new FileOutputStream(FILE_NAME);
            workbook.write(outputStream);
            //workbook.close()
        } catch (FileNotFoundException e) {
            System.out.println("Couldn't find file to write out to");
        } catch (IOException e) {
            System.out.println("IO Exception in printing");
        }

    }
}

我已经注释掉了workbook.close() ,因为这导致了错误(不建议使用的方法?)。

使用上面的代码在我的源文件夹中,我可以运行mvn package ,该mvn package可以成功构建并在目标文件夹中生成.jar文件calendar-1.0-SNAPSHOT.jar

我正在尝试使用运行此文件

java -cp target/calendar-1.0-SNAPSHOT.jar com.mycompany.app.App

...并且我收到以下错误消息

Error: A JNI error has occurred, please check your installation and try again
Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/poi/ss/usermodel/Workbook
        at java.lang.Class.getDeclaredMethods0(Native Method)
        at java.lang.Class.privateGetDeclaredMethods(Unknown Source)
        at java.lang.Class.privateGetMethodRecursive(Unknown Source)
        at java.lang.Class.getMethod0(Unknown Source)
        at java.lang.Class.getMethod(Unknown Source)
        at sun.launcher.LauncherHelper.validateMainClass(Unknown Source)
        at sun.launcher.LauncherHelper.checkAndLoadMain(Unknown Source)
Caused by: java.lang.ClassNotFoundException: org.apache.poi.ss.usermodel.Workbook
        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)
        ... 7 more

如果这个问题需要更多信息,请告诉我。 我在这里茫然。

您需要使用Maven Assembly Plugin创建一个胖子/超级瓶子。 这意味着将一个Jar及其依赖的Jar一起创建到一个可执行的Jar文件中。 当您运行它时,它将具有所有可用的依赖项。

在您的POM中添加以下插件

<build>
    <plugins>
        <!-- Maven Assembly Plugin -->
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-assembly-plugin</artifactId>
            <version>2.4.1</version>
            <configuration>
                <!-- get all project dependencies -->
                <descriptorRefs>
                    <descriptorRef>jar-with-dependencies</descriptorRef>
                </descriptorRefs>
                <!-- MainClass in mainfest make a executable jar -->
                <archive>
                  <manifest>
                    <mainClass>com.your.path.to.main.App</mainClass>
                  </manifest>
                </archive>

            </configuration>
            <executions>
              <execution>
                <id>make-assembly</id>
                                    <!-- bind to the packaging phase -->
                <phase>package</phase>
                <goals>
                    <goal>single</goal>
                </goals>
              </execution>
            </executions>
        </plugin>

    </plugins>
</build>

运行以下命令:

mvn package

将在目标文件夹中创建两个jar文件。

calendar-1.0-SNAPSHOT.jar – Only your project classes
calendar-1.0-SNAPSHOT-with-dependencies.jar – Project and dependency classes in a single jar.

您可以按照以下方式运行它;

java -cp target/calendar-1.0-SNAPSHOT-with-dependencies.jarcom.mycompany.app.App

您可以查看calendar-1.0-SNAPSHOT-with-dependencies.jar的内容

jar tf target/calendar-1.0-SNAPSHOT-with-dependencies.jar

您将maven工件打包为jar,并且默认情况下,由maven jar插件打包的jar不包含带有已构建工件的依赖项jar。 而运行时缺少的类。

如果要在jar中包含应用程序的依赖jar,则应使用maven程序集插件,并为描述符ref参数指定jar-with-dependencies

您可以将程序集的single目标执行绑定到程序包阶段,以便您正在使用的mvn package执行实际上自动创建预期的jar。

<plugins>
  <plugin>
    <artifactId>maven-assembly-plugin</artifactId>
    <configuration>
      <archive>
        <manifest>
          <mainClass>YourMainClassPrefixedByItsPackage</mainClass>
        </manifest>
      </archive>
      <descriptorRefs>
        <descriptorRef>jar-with-dependencies</descriptorRef>
      </descriptorRefs>
    </configuration>
    <executions>
      <execution>
        <id>make-assembly</id> 
        <phase>package</phase> <!-- bind to the packaging phase -->
        <goals>
          <goal>single</goal>
        </goals>
      </execution>
    </executions>
  </plugin>

问题是在编译时POI库可用,但在运行时不可用。 它们可用的原因是它们处于Maven依赖关系中。 另外,我在pom文件中看不到任何构建包装器。 您将需要添加构建包装器来构建可以在IDE外部运行的jar文件。

现在回到您的问题,您需要在CLASSPATH环境变量中添加POI jar,以便Java运行时可以访问它或构建包含依赖项的胖jar。

您可以使用此模板在pom文件中添加构建包装器,以构建具有依赖项的jar。

<build>
    <plugins>
      <plugin>
        <artifactId>maven-dependency-plugin</artifactId>
        <executions>
          <execution>
            <phase>install</phase>
            <goals>
              <goal>copy-dependencies</goal>
            </goals>
            <configuration>
              <outputDirectory>${project.build.directory}/lib</outputDirectory>
            </configuration>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>

Maven package任务只是将项目的已编译类打包到单个jar文件中。 所有第三方库均未包括在内,这就是为什么您会报错-未找到POI类。

您应该构建一个包含所有依赖项的可运行jar文件。 请参考这个问题-您应该使用一些其他的Maven插件来实现这一目标

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM