【maven】snapshot release

拉取jar包时,release和snapshot的逻辑是不同的。release版本先看本地仓库是否存在,如果存在就直接使用,否则才会去远程仓库下载。但是snapshot则不同,会根据updataPolicy来处理。如果到了更新周期,即使本地有,也会去远程仓库查看,最后返回最新的快照版本。

策略在pom中定义:

   <repository>
      <id>nexus1</id>
      <name>Nexus1</name>
      <url>http://localhost:8081/repository/release/</url>
      <releases>
        <enabled>true</enabled>
        <updatePolicy>always</updatePolicy>
      </releases>
      <snapshots>
        <enabled>true</enabled>
        <updatePolicy>always</updatePolicy>
      </snapshots>
    </repository>

always:每一次都去远程查看

daily:每天

never:从不

不写,默认是daily。

updatePolicy只对快照版本有效,如上在releases配置是无效的,即,即使配置了always,但只要本地有,就不会查看远程。

我们可以不指定updatePolicy,而在mvn package或者compile命令中添加-U参数,该参数会强制使用远程或本地中最新的snapshot版本,在开发中是一个利器。

资料:

Maven Dependency Resolution - A Repository Perspective
by Juven Xu on December 15, 2009
Tags: Nexus Repo Reel, Everything Open Source, Maven, Tutorial

Dependencies and repositories are central to Maven. Most people approach Maven as a tool in a very large stack of technology and they might not have the time to dig into the details. You might be using Eclipse, Maven, Nexus, Hudson, in addition to the various libraries and servers that are involved in your development environment, and Maven's dependency management is often so effective at hiding the details of repositories and dependencies that you take some of the complexity behind the scenes for granted. This post explains how dependencies and repositories work together for people who are interested some of the details that make dependency management in Maven "just work".

First of all, we need to know the default repository layout, which affects the repository path of each artifact. The related Maven source code is easy to understand, here it is:

  private static final char PATH_SEPARATOR = '/';

  private static final char GROUP_SEPARATOR = '.';

  private static final char ARTIFACT_SEPARATOR = '-';

  public String pathOf( Artifact artifact )
  {
    ArtifactHandler artifactHandler = artifact.getArtifactHandler();

    StringBuilder path = new StringBuilder( 128 );

    path.append( formatAsDirectory( artifact.getGroupId() ) ).append( PATH_SEPARATOR );
    path.append( artifact.getArtifactId() ).append( PATH_SEPARATOR );
    path.append( artifact.getBaseVersion() ).append( PATH_SEPARATOR );
    path.append( artifact.getArtifactId() ).append( ARTIFACT_SEPARATOR ).append( artifact.getVersion() );

    if ( artifact.hasClassifier() )
    {
      path.append( ARTIFACT_SEPARATOR ).append( artifact.getClassifier() );
    }

    if ( artifactHandler.getExtension() != null && artifactHandler.getExtension().length() > 0 )
    {
      path.append( GROUP_SEPARATOR ).append( artifactHandler.getExtension() );
    }

    return path.toString();
  }

  private String formatAsDirectory( String directory )
  {
    return directory.replace( GROUP_SEPARATOR, PATH_SEPARATOR );
  }
Take TestNG as an example, assume the artifact coordinate is groupId=org.testng, artifactId=testng, version=4.8, classifier=jdk15, and packaging=jar, the above code runs like this:

Calcuate the repository path from the groupId, replace the groupId separator dot with path separator slash, and append another path separator. So, org.testng becomes org/testng/.
Append the artifactId and a path separator. Since in this example the artifactId is testng, so the path becomes org/testng/testng/.
Append the artifact's base version and a path separator. For release artifacts, base version is the version, for snapshots, timestamp will be converted to SNAPSHOT to get the base version. In this example, the base version is 5.8, so the path becomes org/testng/testng/5.8/.
Append the artifactId, a artifact separator hyphen, and the version. Now, the path becomes org/testng/testng/5.8/testng-5.8.
If the artifact has a classifier, append a artifact separator and the classifier. In this example the classifier is jdk15, so the path becomes org/testng/testng/5.8/testng-5.8-jdk15.
Finally, get the artifact extension from artifactHandler. Each packaging type has its own artifactHandler, so the extension is determined by packaging, for default packaging type jar, the extension is also jar. Append a groupId separator dot, and the extension. So the path is finally org/testng/testng/5.8/testng-5.8-jdk15.jar.
Now we know how Maven gets the repository path from artifact coordinate, but this is not the whole story. What if the artifact does not exist in local repository? what if the version of artifact is SNAPSHOT? How does Maven know where and how to get the latest SNAPSHOT?

When Maven resolves a dependency from a repository, these are the basic steps it follows:

If the scope of this dependency is system, simply resolve it from local file system.
Try to find the dependency from local repository, resolve it if it's found.
If the version of the dependency is explicit and non-SNAPSHOT, iterate though the remote repositories to download it, and resolve it if it's found.
(For version RELEASE or LATEST) When it's required, iterate all the remote repositories to get groupId/artifactId/maven-metadata.xml and merge them with the local one.
(For version RELEASE or LATEST) Use the merged metadata to construct an explicit non-snapshot version, resolve it if it's found locally, otherwise download it from remote repository.
(For SNAPSHOT version) When it's required, iterate though the remote repositories to get groupId/artifactId/version/maven-metadata.xml and merge them with the local one.
(For SNAPSHOT version) Use the merged metadata to construct an explicit snapshot version, resolve it if it's found locally, otherwise download it from remote repository.
(For SNAPSHOT version) If the resolved snapshot version is of timestamp style, like 1.4.1-20091104.121450-121, copy the file to a non-timestamp style, like 1.4.1-SNAPSHOT, and use this file.
A few notes:

In step 4 and 6: 'when it's required' means release/snapshot must be enabled for the repository, and repository updatePolicy is satisfied, or force update is enabled by -U options.

In step 5: In maven 2, LATEST will be constructed to the real latest version, no matter it's snapshots or not, but in maven 3, only the latest non-snapshot version will be used.

in step 4: a typical groupId/artifactId/maven-metadata.xml is like this:

<!--?xml version="1.0" encoding="UTF-8"?-->

  org.sonatype.nexus
  nexus

    1.4.2-SNAPSHOT
    1.4.0

      1.3.5
      1.3.6
      1.3.7-SNAPSHOT
      1.4.0-SNAPSHOT
      1.4.0
      1.4.0.1-SNAPSHOT
      1.4.1-SNAPSHOT
      1.4.1.1-SNAPSHOT
      1.4.2-SNAPSHOT

    20091214221557
All the available versions in this directory are listed in order. The latest element points to the latest version, and the release element points to the latest release version. With the help of this file, Maven knows what the latest release version is.

In step 6: a typical groupId/artifactId/version/maven-metadata.xml is like this:

<!--?xml version="1.0" encoding="UTF-8"?-->

  org.sonatype.nexus
  nexus
  1.4.2-SNAPSHOT

      20091214.221414
      13

    20091214221558
The timestamp and buildnumber of the latest snapshot is listed, so Maven can understand what the latest snapshot artifact file is. In this case, it is nexus-1.4.2-20091214.221414-13.pom.

Now that you are familiar with the process Maven uses to resolve dependencies, calculate dependency paths, and resolve conflicts you can refer to this post whenever you have an unexpected failure resolving a dependency.



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值