您的位置:首页 > 编程语言 > Java开发

Java resource loading explained.

2016-01-15 13:12 309 查看
Understanding how Java finds resources is important. Resource loading in Java is “location independent”, Java also differentiates between absolute and relative resource names. And these names are processed by Java ResourceLoader differently. That last little
issue may cause problems, especially because the “wrong” resource names really work under some circumstances.


1
How java locates resources

Java loads resources from the “environment”, in many cases it uses all jars in Classpath to retrieve the resource. Resource loading in java is called location independent because it is not relevant
where your code is running, it just needs correct environment to find the resources.

Given all jars and paths in Classpath, java will search relatively to each tone to find the resource you specified. You specify resources using resource names.


2
Absolute and relative resource names

Resources are referred using resource name:
getResourceAsStream("/path/resource.xml");


“/path/resource.xml” is the resource name here.

The resource name can be:

absolute like “/path/resource.xml”;

relative like “path/resource.xml”;

 

Relative means, relative to the location, where the method was called. The path will be appended if needed.
Absolute will be used as is, only first / will be removed before the search.

Example:

package
 
my.location;
 
class
 
ResourceFinder
{
...
public
 
void
 
findResources(){
   
InputStream
stream1 =
getClass().getResourceAsStream(
"/path/resource.xml"
);
   
InputStream
stream2 =
getClass().getResourceAsStream(
"path/resource.xml"
);
}
...
}
 

➕ In this case, stream1 will get the resource, located in classpath 
path/resource.xml
.

➕ stream2 will get the resource, located in classpath 
my/location/path/resource.xml
 (Relative
to package where the search was initiated).


3
ClassLoader and Class apply resource names differently

There are 
ClassLoader.getResource()
 and 
Class.getResource()
 and
they work differently!!!

java docu:

The methods in ClassLoader use the given String as the name of the

resource without applying any absolute/relative transformation (cf. the

methods in Class). The name should not have a leading “/”.

So, to extend our example:

package
 
my.location;
 
class
 
ResourceFinder
{
...
public
 
void
 
findResources(){
   
InputStream
stream1 =
getClass().getResourceAsStream(
"/path/resource.xml"
);
   
InputStream
stream2 =
getClass().getResourceAsStream(
"path/resource.xml"
);
   
InputStream
stream3 =
getClass().getClassLoader().getResourceAsStream(
"path/resource.xml"
);
   
InputStream
stream4 =
getClass().getClassLoader().getResourceAsStream(
"/path/resource.xml"
);
 
}
...
}
 

➕ stream3 will become resource in classpath under 
path/resource.xml
.

⚠ stream4 resource name 
/path/resource.xml
 is
wrong!


4
Where it is important. Example

I was assessing Maven3 against Maven2 build. Same big project, just call m3.

Following code has worked well in my previous environment:

InputStream
exportFileInputStream =
getClass().getClassLoader().getResourceAsStream(
"/com/thinkplexx/lang/de/general.xml"
);
 

But after I changed the environment (maven2 build -> maven3 build) the 
general.xml
 was missing. I know that resource is there.

Following worked:

InputStream
exportFileInputStream =
getClass().getClassLoader().getResourceAsStream(
"com/thinkplexx/lang/de/general.xml"
);
 

It is a speculation as of how the first snippet could have worked, but it deed. Going to new clean environment triggered the bug.

Links


1) http://download.oracle.com/docs/cd/E17476_01/javase/1.4.2/docs/guide/resources/resources.html

2) http://stackoverflow.com/questions/3238562/getresourceasstream-fails-under-new-environment

3) http://download.oracle.com/docs/cd/E17409_01/javase/6/docs/api/java/lang/ClassLoader.html

4) http://download.oracle.com/docs/cd/E17409_01/javase/6/docs/api/java/lang/Class.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  java