Java中的相对路径解惑

来源:互联网 发布:python windows 路径 编辑:程序博客网 时间:2024/05/29 10:16

让人迷惑的相对路径

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 容器中表现都是统一的.
0 0
原创粉丝点击