java 资源获取工具类

前言

自己写的一个运行过程中获取资源的工具类,主要是兼容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());
    }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值