Java中的相对路径解惑

让人迷惑的相对路径

Java 中有一个很容易让人误解的问题, 就是路径问题.
我们来看一段代码.
项目路径为 /home/pathExample, 类的全限定名是 org.haoyifen.PathTest, 类的绝对地址为 /home/pathExample/src/main/java/org/haoyifen/PathTest.java

public class PathTest {
    @Test
    public void relativePath() {
        Path path = Paths.get("books.xml");
        Path absolutePath = path.toAbsolutePath();
        System.out.println(absolutePath);
    }
}

初学者可能以为上面输出的 * /home/pathExample/src/main/java/org/haoyifen/books.xml* , 但其实输出的是 * /home/pathExample/books.xml* , 也就是相对于项目目录.
这说明 Java 类中处理相对路径并不是以当前该类的路径来进行相对的, 这一点不同于 HTML 中的 js 文件和 CSS 文件的引用.

原因

其实 Java 中处理相对路径是以 JDK 运行时的属性”user.dir” 来进行相对的. 我们可以改变”user.dir” 对应的值, 来改变相对路径转换为绝对路径的值.

    @Test
    public void changeUserDir() {
        //将user.dir对应的值设定为/home/haoyifen
        System.setProperty("user.dir", "/home/haoyifen");
        Path absolutePath = Paths.get("books.xml").toAbsolutePath();
        //验证相对路径转换为绝对路径时, 是以user.dir来进行计算的
        Assert.assertEquals(absolutePath, Paths.get("/home/haoyifen/books.xml"));
    }

在不同的运行环境中, 比如开发时的 IDE, 运行时的命令行或者 WEB 容器, JDK 运行时的属性”user.dir” 的值的改变规则都是不同的, Java 中绝对不要使用相对路径来读取文件, 否则会出现开发时是正常的, 运行时就提示 java.io.FileNotFoundException: books.xml (没有那个文件或目录)

类路径和类加载器

Java中加载文件, 最好是使用类路径来进行加载, 以下是类路径的一些规则 (假设类的全限定名为org.haoyifen.PathTest, 类的根路径为/home/pathExample/target/classes)

  • PathTest.class.getResource(“”)
    当前类所在的目录,file:/home/pathExample/target/classes/org/haoyifen/
  • PathTest.class.getResource(“/”)
    类的跟路径, file:/home/pathExample/target/classes/
  • PathTest.class.getClassLoader().getResource(“”)
    类的跟路径, file:/home/pathExample/target/classes/
  • Thread.currentThread().getContextClassLoader().getResource(“”)
    同上, 类的跟路径, file:/home/pathExample/target/classes/

Spring 框架中的解决办法

Spring 不仅仅适用于 Java SE, 也适用于 Java EE, Spring 中有个很重要的概念就是 Resource 接口, Resource 是一个抽象于底层实现的资源描述符, 用于获取底层资源 (可以是文件系统的 File 也可以是网络 URL) 的输入流和其他相关信息. 其中使用的最多的实现就是 ClassPathResource, 常见的使用案例有:

  • ClassPathXmlApplicationContext 加载 xml 配置文件启动 Spring 框架
  • Mybatis-Spring 中加载 Class 路径中的 mapper.xml 文件来生成 DAO

Resource 最重要的方法如下:

     */
    @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;
    }

使用的就是 classLoader 来进行加载资源.

总结

  1. Java 中相对路径是以 System.getProperty(“user.dir”) 来进行相对的.
  2. Java 中绝对不要使用相对路径来加载文件, user.dir 设定规则在 IDE, 命令行和 WEB 容器中是不同的.
  3. 使用类路径或者类加载器来加载文件, 这在 Java SE 项目和 WEB 容器中表现都是统一的.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值