java Resource 资源加载:
xml properties 包名路径
1 ClassLoad.getResource(String str);
2 Class.getResource(Stirng str);
看第二种加载方式的内部一段代码
- private String resolveName(String name) {
- if (name == null) {
- return name;
- }
- if (!name.startsWith("/")) {
- Class c = this;
- while (c.isArray()) {
- c = c.getComponentType();
- }
- String baseName = c.getName();
- int index = baseName.lastIndexOf('.');
- if (index != -1) {
- name = baseName.substring(0, index).replace('.', '/')
- +"/"+name;
- }
- } else {
- name = name.substring(1);
- }
- return name;
- }
这就说明了
1最终都是通过ClassLoad进行加载的
2第二种方式是可以使用相对路径的,也就是资源相对于本类路径下的路径
如果本来的包名为com.xx.test 下面有一个xx.xml文件和xx.java类。
我们在xx.java类中想加载xx.xml。那么它的路径可以写为:
/com/xx/xx.xml 或者是 xx.cml。
同样的道理如果test包下面还有一个text包,这个包里面有一个yy.java
那么相对路径就是../xx.xml就可以加载到资源。
如果是ClassLoad.getResource(str);这种方式只能写路径的全限定名,不加“/”,也就是com/xx/xx.xml
后又测试了几种文件xml properties 和包路径是可以的 但是java类却不行后追踪源码发现
- private ClassLoader parent;
- public URL getResource(String name) {
- URL url;
- if (parent != null) {
- url = parent.getResource(name);
- } else {
- url = getBootstrapResource(name);
- }
- if (url == null) {
- url = findResource(name); // return null
- }
- return url;
- }
这里我们可以看到加载顺序是会始终找到它的父类或者祖先类直到没有了父类为止
然后到Bootstrap(基本类装入器是不能有java代码实例化的,由JVM控制)加载。
部分源码:
- private static URL getBootstrapResource(String name) {
- try {
- // If this is a known JRE resource, ensure that its bundle is
- // downloaded. If it isn't known, we just ignore the download
- // failure and check to see if we can find the resource anyway
- // (which is possible if the boot class path has been modified).
- sun.jkernel.DownloadManager.getBootClassPathEntryForResource(name);
- } catch (NoClassDefFoundError e) {
- // This happens while Java itself is being compiled; DownloadManager
- // isn't accessible when this code is first invoked. It isn't an
- // issue, as if we can't find DownloadManager, we can safely assume
- // that additional code is not available for download.
- }
- URLClassPath ucp = getBootstrapClassPath();
- Resource res = ucp.getResource(name);
- return res != null ? res.getURL() : null;
- }
测试代码:
测试类结构图:
- com.xx.MyTest
- - com.xx.text.MyTestC
- appconfig.xml
- appconfig.properties
- public class MyTest {
- @Test
- public void testResource() throws IOException {
- URL url3 = this.getClass().getResource("appconfig.xml");
- //or URL url3 = this.getClass().getResource("/com/xx/MyTest/appconfig.xml");
- URL url4 = this.getClass().getClassLoader().getResource("com/xx/MyTest/appconfig.properties");
- System.out.println(url4.getFile());
- System.out.println(url3.getFile());
- }
- public URL printResourceCs(String str) throws IOException {
- URL url3 = this.getClass().getResource(str);
- System.out.println(url3.getFile());
- return url3;
- }
- public URL printResourceCL(String str) throws IOException {
- URL url3 = this.getClass().getClassLoader().getResource(str);
- System.out.println(url3.getFile());
- return url3;
- }
- }
为了测试继承关系得到的基础url:
- public class MyTestC extends MyTest {
- @Test
- public void testA() throws IOException {
- Assert.assertNotNull(printResourceCs("../appConfig.xml"));
- Assert.assertNotNull(printResourceCL("sl/ewfs/dms/action/appConfig.xml"));
- }
- }
应用:
1 当我们需要加载xml,或者properties 配置文件时,有时候需要这样做。
2 利用ClassLoad我们可以得到项目运行是的根目录getClassLoader().getResource("")即可
附上加载properties 代码:
- public void loadPropertiesFromXML(String XMLPath) throws IOException { URL url = getClass().getResource(XMLPath);
- InputStream is = null;
- URLConnection con = null;
- Properties p = new Properties();
- try {
- con = url.openConnection();
- p.loadFromXML(is = con.getInputStream()); //p.load(is = con.getInputStream()); } catch (IOException e) {
- throw e;
- } finally {
- if (is != null) {
- try {
- is.close();
- } catch (IOException e) {
- e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
- }
- }
- }
- }
再来看看Spring的资源加载:
Spring的Resource接口代表底层外部资源,提供了对底层外部资源的一致性访问接口。
对应层次图
uml:
其中,最常用的有四个:
ClassPathResource:通过 ClassPathResource 以类路径的方式进行访问;
FileSystemResource:通过 FileSystemResource 以文件系统绝对路径的方式进行访问;
ServletContextResource:通过 ServletContextResource 以相对于Web应用根目录的方式进行访问;
UrlResource :通过java.net.URL来访问资源,当然它也支持File格式,如“file:”。
当然你也可以通过ApplicationContext 来取得Resource
这会带来少许的方便,因为当你可以实现ApplicationContextAware来方便的得到ApplicationContext
然后使用
- applicationContext.getResource("commons/lib/xx/xx.xx").getFile().getAbsolutePath()
;
就可以得到资源的绝对路径
下段是applicationContext getResource 的代码
- String CLASSPATH_URL_PREFIX = “classPath”;
- public Resource getResource(String location) {
- Assert.notNull(location, "Location must not be null");
- if (location.startsWith(CLASSPATH_URL_PREFIX)) {
- return new ClassPathResource(location.substring(CLASSPATH_URL_PREFIX.length()), getClassLoader());
- }
- else {
- try {
- // Try to parse the location as a URL...
- URL url = new URL(location);
- return new UrlResource(url);
- }
- catch (MalformedURLException ex) {
- // No URL -> resolve as resource path.
- return getResourceByPath(location);
- }
- }
- }
Resource参考:
http://wade6.iteye.com/blog/1706941
http://jinnianshilongnian.iteye.com/blog/1416319
http://jinnianshilongnian.iteye.com/blog/1416320
http://jinnianshilongnian.iteye.com/blog/1416321
http://jinnianshilongnian.iteye.com/blog/1416322
java 类加载机制:http://www.ibm.com/developerworks/cn/java/j-lo-classloader/