Tell you how Maven uses mirror and repository through tests and code

When I used maven before, I used the default configuration, and I didn't modify it myself. . Although many times the download is very slow, I have not had a deep understanding of the maven configuration. .

However, I have encountered a lot of problems recently. I have read the official documentation on the structure of settings and pom, and I have gained a lot.

The main reason I encountered the problem was because I modified the configuration according to the "Open Source China Maven Library Use Help" without knowing the meaning of the configuration, and the speed was improved very significantly. But there is one biggest problem with that help. See the configuration below:

<mirror>  
    <id>nexus-osc</id>  
    <mirrorOf>*</mirrorOf>  
    <name>Nexus osc</name>  
    <url>http://maven.oschina.net/content/groups/public/</url>  
</mirror>  

Please pay attention to the mirrorOf here. For the function of mirrorOf, please see:

 http://blog.csdn.net/isea533/article/details/21560089

After the configuration is * (asterisk) here, all warehouses will access the jar through the source of osc. Since the current maven warehouse of osc is the same as the central warehouse, but does not contain third-party warehouses, third-party warehouses will make mistakes , it will be searched from the main repository of osc, and it must not be found, so maven will fail to build or have various problems.

Although osc is not yet an official mirror of maven, mirrorOf can be set to central, which is the id of the official website warehouse. Only after it is modified to central, can it be fully compatible with all situations, and other configured repositories can work ( tested , you can try * and central ).

When mirrorOf configures * (asterisk), it is generally for your own private library (private library and other warehouse configurations). And if there are multiple mirrors, be sure to put the * (asterisk) at the bottom.

 

In order to have a deeper understanding of the relationship between maven and mirror and repository, we have a rough look at the source code of maven. The code is as follows:

[java] view plain copy

  1. @Deprecated  
    public ArtifactRepository getMirrorRepository(ArtifactRepository repository) {  
        Mirror mirror = mirrorSelector.getMirror(repository, legacySupport.getSession().getSettings().getMirrors());  
        if (mirror != null) {  
            String id = mirror.getId();  
            if (id == null) {  
                // TODO: this should be illegal in settings.xml  
                id = repository.getId();  
            }  
            log.debug("Using mirror: " + mirror.getUrl() + " (id: " + id + ")");  
            repository = artifactRepositoryFactory.createArtifactRepository(id, mirror.getUrl(),  
                    repository.getLayout(), repository.getSnapshots(),  
                    repository.getReleases());  
        }  
        return repository;  
    }  

     

Maven will first look for the mirror for the repository (see the next code for the search logic). If the corresponding mirror is not found in the settings, it will return the incoming repository, that is, if the repository does not have a corresponding mirror (mirror) , then it will be obtained directly with the url of the repository.

If the mirror is found, the artifactRepositoryFactory.createArtifactRepository(...) method will be executed. This method uses the mirror to construct a new repository and uses the mirror configured url to find it.

An all-match * and an external all-match external:* are defined in the system

  1. private static final String WILDCARD = "*";  
    private static final String EXTERNAL_WILDCARD = "external:*";  

     

The logic code for maven to find mirror is as follows:

  1. public Mirror getMirror(ArtifactRepository repository, List<Mirror> mirrors) {  
        String repoId = repository.getId();  
        if (repoId != null && mirrors != null) {  
            for (Mirror mirror : mirrors) {  
                if (repoId.equals(mirror.getMirrorOf()) && matchesLayout(repository, mirror)) {  
                    return mirror;  
                }  
            }  
            for (Mirror mirror : mirrors) {  
                if (matchPattern(repository, mirror.getMirrorOf()) && matchesLayout(repository, mirror)) {  
                    return mirror;  
                }  
            }  
        }  
        return null;  
    }  

     

As you can see from the code, first look for the mirrorOf and the repository with the same id and the same Layout. Since the layout is rarely configured, here is the first rule:

1. First match the mirrorOf and the mirror with the same warehouse id.

From the second for loop, you can see that the rules are used to match, and the rules match the code:

  1. static boolean matchPattern(ArtifactRepository originalRepository, String pattern) {  
        boolean result = false;  
        String originalId = originalRepository.getId();  
        //首先匹配*号,如果mirrorOf是*号,就用当前的镜像  
        //或者如果当前的mirrorOf和repository的id一样也返回(这在前面的for循环处理过,所以这种情况基本不会出现)  
        if (WILDCARD.equals(pattern) || pattern.equals(originalId)) {  
            result = true;  
        } else {  
            //其次mirrorOf支持多个用逗号隔开,这里先拆分,逐个循环  
            String[] repos = pattern.split(",");  
            for (String repo : repos) {  
                //repo支持!(感叹号)来屏蔽一个repository的Id,这里先判断如果是排除的,就return false  
                if (repo.length() > 1 && repo.startsWith("!")) {  
                    if (repo.substring(1).equals(originalId)) {  
                        // explicitly exclude. Set result and stop processing.  
                        result = false;  
                        break;  
                    }  
                }  
                //逗号隔开中的一个值和repository的id一样就返回true  
                else if (repo.equals(originalId)) {  
                    result = true;  
                    break;  
                }  
                //检查外部匹配external:*  
                else if (EXTERNAL_WILDCARD.equals(repo) && isExternalRepo(originalRepository)) {  
                    result = true;  
                }  
                //最后检查*匹配  
                else if (WILDCARD.equals(repo)) {  
                    result = true;  
                }  
            }  
        }  
        return result;  
    }  

     

Because the code is relatively long, it is written as code comments, the code is easy to understand, you can refer to the comments.

From this code you can get the following rules:

2. If mirrorOf is * (asterisk) or the same as the repo id, use the mirror

3. For the case of multiple or one mirrorOf, judge from the first one

    3.1 If it is an exclusion option, do not use this mirror

    3.2 Use this mirror if it happens to be the same as the repo id

    3.3 Determine whether there is an external match (there is also an isExternalRepo method to determine whether it is a local repository), if it is not a local repository, use the mirror

    3.4 Determine whether it is * (asterisk), if so, use the image.

In addition to the rules 1, 2, 3 (1~4), you also need to pay attention to the outermost loop. First, the loop will start from the first mirror configured in settings, and then loop from the content separated by mirrorOf commas.

 

Through the above tests and understanding of the code, I finally figured out how maven handles the mirror and repository relationship. Also hope this helps for people who don't understand this.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326009802&siteId=291194637