在 开发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
// 获取与当前类在同一个包下的资源 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");
另外在servlet中:
this.getClass().getClassLoader().getResource("/").getPath();
这将获取 到classes目录的全路径
例如 : E:/eclipseM9/workspace/tree/WEB-INF/classes/
这个方法也可以在web环境里确定路径,比较好用
B、获取文件系统中的资源
// 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这个类的职责未划分清楚,既用来表示资源有用来获取其资源。
另外:
String path = getServletContext().getRealPath("/");
将获取web项目的全路径
例如 :E:/eclipseM9/workspace/tree/
tree是我web项目的根目录
String webPath = ServletActionContext.getServletContext().getRealPath("/");
将根据服务器的文件保存地址找到项目部署的绝对地址
以下内容
From : http://blog.csdn.net/ruyanhai/archive/2007/11/07/1871663.aspx
◆一般情况下,我们都使用相对路径来获取资源,这样的灵活性比较大.
比如当前类为com/bbebfe/Test.class
而图像资源比如sample.gif应该放置在com/bbebfe/sample.gif
而如果这些图像资源放置在icons目录下,则应该是com/bbebfe/icons/sample.gif
通过当前类文件的路径获取资源主要有如下几种方式:
· 假设当前类为com.bbebfe.Test
· 包所在的文件夹为bin
String imageName = "icons/sample.gif"
1, 通过Class.getResource()定位类路径下的资源(bin/com/bbebfe/icons/sample.gif)
Class clazz = this.getClass();
URL url = clazz.getResource(imageName);
2,通过ClassLoader.getResource()定位包的根目录下的资源(bin/icons/sample.gif)
Class clazz = this.getClass(); URLClassLoader loader = (URLClassLoader)clazz.getClassLoader(); URL url = loader.getResource(imageName);
3, 通过ClassLoader.findResource()提供自己定制的方式定位资源
URL url = loader.findResource(imageName);
◆那么这三种方法有那些区别, 我们应该在何时使用哪种方法呢?
· Class.getResource() 方法
该方法实际通过该Class的Class Loader的getResource()方法来获得资源, 在调用ClassLoader的getResource()方法之前, Class.getResource()方法会对资源名称做一定的处理,构建一个该资源的绝对名称(absolute name, 大意是:
+如果资源名称以'/'('/u002f') 开始, 则资源的绝对名称是'/'以后的部分.
如果imageName是"/icons/sample.gif", 则在这里会变成"icons/sample.gif"
+否则对于其他情况, 绝对名称将是如下形式(给资源名称的前面加上modified_package_name/):
modified_package_name/resource_name (修正的包名称/资源名称)
其中修正的包名称含义是将当前对象所在的包名称中的'.'('/u002e')替换为'/'
如果ClassLoader.getResource()方法返回一个值为null的URL, 则Class.getResource()方法最终会将资源请求交给ClassLoader.getSystemResource(java.lang.String).
· ClassLoader.getResource() 方法
该对资源进行查找, 资源的名称是以'/'分隔的路径, 这个方法首先查找自己的父亲ClassLoader, 由自己的父ClassLoader来查找资源(实际上, 如果父亲的父亲不是空, 则父亲仍会向上提交查找请求). 如果自己的父ClassLoader是null, 则查找Java虚拟机中内建的class loader, 并将资源请求提交给它们, 如果这些操作都失败了, 则ClassLoader会调用自己的findResource()方法来查找资源.
· ClassLoader.findResource() 方法
该方法在内部查找指定的资源, 如果你实现了自己的Class Loader,则应该重载这个方法以自己特定的方式来查找类文件和资源.
◆通过以上的总结, 我们可以看到三点.
1, 无论是getResource(), 还是findResource(), 这些方法都只是资源的定位方法, 最终都只是返回一个URL, 只是对资源的定位而已, 我们随后应通过自己的方法来读取这些资源. 而在Class和ClassLoader中还定义的有getResourceAsStream方法, 该方法是getResource的增强版, 这里就不介绍了.
2,如果需要以类为相对路径查找资源, 则应该调用Class.getResource()方法, 不要直接调用ClassLoader.getResource()方法. 另外, 除非是你自己定义了ClassLoader并重载了findResource方法,否则也不要直接调用ClassLoader.findResource方法, 因为在Class.getResource()方法中会对资源名称作一定的处理, 这在上面介绍了, 下面举个实例:
假设我的当前类在Eclipse工程Database下, 类所在的包是com.bbebfe.test, 而icons目录放在bin/com/bbebfe/test/目录下, 我需要得到icons/sample.gif文件的URL, 则调用this.getClass().getResource()得到的URL是:
file:/E:/MyLife/MyProjects/Eclipse3.2/Database/bin/com/bbebfe/test/icons/disremove.gif
3, 有时候我们希望某个jar库的图像资源在同一个icons下统一管理, 而不是为每个包下面的Class建一个icons, 也就是说需要以库为相对路径来查找资源, 此时则应该调用ClassLoader.getResource()方法, 举个例子:
·某个工程有如下的包结构:
com.bbebfe.ui
com.bbebfe.test
com.bbebfe.database
·如果以类为相对路径, 则在每个包下都必须建立一个icons目录, 并放置相应的资源文件. 如下:
com.bbebfe.ui/icons/...
com.bbebfe.test/icons/...
com.bbebfe.database/icons/...
·而我们可能希望在根目录下放置一个icons目录, 把所有资源放置在这里管理, 这样还可以防止资源的重复. 就是如下形式
com.bbebfe.ui
com.bbebfe.test
com.bbebfe.database
icons/sample.gif ...
则此时我们应该调用ClassLoader.getResource方法, 由于它没有对资源名称作处理, 也就是说没有将修正的包名添加到资源名称前, 所以它会在类所在的包的根下去查找资源.(运行java程序的语法是java com.bbebfe.ui.Test, 所以根目录是com目录的上级目录).
◆最后, 在Java中对资源进行定位的方法有很多种, 在Eclipse源代码中还有如下一段定位文件资源的代码, 还没有时间研究:
ProtectionDomain domain = Main.class.getProtectionDomain(); CodeSource source = null; URL result = null; if (domain != null) source = domain.getCodeSource();//获得code source if (source != null) result = source.getLocation();//获得URL String path = decode(result.getFile());// // normalize to not have leading / so we can check the form File file = new File(path); path = file.toString().replace('//', '/'); // create a file URL (via File) to normalize the form (e.g., put // the leading / on if necessary) path = new File(path).toURL().getFile();
相关推荐
Nonejs 实现磁力链接获取 DHT BT爬虫 磁力链接解析 种子解析 资源搜索
磁力链 * 使用 nodejs 实现磁力链接爬虫 磁力...* @keenwon的node磁力搜索引擎的文章,感觉非常有意思,同时也谢谢能把项目分享出来 @keenwon的项目地址antcolony 实现方式 还是有很大的不同 从获取磁力 到解析磁力
java解析wsdl文档获取方法与参数的工具类,与博客中描述内容相符。我目前把我的资源全部调成了0分,我希望不要因为其他什么原因改变我的资源下载积分,不然以后只能搞百度云等链接了。
当用户需要获取某些资源时,往往需要通过各 种搜索引擎或者专业的资源网站进行查找,而且很多时候找到 了资源链接后还需要进行各种繁琐的操作才能完成下载。而使 用 123网盘解析PHP版本源码,只需在相关网站上找到...
解析内容: 爬虫对获取的HTML进行解析,提取有用的信息。常用的解析工具有正则表达式、XPath、Beautiful Soup等。这些工具帮助爬虫定位和提取目标数据,如文本、图片、链接等。 数据存储: 爬虫将提取的数据存储到...
1,引入二维码解析的js插件llqrcode.js 2,解析的图片,这里采取的是上传图片解析(可以采用扫一扫输出的图片解析) //获取图片路径 let getObjectURL = function(file){ ...3,获取解析图片 url =
当用户需要获取某些资源时,往往需要通过各种搜索引擎或者专业的资源网站进行查找,而且很多时候找到了资源链接后还需要进行各种繁琐的操作才能完成下载。而使用 123网盘解析PHP版本源码,只需在相关网站上找到资源...
不像wav文件其头部的字段都是基于byte为单位,直接使用内存结构相同的实体即可直接读取,adts的头部字段是以bit为单位的,这就给解析其头部带来了一定的难度,几乎获取每个字段都需要进行位操作,一些跨byte的位还...
此资源转载于pudn,经本学渣亲测可用。嘿嘿
通过httpclient的方式获取返回的文本,也可以访问某些支持http方式访问的接口,返回XML并解析
读取pe信息获取文件资源 vc编写 不够长
http://flash.weather.com.cn/wmaps/xml/beijing.xml 这个是网络的XML 代码已经解析完成,本人是初学者,有不同的看法可以留言
设计资源素材解析系统网站源码 支持N个平台 教程在压缩包里面很详细。包括了网站设置与获取cookie等详细教程
很多时候我们需要将资源文件以XML形式放在assets文件夹下,我写的这个demo是一个比较通用的获取xml输入流,解析xml获取想要数据的方法,希望对大家有帮助。
1.自动获取所在城市 2.自动获取当天日期 3.自动获取空气指数 PM2.5 4.可拓展更多信息
jsoup解析页面元素,根据url获取网络资源pdf并解析pdf里面的内容。
本程序使用cJSON库对心知天气的JSON数据包进行解析,可以方便的移植到STM32等单片机平台上,再配合WIFI或者其他通信模块即可做成个简易的天气预报系统。
想获取当前用户信息怎么办? 我们知道spring oauth2是基于spring security的实现的。 spring security可以通过SecurityContextHolder.getContext().getAuthentication().getPrincipal()获取到当前用户信息。 而...