惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Microsoft Azure Blog
Microsoft Azure Blog
WordPress大学
WordPress大学
Google DeepMind News
Google DeepMind News
美团技术团队
大猫的无限游戏
大猫的无限游戏
H
Help Net Security
小众软件
小众软件
aimingoo的专栏
aimingoo的专栏
博客园 - 聂微东
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
M
MIT News - Artificial intelligence
酷 壳 – CoolShell
酷 壳 – CoolShell
博客园 - Franky
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
Microsoft Security Blog
Microsoft Security Blog
F
Fortinet All Blogs
A
About on SuperTechFans
Recent Announcements
Recent Announcements
D
Docker
Vercel News
Vercel News
Engineering at Meta
Engineering at Meta
腾讯CDC
Martin Fowler
Martin Fowler
阮一峰的网络日志
阮一峰的网络日志

博客园 - 如.若

Linux系统负载过高问题排查 Git 配置 ssh-key 免密登录 cron表达式详解 Spring Boot 使用 EnvironmentPostProcessor 接口实现加载外部配置文件 AdoptOpenJDK(JAVA环境)安装 JVM优化之 -Xss -Xms -Xmx -Xmn 参数设置 JAVA 多线程基础 SQL 存储过程游标应用 SQL 语句实现查询子父节点 浅谈web项目读取classpath路径下面的文件 SpringBoot+SpringSecurity+SpringSession实现一个前后端分离的权限管理系统 Spring Security 中 CSRF 防御源码解析 Redis 持久化 SpringBoot 如何防御 CSRF 攻击 SimpleDateFormat线程不安全的5种解决方案 数据库建模-规范 接口的幂等性怎么设计? TOP命令结果分析 Redis配置参数详解
Spring ClassPathResource加载资源文件详解
如.若 · 2021-07-01 · via 博客园 - 如.若

先看Demo

@Test
public void testClassPathResource() throws IOException {
    Resource res = new ClassPathResource("resource/ApplicationContext.xml");
    InputStream input = res.getInputStream();
    Assert.assertNotNull(input);
}

再看内部源码

public ClassPathResource(String path) {
     this(path, (ClassLoader) null);
}

public ClassPathResource(String path, ClassLoader classLoader) {
    Assert.notNull(path, "Path must not be null");
    String pathToUse = StringUtils.cleanPath(path);
    if (pathToUse.startsWith("/")) {
        pathToUse = pathToUse.substring(1);
    }
    this.path = pathToUse;
    this.classLoader = (classLoader != null ? classLoader : ClassUtils.getDefaultClassLoader());
}

public ClassPathResource(String path, Class<?> clazz) {
     Assert.notNull(path, "Path must not be null");
     this.path = StringUtils.cleanPath(path);
     this.clazz = clazz;
}

获取资源内容

/**
 * This implementation opens an InputStream for the given class path resource.
 * @see java.lang.ClassLoader#getResourceAsStream(String)
 * @see java.lang.Class#getResourceAsStream(String)
 */
@Override
public InputStream getInputStream() throws IOException {
    InputStream is;
    if (this.clazz != null) {
        is = this.clazz.getResourceAsStream(this.path);
    }
    else if (this.classLoader != null) {
        is = this.classLoader.getResourceAsStream(this.path);
    }
    else {
        is = ClassLoader.getSystemResourceAsStream(this.path);
    }
    if (is == null) {
        throw new FileNotFoundException(getDescription() + " cannot be opened because it does not exist");
    }
    return is;
}

源码解读

该类获取资源的方式有两种:Class获取和ClassLoader获取。

@Test
public void testResouce() {
    ClassLoader loader = Thread.currentThread().getContextClassLoader();
    System.out.println(loader.getResource("").getPath());
    System.out.println(this.getClass().getResource("").getPath());
    System.out.println(this.getClass().getResource("/").getPath());
    System.out.println(System.getProperty("user.dir"));
}

运行结果:

/home/temp/spring_test/target/test-classes/
/home/temp/spring_test/target/test-classes/com/test/spring/spring_test/
/home/temp/spring_test/target/test-classes/
/home/temp/spring_test
//获取的是相对于当前类的相对路径
Class.getResource("")
//获取的是classpath的根路径
Class.getResource("/")
//获取的是classpath的根路径
ClassLoader.getResource("")

总结

在创建ClassPathResource对象时,我们可以指定是按Class的相对路径获取文件还是按ClassLoader来获取。