在java中获取资源

2023-05-23


我们通常要做的一件事就是在开发java程序时获取资源。那资源是什么?说到底,在电脑里就是一堆数据。只是这些数据对我们的java程序有多种表现形式,通常有File,URL,InputStream等。而且仅仅是文档这个项目就有很多种:环境变量,java类文档,jps文档,照片,照片,css、js文档等等。面对众多的资源,当我们设计一个读取资源的界面时,我们需要为不同形式的资源提供方法,这导致我们的界面仍然与实际的资源方法联系在一起,并且没有完全抽象。另外,资源在java系统中的存储位置也各不相同。有的存储在classpath中,有的存储在文件系统中,有的存储在web应用中。而且java程序在不同位置的资源中获取这些资源的方法也不同。


A、在classpath中获取资源:






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

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

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





那为什么在jdk中又带来了三种获取classpath下资源的方法呢?这些都有一些来源。


在第一行代码中,使用Class类的例子来获取,第二行代码是通过载入当前类的classloader来获取的。看看jdk中的源代码,你会发现class类的例子最终被委托载入他的classloader来获取资源。










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);

    }









根据上述代码可以看出,对于资源的载入,没有像类载入所用的双亲委托机制。但当当前类的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之外,我还不明白其它的用途。你应该已经发现了这样一个问题。类装载器本身也是一个类,也需要装载到内存中。谁来装载这些类装载器?总有根吧?是的,确实有这样一个根,那就是Bootstrapp,神龙见头不见尾。 ClassLoader. 为什么说它的龙看不到尾巴,因为你根本抓不住Java代码里的一点尾巴,虽然你可以一直感受到它的存在,但是它本身就是C,因为java运行环境所需的所有类库都是装载的。 编写程序,可独立运行,可以算是JVM的运行起点,优秀吧。当Bootstrap完成其任务后,它将生成一个AppClassLoader(实际上,在此之前,该系统还将使用扩展装载器ExtClassLoader,它用于装载Java运行环境扩展包中的类),这种装载器是经常使用的,可以调用ClassLoader。.getSystemClassLoader() 来获取,假设我们没有使用类装载器在系统中的相关操作设置或定制新的类装载器,那么我们编写的所有java类都将由其装载,这是值得尊重的。AppClassLoader搜索类的区域就是众所周知的Classpath,也是初学者必须跨越的门槛,是否有一种闪光的感觉,我们根据它的搜索范围来命名类路径类装载器。或者之前假设的情况,当Java中出现一个新的类时,AppClassLoader首先将其传达给其父类装载器,即Extion。 ClassLoader,问问它能不能装载这样的东西,如果可以的话,那么AppClassLoader就不会做这份工作了,同样Extion。 在装载ClassLoader时,还会先问它的父类装载器。不难发现,类装载器其实是一个树形的框架图。每个类装载器都有自己的父亲。类装载器在装载类装载时,总是先装载自己的父类装载器(对长辈多么尊重)。如果父类装载器不能装载这种装载器,它会自己装载。如果它不能装载,那么对不起,它会喊:Exception,class not found。当NoClassDefFoundException因直接类路径装载器装载类失败而抛出的时候,就是NoClassDefFoundException。如采用自定义的类装载器loadClass方法或ClassLoaderfindSystemClass方法装载类,如果您不刻意改变,则抛出ClassNotFoundException。


假如一个类是通过bootstrapp 如果我们输入,那么如果我们通过这个类别获得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的路径表示。例如获取webbes.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。 根目录是WebRoot//class文档。WEB-INF/classes 当然你也可以使用System.getProperty("user.dir")得到你所有的工程路径。
1.在jsp中获取路径:
以项目名称TEST为例
(1)获得包括工程名称在内的当前页面全路径:






request.getRequestURI()





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






request.getContextPath()





结果:/TEST
获得当前页面所在目录下的全名:






request.getServletPath()



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





application.getRealPath("test.jsp")




结果:D:\resin\webapps\TEST\test.jsp
(5)获取页面所在服务器的正确路径:






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





结果:D:\resin\webapps\TEST
在类别中获得路径:
(1)类的尽对路径:






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





(2)获得工程的路径:






System.getProperty("user.dir")



结果:D:\TEST
获取Servlet中的路径:
(1)获得工程目录:






request.getSession().getServletContext().getRealPath(")//参数可以具体到包名。





结果:E:\Tomcat\webapps\TEST
(2)获取IE地址栏地址:






request.getRequestURL()





结果:http://localhost:8080/TEST/test
(3)获得相对地址:





request.getRequestURI()




结果:/TEST/test


本文仅代表作者观点,版权归原创者所有,如需转载请在文中注明来源及作者名字。

免责声明:本文系转载编辑文章,仅作分享之用。如分享内容、图片侵犯到您的版权或非授权发布,请及时与我们联系进行审核处理或删除,您可以发送材料至邮箱:service@tojoy.com