看了这篇,Javaweb项目的资源&配置文件就会了。

经常会遇到Javaweb项目资源加载找不到资源的问题,这个问题困扰了我好久,今天抽空来总结一下资源加载的问题。

说明:

此文章的内容是基于【 intellij idea 】集成开发软件

一、前提:路径问题

先了解什么是绝对路径,什么是相对路径,加载文件不过是了解加载方式和路径问题,现在先了解路径

绝对路径

绝对路径就是文件的真正存在的路径,是指从硬盘的根目录(盘符)开始,进行一级级目录指向文件

比如:

F:\study\Java\JavaWeb\Javaweb拓展\Java中加载资源文件的路径问题.md

相对路径

相对路径就是以当前文件为基准进行一级级目录指向被引用的资源文件。

  • ../ 表示当前文件所在的目录的上一级目录

  • ./ 表示当前文件所在的目录(可以省略)

  • / 表示当前站点的根目录(域名映射的硬盘目录)

二、普通Java项目如何获取资源文件

普通的Java项目和Javaweb项目加载资源/配置文件的方式略微有不同,这里先讲一下普通的Java项目是如何加载的

普通Java项目的项目结构

如图:
在这里插入图片描述

data.txt 是我要加载的资源文件,ResourcePahTest 是我测试的类

加载的三种方式

测试类

public class ResourcePahTest {
    /**
     * 绝对路径
     * @throws IOException
     */
    @Test
    public void test1() throws IOException {
        File file = new File("E:\\javaWorkSpace\\studyForJava\\src\\dailyTestCode\\day20200923\\data.txt");
        FileInputStream in = new FileInputStream(file);
        int len;
        while ((len = in.read())!=-1){
            System.out.print((char)len);
        }
    }

    /**
     * 项目根路径
     * @throws IOException
     */
    @Test
    public void test2() throws IOException {
        File file = new File("src\\dailyTestCode\\day20200923\\data.txt");
        FileInputStream in = new FileInputStream(file);
        int len;
        while ((len = in.read())!=-1){
            System.out.print((char)len);
        }
    }

    /**
     * 通过类加载器
     * @throws IOException
     */
    @Test
    public void test3() throws IOException {
        //获得类加载器的方式:
        //1.先获得Class对象,获得Class对象的三种方式:
        //2.再通过Class对象获得类加载器,即getClassLoader()
        //3.最后通过类加载器获取资源
        InputStream in = ResourcePahTest.class.getClassLoader().getResourceAsStream("dailyTestCode\\day20200923\\data.txt");
        int len;
        while ((len = in.read())!=-1){
            System.out.print((char)len);
        }
    }
}

注意:

我们平时用到的最多的形式就是通过类加载器加载配置文件了。那为什么是要用累加器的形式呢,以及类加载器如何寻找路径呢?后面会详细介绍

三、web项目读取资源路径的问题

关于类加载器加载资源文件的问题

为什么要用类加载器加载?


用类加载器加载的话,用的是相对路径,所以就不考虑修改路径的问题。

类加载器如何寻找路径?(重点)

这种方式是通过类加载器所在的目录(编译后的classes文件夹)为根目录的相对路径,我可能表达的有误,或者不清楚,直接上图

提示:精华全在这里了,有点长,看下去不亏!

  • 普通的Java项目(刚刚那个)
    image-20200924104504077

如图所示,在idea中,编译的 . class文件会全部放在classes这个文件夹中,所以就以这个文件夹为根路径,利用相对路径找到data.txt文件,即:

 InputStream in = ResourcePahTest.class.getClassLoader().getResourceAsStream("dailyTestCode\\day20200923\\data.txt");
  • web项目稍微有点区别

注意:idea 和 eclipse 编译发布项目的方式不同)这里以 idea 为例,后面的友链有eclipse为例的

image-20200924110547600

这里面分别有6个资源文件 data1txt ~ data4.txtUserDao.xmlmybatis-config.xml,分别处在不同的文件夹下面,那么如何通过类加载器加载到这些文件呢?

前面我们说过了是以项目编译后.class文件存放的位置classes文件夹为根路径,那么我们现在来看看 classes文件夹

image-20200924111106283

对比可以看到,data1.txt压根没有加载过来,所以你无论如何都加载不到这个资源,那为什么UserDao.xmldata2.xmlmybatis-config.xml 可以加载到classes文件夹中呢?

不难发现,在编译前,它们都在resources这个文件夹中,不是因为它的名字是resources的原因哈,是因为idea对它进行了一个标记的操作,把它标记为资源文件。如图:

image-20200924111956695

选中 xxx 文件夹,右键后标记为资源文件夹,标记后里面的资源都被识别为 资源文件,能被加载到 classes 文件夹中

插一句:上上图的 java文件夹就标记为了Sources Root这个类型,相当于src文件夹

标记为资源文件夹的特点:

  1. 加载到classes 文件夹后和 java文件夹(src)合并了,目录相互对应,所以你可以看到 UserDao.class 和 UserDao.xml 都在dao文件夹下面,而其它的配置文件在外边
  2. 标记为资源文件夹的文件夹创建子文件只能一个一个创建,比如 不能 com.yxm.dao,这样的话相当于只创建一个文件夹,而不是 com yxm dao 三个文件夹(mybatis中会遇到这个问题)

这个时候你会发现webapp文件夹下面的 data3.xml ,data4.xml 你还没有找到。

那是因为classes 文件夹存放的是java项目编译后的classes文件,而 web项目编译后的文件夹 是另一个(idea才是这样),如图:

image-20200924113419741

这个红圈文件夹才是web项目编译后的目录,Java项目编译后的内容 classes 文件夹也放到这个文件夹里面

怎么通过类加载找到 data3.xml 和 data4.xml 不要我说了吧

额。。。。。。。这个确实需要说一下,因为我也中招了

举例:

就获取web-info目录下面的data4.txt 来说

 public void test() throws IOException {
     // 按照以上的做法 用../就可以返回上一级目录了,然后就可以拿到data4.txt
        InputStream in = this.getClass().getClassLoader().getResourceAsStream("../data4.txt");
        int len;
        while((len = in.read()) != -1) {
            System.out.print((char)len);
        }
    }

我的做法:

  1. 开启tomccat
  2. 编写测试类,用Junit4单元测试,直接测试

结果:

一直报异常,没有加载到文件。。。

原因:

坑!!!我没有通过tomcat 获取,啥意思?就是单元测试是没有经过tomcat的,要想通过tomcat,就要调用servlet类,然后servlet类调用这个获取方法。 赶紧记录一下,不然下次又是排错找半天

servlet中用ServlertContext域的getRealPath()获取

这个很简单,就随便带过哈

举例:获取data3.txt 文件

//这个就是把webapp作为根目录,
String contextPath = request.getServletContext().getRealPath("data3.txt");
        System.out.println(contextPath);
InputStream in = new FileInputStream(contextPath);

局限性:

只能在servlet类中使用这个方法

四、友链

  1. 优化通过类加载器加载配置文件

通过类加载器加载资源文件

  1. 了解更多👇

Java中加载资源文件的路径问题

  1. 以 eclispe 为例的

JavaWeb中servlet读取配置文件的方式

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值