Get resources in java

In the process of developing java programs, one of the things we often do is to obtain resources. So what are resources? To put it bluntly, in the computer that is a pile of data. It's just that this pile of data has many forms for our java program, generally there are File, URL, InputStream and so on. There are many kinds of files alone: ​​configuration files, java class files, jps files, pictures, css, js files and so on. In the face of all kinds of resources, when we design an interface for reading resources, we need to provide methods for different forms of resources, so that our interface is still bound with the actual resource form, and it is not completely abstract. . In addition, the storage location of resources in java programs is also different. Some are stored in the classpath, some are stored in the file system, and some are stored in the web application. For resources in different locations, Java programs have different methods to obtain these resources.

    A. Get the resources in the classpath:

 URL url = this.getClass().getResource("resource_name");

    URL url = this.getClass().getClassLoader().getResource("resource_name");

    URL url = Thread.currentThread().getContextClassLoader().getResource("resource_name");

    So why are there three ways to obtain resources under the classpath in jdk? There is some origin to this.

    The first line of code is obtained by using an instance of the Class class, and the second line of code is obtained by using the classloader that loads the current class. Looking at the source code in the jdk, you will find that the instance of the class class finally delegates the loading of its classloader to obtain resources.

copy code
    public java.net.URL getResource(String name) {

    name = resolveName(name);

    ClassLoader cl = getClassLoader0();

    if (cl==null) {

    // A system class.

    return ClassLoader.getSystemResource(name);

    }

    return cl.getResource(name);

    }
copy code

  从上面的代码中可以看出,对于资源的加载并没有像类加载所采用的双亲委托机制。而是当前类的classloader不为null的情况下先从当前类的classloader中加载资源。而只有当前类的classloader为null的时候才从system classloader中去加载资源。这样可以方便我们自定义配置类覆盖一些默认配置。当然,j2se应用中如果没有特别定制classloader时,我们自己写的类都是被system classloader加载的。到底利用class去获取资源和利用classloader去获取资源有什么区别呢?区别就在 resolveName(name)这个方法中。两种方式对于资源名称的表示方式不同。下面是一个简单的包结构,/表示类路径的根

    /

    |-com.cn.test

    |-Test.class

    |-test2.txt

    |-test1.txt

    Java代码

    // 获取与当前类在同一个包下的资源

  URL url1 = this.getClass().getResource("test2.txt");

    // 获取com.cn.test包下的资源,需加/

    URL url2 = this.getClass().getResource("/com/cn/test/test2.txt");

    // 获取类路径根下的资源

