About Tomcat under spring cannot load dependency jar in properties file for analysis

Source: Internet
Author: User

We often put the properties file that spring needs to load under java/resources, so that the problem of storage causes the properties to be packaged in the root directory of the jar, so our spring configuration path is classpath*: Xxx.properties, but such a jar when we are referenced by other projects will find the properties file is always unable to load, the problem from the source of spring to find out why this.

First, the properties are loaded as a resource, and the implementation of loading is an implementation of the Org.springframework.core.io.ResourceLoader interface, Where Org.springframework.core.io.support.PathMatchingResourcePatternResolver is used to parse classpath*: The resource definition for the prefix.

Pathmatchingresourcepatternresolver's Getresources method has the following content

String Classpath_all_url_prefix = "classpath*:"; if (Locationpattern.startswith (Classpath_all_url_prefix)) {//a class Path resource (multiple resources for same name possible) if (Getpathmatcher (). Ispattern (Locationpattern.substring ( Classpath_all_url_prefix.length ()))) {//A class path resource Patternreturn findpathmatchingresources ( Locationpattern);} else {//All class path resources with the given Namereturn findallclasspathresources (locationpattern.substring ( Classpath_all_url_prefix.length ()));}}

If we use classpath*:config-*.properties to find resources, we'll go into the Findpathmatchingresources method, and we'll see how the first few lines of this method are written.

Protected resource[] Findpathmatchingresources (String locationpattern) throws IOException {string Rootdirpath = Determinerootdir (Locationpattern); String subpattern = locationpattern.substring (Rootdirpath.length ()); resource[] rootdirresources = getresources (Rootdirpath);
here through Determinerootdir (Locationpatternthe resulting rootdirpath will become classpath*: then it will be called to the Publicresource[] Getresources (StringLocationpattern)throwsIOException This method inside, (see Code)

Public resource[] Getresources (String locationpattern) throws IOException {Assert.notnull (Locationpattern, "location Pattern must not is null ") if (Locationpattern.startswith (Classpath_all_url_prefix)) {//A class path resource (multiple R Esources for same name possible) if (Getpathmatcher (). Ispattern (Locationpattern.substring (classpath_all_url_ Prefix.length ()))) {//A class path resource Patternreturn findpathmatchingresources (Locationpattern);} else {//All class path resources with the given Namereturn findallclasspathresources (locationpattern.substring ( Classpath_all_url_prefix.length ()));}}

, and then no longer call the Findpathmatchingresources method, but call Findallclasspathresources this method, the parameters will be "classpath*:" This substring off, This time the magical place comes, let's see what's magical in Findallclasspathresources, on the code:

Protected resource[] Findallclasspathresources (string location) throws IOException {string path = Location;if ( Path.startswith ("/")) {path = path.substring (1);} enumeration<url> resourceurls = getClassLoader (). getresources (path); set<resource> result = new Linkedhashset<resource> (+), while (Resourceurls.hasmoreelements ()) {URL url = Resourceurls.nextelement (); Result.add (Convertclassloaderurl (URL));} Return Result.toarray (New Resource[result.size ()));

the code is simple, and the key is enumeration<url>. Resourceurls = getClassLoader (). getresources (path);( Note that this time path= "" In this line, the ClassLoader here determines the resources we can get if under Tomcat. This ClassLoader is Tomcat's WebappClassLoader, This time we find the path to the resource is an empty string. This class returns two URLs, one is ${webapps}/web-inf/classes, and the other is ${tomcat-home}/lib, strange, incredibly ${webapps }/web-inf/lib is not in the return URL, a bit magical, let's look!

Public enumeration<url> getresources (String name) throws IOException {        enumeration[] tmp = new enumeration[2];        if (parent = null) {            tmp[0] = parent.getresources (name);        } else {            tmp[0] = getbootstrapresources (name) ;        }        TMP[1] = findresources (name);        return new compoundenumeration<> (TMP); }

This method is actually webappclassloader directly inherit the classload come over, Parentclassload actually find the time of the classpath of the Tomcat container is findresources (name) This call, This call Webappclasspath has its own implementation and continues to look:

@Override public    enumeration<url> findresources (String name) throws IOException {        ..... omit n multiple codes        // Looking at the JAR files        synchronized (jarfiles) {            if (Openjars ())} {for                (i = 0; i < jarfileslength; i++) {                    jarentry jarentry = jarfiles[i].getjarentry (name);                    if (jarentry! = null) {                        try {                            String Jarfakeurl = GetURI (Jarrealfiles[i]). toString ();                            Jarfakeurl = "jar:" + jarfakeurl + "!/" + name;                            Result.add (New URL (Jarfakeurl));                        } catch (Malformedurlexception e) {                            //Ignore}}}}      ... This also omits n multiple code        return collections.enumeration (Result);    }

We can see this for loop inside get jarentry this sentence, jarentry jarentry = jarfiles[i].getjarentry (name); this name is actually a "" string, So the returned jarentry is null, so that all the configuration files in the jar package under all web-inf/lib will not go into the next matching process.

So the root of the problem is classpath*: This configuration, under Tomecat does not apply to the file under the root directory matching loading situation, so want to load Lib/xxx.jar package inside the Porpertis file, Need to put the porperties file in a package path, I was placed in the Config this package path to solve, you can refer to the solution.


Special note Jetty under this situation, so the problem is under Tomcat, after taking time to see how jetty Classpath is not let this phenomenon appear.

About Tomcat under spring cannot load dependency jar in properties file for analysis

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.