Spring Boot:如何将classPath(target目录)中的文件路径映射至resource目录的原始路径
这个问题我之前也碰到过——毕竟PathMatchingResourcePatternResolver是从classpath加载资源,而classpath默认指向编译后的target/classes(或target/test-classes)目录,拿到的自然是构建后的文件路径。要映射回src/main/resources(或src/test/resources)的原始文件,这里有几个实用的方案:
方案1:基于构建目录结构的路径替换(最直接)
Maven/Gradle这类构建工具的目录结构是约定俗成的:src/main/resources下的文件编译后会放到target/classes,src/test/resources会放到target/test-classes。我们可以直接对拿到的路径做字符串替换,把编译后的目录前缀替换为源目录前缀。
修改你的getPathFromResources方法即可实现:
private List<String> getPathFromResources(Resource[] resources) { return Arrays.stream(resources) .map(this::parseUri) .filter(uri -> !uri.getPath().isEmpty()) .map(URI::getPath) // 替换target/classes为src/main/resources,适配Maven/Gradle默认结构 .map(path -> path.replaceFirst("/target/classes/", "/src/main/resources/")) // 如果是测试资源,再加一行替换target/test-classes // .map(path -> path.replaceFirst("/target/test-classes/", "/src/test/resources/")) .collect(Collectors.toList()); }
注意:如果你的项目自定义了资源目录或构建输出目录,需要调整替换的字符串,比如Gradle可能用build/classes/java/main代替target/classes。
方案2:通过配置文件指定源资源目录(更灵活)
如果项目结构不固定,或者需要支持多环境,最好把源资源目录的路径配置在application.properties(或application.yml)里:
# application.properties resource.source.directory=src/main/resources
然后在代码中读取这个配置,再进行路径映射:
// 注入配置(Spring环境下用@Value,普通Java项目可以用Properties类读取) @Value("${resource.source.directory}") private String sourceResourceDir; private List<String> getPathFromResources(Resource[] resources) { String classpathDir = System.getProperty("user.dir") + "/target/classes/"; String sourceDir = System.getProperty("user.dir") + "/" + sourceResourceDir + "/"; return Arrays.stream(resources) .map(this::parseUri) .filter(uri -> !uri.getPath().isEmpty()) .map(URI::getPath) .map(path -> path.replace(classpathDir, sourceDir)) .collect(Collectors.toList()); }
这里用System.getProperty("user.dir")获取项目根目录,避免硬编码绝对路径的问题。
方案3:借助构建工具API获取源目录(耦合性稍高)
如果是Maven项目,可以引入Maven的API依赖,直接从项目模型中获取资源目录:
<!-- pom.xml --> <dependency> <groupId>org.apache.maven</groupId> <artifactId>maven-core</artifactId> <version>3.9.0</version> <scope>provided</scope> </dependency>
然后在代码中获取:
private List<String> getSourceResourcePaths() throws MavenException { MavenProject project = new MavenProject(new File("pom.xml")); List<Resource> resources = project.getResources(); // 这里可以拿到所有配置的源资源目录,比如src/main/resources String sourceDir = resources.get(0).getDirectory(); // 后续逻辑同方案2,进行路径替换 return ...; }
这个方案的优点是完全贴合项目的构建配置,不会因为自定义目录出错,但缺点是依赖了Maven API,只能在Maven环境下使用。
内容的提问来源于stack exchange,提问作者Johnyb




