ClassPath 和 getResourceAsStream()
ClassPath
Classpath 是 Java 虚拟机或 Java 编译器中的参数,用于指定用户定义的类和包的位置。
普通本地项目的 ClassPath
Java 的运行是先运行 javac.exe
先将 .java
代码编译成 .class
字节码文件,然后运行 java.exe
启动 JVM ,然后 JVM 调用自己的 ClassLoader 类加载器读取 .class
文件,然后处理文件为内存中的 Class 类,这样无论是实例化还是执行就都没问题了。
但是 ClassLoader 去哪里找 .class
文件呢?那就是 ClassPath。而需要加载的 .class
文件除了我们自己写的 java 代码编译出来的以外,还有我们引用的外部的核心类的 .class
文件。对于外部核心类,我们通过设置环境变量中的 classpath=XXXXXX
将核心类的文件位置告诉 ClassLoader。至于我们自己写的 java 代码的 .class
文件位置,则由 IDEA 在代替我们运行 java.exe 文件的时候,传入了 -cp XXXX
参数,告诉了 ClassLoader 位置。
而 IDEA 增加的参数的地址在一个本地的普通工程中是固定的,那就是工程中的 Out\Production\ProjectName 文件夹里面。这个文件夹里面存储的就是编译好的 .class
文件。所以 Out\Production\ProjectName 也属于 ClassPath 的一部分。
Web 项目的 ClassPath
对于我们正在开发的 Web 项目来说,文件结构就会复杂很多了。首先是开发本地的文件,我们写 Java 代码的文件结构是这样的:
首先 main/java 和 test/java 下面的都是我们开发的时候编写的 .java
文件存储的位置,而 main/resource 和 test/resource 分别是业务代码和测试代码运行时所需要的资源的存放位置。 main/webapp 目录里面则是放置着 Web 应用所需要的文件资源(html,css,jsp,js 等),需要注意的是 main/webapp/WEB-INF 文件夹比较特殊,这个文件夹用于存储禁止用户访问的资源内容,只要 Web 应用需要,但是不想让用户访问到,就需要放置到这个文件夹下面。
上面就是我们在开发应用的时候,本地的一个项目结构了。但是我们开发的东西是最终需要部署到服务器上面的,肯定不会直接放置我们的开发文件(都是 .java
文件无法运行),所以和上面的本地普通工程一样,需要有一个放置成品的文件夹,那就是 Target 文件夹,里面自动生成了所有被开发的成品。而其中文件夹名字和我们的项目名一样的那个文件夹,就是我们最终需要部署的 Web 应用了。
而这个 Web 应用成品的生成逻辑是这样的:首先开发区的 webapp 里面的东西会直接平移到成品文件夹里面(各种 Web 资源 html,css,jsp,js 等)。然后将开发区的 main/java 文件夹下面的所有 .java
文件编译成 .class
文件,然后和 main/resource 文件夹里面的资源一起按照原有的结构和放到 WEB-INF/classes 文件夹里面 (java+resource->classes) 。然后将 Maven 里面记录的依赖全部下载到 WEB-INF/lib 文件夹里面,供运行 classes 里面的字节码的时候调用。
这也是对应 Tomcat 的一个 Web 应用应该有的目录结构:Tomcat 应用目录结构
那么这里 Web 应用里面的 ClassPath 也就一目了然了, BookStore/WEB-INF/classes
和 BookStore/WEB-INF/lib
。
getResourceAsStream()
这个方法都是用来读取一个文件,调用后返回读取这个文件的 InputStream 对象,用于获取数据。
使用 Class 类的方法
this.getClass().getResourceAsStream(String file);
这里是通过 Class 类来调用出来这个方法。当传入的文件路径开头加上了 /
之后,会以 ClassPath 为根路径去寻找资源。当传入的文件路径没有 /
的时候,则从 此类所在的包 下面去寻找资源
使用 ClassLoader 类的方法
this.getClass().getClassLoader().getResourceAsStream(String file);
这里是通过类加载器 ClassLoader 类来调用这个方法,传入的参数不允许开头加上 /
,默认是以 ClassPath 为根路径去寻找资源。