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

时间:2017-03-31 20:27:27

标签: java excel apache maven apache-poi

我正在努力运行一个使用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并在目标文件夹中生成.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

如果此问题需要更多信息,请告知我们。我在这里不知所措。

4 个答案:

答案 0 :(得分:1)

你需要使用Maven Assembly Plugin创建一个胖/超级jar。这意味着将Jar与其依赖项Jars一起创建到一个可执行的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

答案 1 :(得分:1)

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

如果要在jar中包含应用程序的依赖项jar,则应使用maven程序集插件并为descriptorRef参数指定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>

答案 2 :(得分:0)

问题是在编译时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>

答案 3 :(得分:0)

Maven package任务只是将项目的已编译类打包到一个jar文件中。所有第三方库都不包括在内,这就是您收到错误的原因 - 找不到POI类。

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