项目打包成jar后包无法读取src/main/resources下文件怎么解决

发布时间:2022-04-02 13:42:55 作者:iii
来源:亿速云 阅读:1212

项目打包成jar后包无法读取src/main/resources下文件怎么解决

引言

在Java开发中,我们经常会将项目打包成JAR文件以便于部署和分发。然而,在打包过程中,有时会遇到一个常见的问题:项目在IDE中运行时能够正常读取src/main/resources目录下的资源文件,但打包成JAR后却无法读取这些文件。这个问题通常是由于资源文件的路径问题或打包配置不当引起的。本文将详细探讨这个问题的原因,并提供多种解决方案。

1. 问题描述

在开发过程中,我们通常会将一些配置文件、模板文件或其他资源文件放在src/main/resources目录下。在IDE中运行时,这些文件可以通过相对路径或类路径(classpath)来访问。然而,当项目打包成JAR文件后,这些资源文件会被打包到JAR文件的根目录或特定的子目录中。此时,如果代码中仍然使用相对路径来访问这些文件,就会导致文件无法找到。

1.1 示例代码

假设我们有一个简单的Java项目,结构如下:

my-project
├── src
│   ├── main
│   │   ├── java
│   │   │   └── com
│   │   │       └── example
│   │   │           └── MyApp.java
│   │   └── resources
│   │       └── config.properties
│   └── test
│       └── java
└── pom.xml

MyApp.java中,我们尝试读取config.properties文件:

package com.example;

import java.io.InputStream;
import java.util.Properties;