URL url3 = this.getClass().getClassLoader().getResource("test1.txt");

    // 获取包com.cn.test包下的资源

   URL url4 = this.getClass().getResource("com/cn/test/test2.txt");

     装载类的过程非常简单:查找类所在位置,并将找到的Java类的字节码装入内存,生成对应的Class对象。Java的类装载器专门用来实现这样的过程,JVM并不止有一个类装载器,事实上,如果你愿意的话,你可以让JVM拥有无数个类装载器,当然这除了测试JVM外,我想不出还有其他的用途。你应该已经发现到了这样一个问题,类装载器自身也是一个类,它也需要被装载到内存中来,那么这些类装载器由谁来装载呢,总得有个根吧?没错,确实存在这样的根,它就是神龙见首不见尾的Bootstrap ClassLoader. 为什么说它神龙见首不见尾呢,因为你根本无法在Java代码中抓住哪怕是它的一点点的尾巴,尽管你能时时刻刻体会到它的存在,因为java的运行环境所需要的所有类库,都由它来装载,而它本身是C++写的程序,可以独立运行,可以说是JVM的运行起点,伟大吧。在Bootstrap完成它的任务后,会生成一个AppClassLoader(实际上之前系统还会使用扩展类装载器ExtClassLoader,它用于装载Java运行环境扩展包中的类),这个类装载器才是我们经常使用的,可以调用ClassLoader.getSystemClassLoader() 来获得,我们假定程序中没有使用类装载器相关操作设定或者自定义新的类装载器,那么我们编写的所有java类通通会由它来装载,值得尊敬吧。AppClassLoader查找类的区域就是耳熟能详的Classpath,也是初学者必须跨过的门槛,有没有灵光一闪的感觉,我们按照它的类查找范围给它取名为类路径类装载器。还是先前假定的情况,当Java中出现新的类,AppClassLoader首先在类传递给它的父类类装载器,也就是Extion ClassLoader,询问它是否能够装载该类,如果能,那AppClassLoader就不干这活了,同样Extion ClassLoader在装载时,也会先问问它的父类装载器。我们可以看出类装载器实际上是一个树状的结构图,每个类装载器有自己的父亲,类装载器在装载类时,总是先让自己的父类装载器装载(多么尊敬长辈),如果父类装载器无法装载该类时,自己就会动手装载,如果它也装载不了,那么对不起,它会大喊一声:Exception,class not found。有必要提一句,当由直接使用类路径装载器装载类失败抛出的是NoClassDefFoundException异常。如果使用自定义的类装载器loadClass方法或者ClassLoader的findSystemClass方法装载类,如果你不去刻意改变,那么抛出的是ClassNotFoundException。

  如果一个类是通过bootstrap 载入的,那我们通过这个类去获得classloader的话,有些jdk的实现是会返回一个null的,比如说我用 new Object().getClass().getClassLoader()的话,会返回一个null,这样的话上面的代码就会出现NullPointer异常.所以保险起见我们最好还是使用我们自己写的类来获取classloader("this.getClass().getClassLoader()“),这样一来就不会有问题。

    B、获取文件系统中的资源

    Java代码

    // 1、获得File对象

  File file = new File("test.txt");

    // 2、获得File对象的字节流

    InputStream in = new FileInputStream(file);

    值得注意的是在File的构造函数File(String name) 中的name参数可以是相对路径和绝对路径。相对路径是相对于System.getProperties("user.dir")的。

    C、获取web应用中的资源

servletContext.getResourceAsStream(resource_name);

    resource_names为相对于webroot的路径表示。例如获取web.xml,resource_name表示为"/WEB-INF/web.xml"

    面对上面介绍的各种资源表现形式和存放位置,难道java中就没有提供一个统一处理方式吗?有,java.net.URL。

    从名称上来看 URL(Uniform Resource Locator) 统一资源定位器。看起来很好很强大。但很多时候使用它并不能定位到我们需要的资源。

    首先,它jdk中体统的URL能访问的协议非常有限(当然可以进行扩展,不过很麻烦);常用的有http,file,ftp等等。并没有提供对classpath和servletContext中的资源的获取方法。

    另外,它没有提供判断资源是否存在的方法。每次只有等我们真正去获取资源的时候抛出异常才能知道资源无法获取。

    其次,URL这个类的职责未划分清楚,既用来表示资源有用来获取其资源。

 

  在jsp和class文件中调用的相对路径不同。在jsp里,根目录是WebRoot 在class文件中,根目录是WebRoot/WEB-INF/classes 当然你也可以用System.getProperty("user.dir")获取你工程的尽对路径。
1.jsp中取得路径:
以工程名为TEST为例
(1)得到包含工程名确当前页面全路径:

 request.getRequestURI()  

结果:/TEST/test.jsp 
(2)得到工程名:

request.getContextPath() 

结果:/TEST
(3)得到当前页面所在目录下全名称:

request.getServletPath()  

结果:假如页面在jsp目录下 /TEST/jsp/test.jsp 
(4)得到页面所在服务器的全路径:

application.getRealPath("test.jsp")   

Result: D:\resin\webapps\TEST\test.jsp
(5) Get the absolute path of the server where the page is located:

absPath=new java.io.File(application.getRealPath(request.getRequestURI())).getParent();  

Result: D:\resin\webapps\TEST
2. Get the path in the class:
(1) The absolute path of the class:

Class.class.getClass().getResource("/").getPath()   

(2) Get the path of the project:

System.getProperty("user.dir")  

Result: D:\TEST 
3. Get the path in Servlet:
(1) Get the project directory:

request.getSession().getServletContext().getRealPath("") // The parameter can be specific to the package name.  

Result: E:\Tomcat\webapps\TEST 
(2) Get the IE address bar address:

request.getRequestURL()   

Result: http://localhost:8080/TEST/test 
(3) get the relative address:

request.getRequestURI()   

Result: /TEST/test

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=326962152&siteId=291194637