前言
自己写的一个运行过程中获取资源的工具类,主要是兼容jar包运行和非jar包运行的情况
方法会指明哪个优先 这里把所有文件夹也认为是包
可能存在逻辑漏洞的地方
这里判断是否是jar包运行 前后采用了好多方式,现在这种可能比较适用,即随便拿一个类(不要是导入的资源jar包,最好就是启动类) 看其资源路径中是否以jar开头 如果是即是jar包
获取所在文件夹路径: 用刚才的类的资源路径进行切割切割去file:后面的字符串 再构造file 这样 应该适用范围比较广
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import java.io.*;
import java.net.URL;
import java.net.URLDecoder;
/**
* 资源扫描类
*
* @author Norton Lai
* @created 2020/4/17
*/
@Slf4j
public class UriScan {
/**
* 锚点
*
* @Fields anchor
*/
private File anchor;
private Class anchorClz;
/**
* 构造必须传入一个锚点类,这个类可以随意选择,但是位置关键,
* 不能是lib下的jar包,不能是其他模块的类,
* 最好就是main函数所在的类 程序的入口类.
* 这个工具全依靠此类的位置来推断启动方式,来寻找资源
*
* @param anchorClz the anchor clz
* @author Norton Lai
* @created 2020 -04-17 09:44:42
*/
public UriScan(Class anchorClz) {
this.anchorClz = anchorClz;
try {
anchor = new File(URLDecoder.decode(anchorClz.getProtectionDomain().getCodeSource().getLocation().getPath(), "utf-8"));
int i = 10;
while (anchor.isFile() && i > 0) {
i--;
anchor = anchor.getParentFile();
}
} catch (UnsupportedEncodingException e) {
log.error(e.getMessage(), e);
}
}
public static void main(String[] args) {
UriScan scan = new UriScan(UriScan.class);
System.out.println(scan.isStartupFromJar());
}
/**
* 构造路径
*
* @param pack
* @param name
* @return
* @author Norton Lai
* @created 2019-9-9 上午11:49:47
*/
private String buildPath(String pack, String name) {
if (pack == null || pack.length() == 0) {
pack = "/";
}
pack = pack.replace('.', '/');
if (!pack.startsWith("/")) {
pack = "/" + pack;
}
if (!pack.endsWith("/")) {
pack += "/";
}
pack += name;
return pack;
}
/**
* 获取root目录如果是classes 就是classes目录 如果是jar 则是jar所在文件夹
*
* @return
* @author Norton Lai
* @created 2019-8-24 下午6:31:58
*/
public File getRoot() {
String path = anchor.getAbsolutePath();
log.info("根目录:" + path);
if (isStartupFromJar()) {
if (path.contains("file:")) {
int i = path.indexOf("file:");
path = path.substring(0, i);
anchor = new File(path);
log.info("判断是否文件夹: " + path + " " + anchor.exists());
}
return anchor;
}
return anchor;
// return new File(ResourceScanUtil.class.getResource("/").getFile());
}
/**
* 判断启动方式
*
* @param clazz
* @return
* @author Norton Lai
* @created 2019-9-9 上午10:47:38
*/
public boolean isStartupFromJar() {
// boolean isStartJar = anchor.isFile();
String resource = anchorClz.getResource(anchorClz.getSimpleName()+".class").toString();
log.info(resource);
boolean isStartJar = resource.startsWith("jar");
log.info("是否是从jar启动:" + isStartJar);
return isStartJar;
}
/**
* 获取文件对象,优先dir,如果最终在jar里找到了,会复制一份到dir里 如果找不到就返回null
*
* @param pkg
* @param name
* @return
* @author Norton Lai
* @created 2019-9-9 下午12:14:43
*/
public File getRes(String pkg, String name) {
String path = buildPath(pkg, name);
File resource = new File(getRoot(), path);
if (!resource.exists()) {
InputStream stream = getResStreamFirstJar(pkg, name);
if (stream != null) {
try (FileOutputStream output = new FileOutputStream(resource)) {
IOUtils.copy(stream, output);
} catch (Exception e) {
return null;
}
}
return resource;
}
return resource;
}
/**
* 从根目录找资源,如果是编辑器里 就是编译后class存放的文件夹开始找,pack就是包名 如 cn.lsg.img 等<br>
* 如果是可执行jar包 先在jar包里找,找不到再从 jar包所在的位置当成根目录开始找
*
* @param pack
* @param name
* @return
* @author Norton Lai
* @created 2019-8-17 上午11:13:40
*/
public URL getResUrl(String pack, String name) {
pack = buildPath(pack, name);
URL url = anchorClz.getResource(pack);
return url;
}
/**
* 如果是以class方式运行 直接找路径拿资源,如果是以jar包方式运行 先去根目录找 找不到再去jar包内找.
*
* @param pkg
* @param name
* @return
* @author Norton Lai
* @created 2019-9-9 上午11:54:17
*/
public InputStream getResStreamFirstDir(String pkg, String name) {
String path = buildPath(pkg, name);
File resource = new File(getRoot(), path);
log.info("路径:" + resource.getAbsolutePath());
if (resource.exists()) {
try {
return new FileInputStream(resource);
} catch (FileNotFoundException e) {
log.error(e.getMessage(), e);
return null;
}
}
if (isStartupFromJar()) {
InputStream ins = anchorClz.getResourceAsStream(path);
return ins;
}
return null;
}
/**
* 从根目录找资源,如果是编辑器里 就是编译后class存放的文件夹开始找,pack就是包名 如 cn.lsg.img 等<br>
* 如果是可执行jar包 先在jar包里找,找不到再从 jar包所在的位置当成根目录开始找
*
* @param pack
* @param name
* @return
* @author Norton Lai
* @created 2019-8-17 上午11:11:13
*/
public InputStream getResStreamFirstJar(String pack, String name) {
pack = buildPath(pack, name);
InputStream ins = anchorClz.getResourceAsStream(pack);
return ins;
}
/**
* 从根目录找资源,如果是编辑器里 就是编译后class存放的文件夹开始找,pack就是包名 如 cn.lsg.img 等<br>
* 如果是可执行jar包 先在jar包里找,找不到再从 jar包所在的位置当成根目录开始找
*
* @param pack
* @param name
* @return
* @author Norton Lai
* @created 2019-8-17 上午11:08:23
*/
@Deprecated
public File getResourceFromRoot(String pack, String name) {
// 包名对应的路径名称
URL url = getResUrl(pack, name);
if (url == null) {
return null;
}
return new File(url.getFile());
}
}