112 lines
4.1 KiB
Java
112 lines
4.1 KiB
Java
package quant.rich.emoney.util;
|
||
|
||
import java.io.*;
|
||
import java.nio.charset.StandardCharsets;
|
||
import java.nio.file.*;
|
||
|
||
import lombok.extern.slf4j.Slf4j;
|
||
|
||
@Slf4j
|
||
public class SmartResourceResolver {
|
||
|
||
private static RunningFrom runningFrom;
|
||
|
||
static {
|
||
if (isRunningFromJar()) {
|
||
runningFrom = RunningFrom.JAR;
|
||
}
|
||
else if (isRunningFromWar()) {
|
||
runningFrom = RunningFrom.WAR;
|
||
}
|
||
else {
|
||
runningFrom = RunningFrom.IDE;
|
||
}
|
||
}
|
||
|
||
/**
|
||
获取资源
|
||
<p>
|
||
<ul>
|
||
<li>JAR
|
||
<ul>
|
||
<li>优先以 jar 文件所在目录为基准,寻找相对路径外部文件</li>
|
||
<li>当外部文件不存在时,读取 classpath,即 jar 内部资源文件</li>
|
||
</ul>
|
||
</li>
|
||
<li>WAR 只获取 classpath 文件,即 /WEB-INF/classes/ 下文件</li>
|
||
<li>IDE 只获取源文件,即 src/main/resources/ 下文件</li>
|
||
</ul></p>
|
||
* @param relativePath 相对路径
|
||
* @param writable 是否一定可写
|
||
* @return
|
||
*/
|
||
public static InputStream loadResource(String relativePath) {
|
||
try {
|
||
Path externalPath = resolveExternalPath(relativePath);
|
||
|
||
if (externalPath != null && Files.exists(externalPath)) {
|
||
log.debug("从外部文件系统加载资源: {}", externalPath);
|
||
return Files.newInputStream(externalPath);
|
||
}
|
||
|
||
// 否则回退到 classpath(JAR、WAR、IDE)
|
||
InputStream in = SmartResourceResolver.class.getClassLoader().getResourceAsStream(relativePath);
|
||
if (in != null) {
|
||
log.debug("从 classpath 内部加载资源: {}", relativePath);
|
||
return in;
|
||
}
|
||
|
||
throw new FileNotFoundException("无法找到资源: " + relativePath);
|
||
} catch (Exception e) {
|
||
throw new RuntimeException("读取资源失败: " + relativePath, e);
|
||
}
|
||
}
|
||
|
||
public static void saveText(String relativePath, String content) throws IOException {
|
||
Path outputPath = resolveExternalPath(relativePath);
|
||
Files.createDirectories(outputPath.getParent()); // 确保目录存在
|
||
Files.writeString(outputPath, content, StandardCharsets.UTF_8, StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING);
|
||
log.debug("写入外部资源文件成功: {}", outputPath);
|
||
}
|
||
|
||
private static Path resolveExternalPath(String relativePath) {
|
||
try {
|
||
Path basePath;
|
||
if (runningFrom == RunningFrom.JAR) {
|
||
basePath = Paths.get(SmartResourceResolver.class.getProtectionDomain()
|
||
.getCodeSource().getLocation().toURI()).getParent();
|
||
return basePath.resolve(relativePath).normalize();
|
||
} else if (runningFrom == RunningFrom.WAR) {
|
||
basePath = Paths.get(SmartResourceResolver.class.getProtectionDomain()
|
||
.getCodeSource().getLocation().toURI()); // e.g., WEB-INF/classes/
|
||
return basePath.resolve(relativePath).normalize();
|
||
} else {
|
||
// IDE 环境:返回 src/main/resources 下真实文件
|
||
return Paths.get("src/main/resources", relativePath).normalize();
|
||
}
|
||
}
|
||
catch (Exception e) {
|
||
e.printStackTrace();
|
||
return null;
|
||
}
|
||
}
|
||
|
||
private static boolean isRunningFromJar() {
|
||
String path = SmartResourceResolver.class.getResource(
|
||
SmartResourceResolver.class.getSimpleName() + ".class").toString();
|
||
return path.startsWith("jar:");
|
||
}
|
||
|
||
private static boolean isRunningFromWar() {
|
||
String path = SmartResourceResolver.class.getResource(
|
||
SmartResourceResolver.class.getSimpleName() + ".class").toString();
|
||
return path.contains("/WEB-INF/classes/");
|
||
}
|
||
|
||
private static enum RunningFrom {
|
||
JAR,
|
||
WAR,
|
||
IDE
|
||
}
|
||
}
|