public class MyApp {
    public static void main(String[] args) {
        Properties prop = new Properties();
        try (InputStream input = MyApp.class.getResourceAsStream("/config.properties")) {
            if (input == null) {
                System.out.println("Sorry, unable to find config.properties");
                return;
            }
            prop.load(input);
            System.out.println("Loaded properties: " + prop);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

在IDE中运行时,这段代码能够正常读取config.properties文件。然而,当项目打包成JAR文件后,运行JAR文件时却无法找到config.properties文件。

2. 问题原因分析

2.1 资源文件的打包路径

在Maven项目中,src/main/resources目录下的文件默认会被打包到JAR文件的根目录中。也就是说,config.properties文件会被打包到JAR文件的根目录,而不是/resources/config.properties路径。

2.2 类路径(Classpath)的访问方式

在Java中,资源文件通常通过类路径(classpath)来访问。类路径是指JVM在运行时查找类和资源文件的路径。当项目打包成JAR文件后,JAR文件本身就是一个类路径条目。因此,资源文件的路径需要相对于类路径来指定。

2.3 代码中的路径问题

在示例代码中,我们使用了MyApp.class.getResourceAsStream("/config.properties")来访问资源文件。这里的/表示从类路径的根目录开始查找。然而,由于config.properties文件被打包到了JAR文件的根目录,因此路径应该是/config.properties,而不是/resources/config.properties

3. 解决方案

3.1 使用正确的资源路径

首先,我们需要确保在代码中使用正确的资源路径。在示例代码中,我们已经使用了正确的路径/config.properties。如果资源文件被打包到了JAR文件的根目录,那么这个路径是正确的。

3.2 使用ClassLoader来加载资源

除了使用Class.getResourceAsStream()方法,我们还可以使用ClassLoader.getResourceAsStream()方法来加载资源文件。ClassLoader是Java中用于加载类和资源的核心类,它可以从类路径中查找资源文件。

package com.example;

import java.io.InputStream;
import java.util.Properties;

public class MyApp {
    public static void main(String[] args) {
        Properties prop = new Properties();
        try (InputStream input = MyApp.class.getClassLoader().getResourceAsStream("config.properties")) {
            if (input == null) {
                System.out.println("Sorry, unable to find config.properties");
                return;
            }
            prop.load(input);
            System.out.println("Loaded properties: " + prop);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

在这个示例中,我们使用了MyApp.class.getClassLoader().getResourceAsStream("config.properties")来加载资源文件。这里的路径是相对于类路径的根目录的,因此不需要在路径前加上/

3.3 使用ClassPathResource(Spring框架)

如果你使用的是Spring框架,可以使用ClassPathResource来加载资源文件。ClassPathResource是Spring提供的一个工具类,用于从类路径中加载资源文件。

package com.example;

import org.springframework.core.io.ClassPathResource;
import java.io.InputStream;
import java.util.Properties;

public class MyApp {
    public static void main(String[] args) {
        Properties prop = new Properties();
        try (InputStream input = new ClassPathResource("config.properties").getInputStream()) {
            if (input == null) {
                System.out.println("Sorry, unable to find config.properties");
                return;
            }
            prop.load(input);
            System.out.println("Loaded properties: " + prop);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

3.4 使用ResourceBundle加载属性文件

如果你需要加载属性文件(如.properties文件),可以使用ResourceBundle类。ResourceBundle是Java提供的一个工具类,用于从类路径中加载属性文件。

package com.example;

import java.util.ResourceBundle;

public class MyApp {
    public static void main(String[] args) {
        ResourceBundle bundle = ResourceBundle.getBundle("config");
        if (bundle == null) {
            System.out.println("Sorry, unable to find config.properties");
            return;
        }
        System.out.println("Loaded properties: " + bundle.getString("some.key"));
    }
}

在这个示例中,ResourceBundle.getBundle("config")会从类路径中查找名为config.properties的文件,并加载其中的属性。

3.5 使用Maven资源过滤

如果你需要在打包过程中对资源文件进行过滤或处理,可以使用Maven的资源过滤功能。资源过滤允许你在打包过程中替换资源文件中的占位符或变量。

pom.xml中配置资源过滤:

<build>
    <resources>
        <resource>
            <directory>src/main/resources</directory>
            <filtering>true</filtering>
        </resource>
    </resources>
</build>

在资源文件中使用占位符:

app.name=${project.name}
app.version=${project.version}

在打包过程中,Maven会自动替换这些占位符为实际的值。

3.6 使用maven-assembly-plugin打包

如果你需要将资源文件打包到特定的目录中,可以使用maven-assembly-plugin插件。maven-assembly-plugin允许你自定义打包过程,将资源文件打包到指定的目录中。

pom.xml中配置maven-assembly-plugin

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-assembly-plugin</artifactId>
            <version>3.3.0</version>
            <configuration>
                <descriptors>
                    <descriptor>src/assembly/assembly.xml</descriptor>
                </descriptors>
            </configuration>
            <executions>
                <execution>
                    <id>make-assembly</id>
                    <phase>package</phase>
                    <goals>
                        <goal>single</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

src/assembly/assembly.xml中定义打包规则:

<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.3"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.3 http://maven.apache.org/xsd/assembly-1.1.3.xsd">
    <id>my-assembly</id>
    <formats>
        <format>jar</format>
    </formats>
    <includeBaseDirectory>false</includeBaseDirectory>
    <fileSets>
        <fileSet>
            <directory>src/main/resources</directory>
            <outputDirectory>/resources</outputDirectory>
        </fileSet>
    </fileSets>
</assembly>

在这个配置中,src/main/resources目录下的文件会被打包到JAR文件的/resources目录中。

3.7 使用maven-shade-plugin打包

maven-shade-plugin是另一个常用的Maven插件,用于打包JAR文件。它允许你将依赖项和资源文件打包到一个JAR文件中,并且可以自定义资源文件的路径。

pom.xml中配置maven-shade-plugin

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-shade-plugin</artifactId>
            <version>3.2.4</version>
            <executions>
                <execution>
                    <phase>package</phase>
                    <goals>
                        <goal>shade</goal>
                    </goals>
                    <configuration>
                        <filters>
                            <filter>
                                <artifact>*:*</artifact>
                                <excludes>
                                    <exclude>META-INF/*.SF</exclude>
                                    <exclude>META-INF/*.DSA</exclude>
                                    <exclude>META-INF/*.RSA</exclude>
                                </excludes>
                            </filter>
                        </filters>
                        <transformers>
                            <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                                <mainClass>com.example.MyApp</mainClass>
                            </transformer>
                            <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
                                <resource>config.properties</resource>
                            </transformer>
                        </transformers>
                    </configuration>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

在这个配置中,maven-shade-plugin会将config.properties文件打包到JAR文件的根目录中。

3.8 使用maven-jar-plugin打包

maven-jar-plugin是Maven默认的打包插件,用于打包JAR文件。你可以通过配置maven-jar-plugin来自定义资源文件的打包路径。

pom.xml中配置maven-jar-plugin

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-jar-plugin</artifactId>
            <version>3.2.0</version>
            <configuration>
                <archive>
                    <manifest>
                        <addClasspath>true</addClasspath>
                        <mainClass>com.example.MyApp</mainClass>
                    </manifest>
                    <manifestEntries>
                        <Class-Path>./resources/</Class-Path>
                    </manifestEntries>
                </archive>
            </configuration>
        </plugin>
    </plugins>
</build>

在这个配置中,maven-jar-plugin会将资源文件打包到JAR文件的/resources目录中,并在MANIFEST.MF文件中添加Class-Path条目。

3.9 使用maven-resources-plugin复制资源文件

如果你需要在打包过程中将资源文件复制到特定的目录中,可以使用maven-resources-plugin插件。maven-resources-plugin允许你在打包过程中复制资源文件到指定的目录。

pom.xml中配置maven-resources-plugin

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-resources-plugin</artifactId>
            <version>3.2.0</version>
            <executions>
                <execution>
                    <id>copy-resources</id>
                    <phase>package</phase>
                    <goals>
                        <goal>copy-resources</goal>
                    </goals>
                    <configuration>
                        <outputDirectory>${project.build.directory}/resources</outputDirectory>
                        <resources>
                            <resource>
                                <directory>src/main/resources</directory>
                                <filtering>true</filtering>
                            </resource>
                        </resources>
                    </configuration>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

在这个配置中,maven-resources-plugin会将src/main/resources目录下的文件复制到target/resources目录中。

3.10 使用maven-dependency-plugin打包依赖项

如果你需要将依赖项和资源文件打包到一个JAR文件中,可以使用maven-dependency-plugin插件。maven-dependency-plugin允许你将依赖项和资源文件打包到一个JAR文件中。

pom.xml中配置maven-dependency-plugin

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-dependency-plugin</artifactId>
            <version>3.1.2</version>
            <executions>
                <execution>
                    <id>copy-dependencies</id>
                    <phase>package</phase>
                    <goals>
                        <goal>copy-dependencies</goal>
                    </goals>
                    <configuration>
                        <outputDirectory>${project.build.directory}/lib</outputDirectory>
                        <overWriteReleases>false</overWriteReleases>
                        <overWriteSnapshots>false</overWriteSnapshots>
                        <overWriteIfNewer>true</overWriteIfNewer>
                    </configuration>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

在这个配置中,maven-dependency-plugin会将依赖项复制到target/lib目录中。

3.11 使用maven-war-plugin打包Web应用

如果你开发的是Web应用,可以使用maven-war-plugin插件来打包WAR文件。maven-war-plugin允许你将资源文件打包到WAR文件的特定目录中。

pom.xml中配置maven-war-plugin

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-war-plugin</artifactId>
            <version>3.3.1</version>
            <configuration>
                <webResources>
                    <resource>
                        <directory>src/main/resources</directory>
                        <targetPath>WEB-INF/classes</targetPath>
                    </resource>
                </webResources>
            </configuration>
        </plugin>
    </plugins>
</build>

在这个配置中,maven-war-plugin会将src/main/resources目录下的文件打包到WAR文件的WEB-INF/classes目录中。

3.12 使用maven-ear-plugin打包EAR应用

如果你开发的是EAR应用,可以使用maven-ear-plugin插件来打包EAR文件。maven-ear-plugin允许你将资源文件打包到EAR文件的特定目录中。

pom.xml中配置maven-ear-plugin

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-ear-plugin</artifactId>
            <version>3.1.0</version>
            <configuration>
                <defaultLibBundleDir>lib</defaultLibBundleDir>
                <modules>
                    <webModule>
                        <groupId>com.example</groupId>
                        <artifactId>my-web-app</artifactId>
                        <contextRoot>/my-web-app</contextRoot>
                    </webModule>
                </modules>
            </configuration>
        </plugin>
    </plugins>
</build>

在这个配置中,maven-ear-plugin会将Web应用打包到EAR文件的lib目录中。

3.13 使用maven-antrun-plugin执行自定义任务

如果你需要在打包过程中执行自定义任务,可以使用maven-antrun-plugin插件。maven-antrun-plugin允许你在打包过程中执行Ant任务。

pom.xml中配置maven-antrun-plugin

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-antrun-plugin</artifactId>
            <version>3.0.0</version>
            <executions>
                <execution>
                    <id>copy-resources</id>
                    <phase>package</phase>
                    <goals>
                        <goal>run</goal>
                    </goals>
                    <configuration>
                        <target>
                            <copy todir="${project.build.directory}/resources">
                                <fileset dir="src/main/resources"/>
                            </copy>
                        </target>
                    </configuration>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

在这个配置中,maven-antrun-plugin会将src/main/resources目录下的文件复制到target/resources目录中。

3.14 使用maven-exec-plugin执行Java程序

如果你需要在打包过程中执行Java程序,可以使用maven-exec-plugin插件。maven-exec-plugin允许你在打包过程中执行Java程序。

pom.xml中配置maven-exec-plugin

”`xml org.codehaus.mojo exec-maven-plugin 3.0.0 run-java package java com.example.MyApp arg1 arg2 </

推荐阅读:
  1. 如何解决src下xml等资源文件在IDEA中无法读取的问题
  2. 如何用maven将dubbo工程打成jar包来运行

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

jar

上一篇:python怎么利用PrettyTable美化表格

下一篇:vue+echarts怎么实带渐变效果的折线图

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》