Project, some of the configuration files under current classpath are sometimes read. The code for the previously used read configuration file is as follows
Public StaticProperties Loadpropertiesfile (String fileName) {Properties Prop=NewProperties (); InputStream instream=Classloader.getsystemresourceasstream (fileName); if(NULL!=instream) { Try{prop.load (instream); } Catch(IOException e) {e.printstacktrace (); } } returnprop; }
The method used is classloader.getsystemresourceasstream (filename) to get the input stream of this fileName corresponding to the properties file, and then use the Prop object's Load method. It is normal to use in the jstorm of the production environment, but after switching to jstorm in the test environment, it is found that instream is always null.
Later use the following methods, in different environments can be normal use:
Public StaticProperties Loadpropertiesfile (String fileName) {Properties Prop=NewProperties (); ClassLoader ClassLoader=Thread.CurrentThread (). Getcontextclassloader (); InputStream instream=Classloader.getresourceasstream (fileName); if(NULL!=instream) { Try{prop.load (instream); } Catch(IOException e) {e.printstacktrace (); } } returnprop; }
Obtain the ClassLoader from the current thread to load the class, and then use this classloader to get the InputStream of the configuration file. Here is still very puzzled, why there is such a problem. So choose from a number of online methods to analyze.
Here is the test code, trying to read a program with a directory called Business.properties file. This class is a restlet that runs in Tomcat and can be seen as a simple restful interface. In addition, I added a main method, not to run in the Tomcat environment, but to run a regular Java program.
@Path (value = "/test") Public classTestcode { Public Static voidMain (string[] args) {Testcode TC=NewTestcode (); Tc.testcode (); } @GET @Produces (mediatype.text_plain) @Path (value= "GetPath") PublicString Testcode () {
Method 1 URL url1= Classloader.getsystemresource ("Business.properties"); System.out.println ("Url1:\t" + (URL1 = =NULL? "NULL": Url1.getpath ())); URL Url1withslash= Classloader.getsystemresource ("/business.properties"); System.out.println ("Url1/:\t" + (Url1withslash = =NULL? "NULL": Url1withslash.getpath ()));
Method 2 ClassLoader ClassLoader2= This. GetClass (). getClassLoader (); URL Url2= Classloader2.getresource ("Business.properties"); System.out.println ("Url2:\t" + (Url2 = =NULL? "Null": Url2.getpath ()) + "; ClassLoader is:" +classloader2.tostring ()); URL Url2withslash= Classloader2.getresource ("/business.properties"); System.out.println ("Url2/:\t" + (Url2withslash = =NULL? "NULL": Url2withslash.getpath ()));
Method 3 URL Url3= This. GetClass (). GetResource ("Business.properties"); System.out.println ("Url3:\t" + (Url3 = =NULL? "NULL": Url3.getpath ())); URL Url3withslash= This. GetClass (). GetResource ("/business.properties"); System.out.println ("Url3/:\t" + (Url3withslash = =NULL? "NULL": Url3withslash.getpath ()));
Method 4 ClassLoader ClassLoader4=Thread.CurrentThread (). Getcontextclassloader (); URL Url4= Classloader4.getresource ("Business.properties"); System.out.println ("Url4:\t" + (Url4 = =NULL? "Null": Url4.getpath ()) + "; ClassLoader is:" +classloader4.tostring ()); URL Url4withslash= Classloader4.getresource ("/business.properties"); System.out.println ("Url4/:\t" + (Url4withslash = =NULL? "NULL": Url4withslash.getpath ())); return"OK"; }}
Here's a look at the difference between running with Tomcat and directly running the main method output.
Through the main method, directly run the program, the output is:
URL1:/d:/thomas-dev/team-building-master/target/classes/business.properties
Url1/:null
Url2:/d:/thomas-dev/team-building-master/target/classes/business.properties;classloader Is:[email protected]
Url2/:null
Url3:null
Url3/:/d:/thomas-dev/team-building-master/target/classes/business.properties
Url4:/d:/thomas-dev/team-building-master/target/classes/business.properties;classloader Is:[email protected]
Url4/:null
Running through Tomcat, and then accessing this restful interface, the result is:
Url1:null
Url1/:null
Url2:/d:/apache-tomcat-8.0.33/webapps/root/web-inf/classes/business.properties;classloader Is:WebappClassLoader
Context:root
Delegate:false
----------> Parent Classloader:
[Email protected]
Url2/:/d:/apache-tomcat-8.0.33/webapps/root/web-inf/classes/business.properties
Url3:null
Url3/:/d:/apache-tomcat-8.0.33/webapps/root/web-inf/classes/business.properties
Url4:/d:/apache-tomcat-8.0.33/webapps/root/web-inf/classes/business.properties;classloader Is:WebappClassLoader
Context:root
Delegate:false
----------> Parent Classloader:
[Email protected]
Url4/:/d:/apache-tomcat-8.0.33/webapps/root/web-inf/classes/business.properties
After inquiry information to know:
Method 1: Using the JVM's ClassLoader, if it is a directly running Java program, then it is really called the JVM ClassLoader, so the call to the root of the program can get this file. In Tomcat, this class is not loaded by the system's own ClassLoader, but by a webappclassloader, which is loaded by the JVM's ClassLoader, which is null
Method 2: Get the ClassLoader that loads the current class, this classloader will change as the environment changes, you can see that the first direct run ClassLoader is the JVM's own ClassLoader Is:[email protected], And in Tomcat is WebappClassLoader, its parent is [email protected], can get to the properties file, so Method 2 is feasible.
Method 3: Call the GetResource method directly from the class of the current object, just go in and call the ResolveName method, the ResolveName method, to determine whether the file path starts with/or. To determine whether it is relative to the current class file directory or relative to the program root, and then gets the classloader of the current class as in Method 2, if not obtained, uses the system's own ClassLoader. This method is more intelligent and can be used, but it needs to be added to the program root directory compared to other methods.
Method 4: Get the ClassLoader that loads the current thread, the current class is called on the current thread, then their ClassLoader objects are the same, and they can see that the memory address of the ClassLoader they output is the same.
The understanding is still relatively simple, some in-depth problems are not clear, after-depth understanding of ClassLoader and then add.
About Getsystemresource, GetResource's summary