`
juvenshun
  • 浏览: 1588545 次
  • 性别: Icon_minigender_1
  • 来自: 苏州
社区版块
存档分类
最新评论

Maven仓库的布局

阅读更多

注:本文节选自我正在编写的《Maven实战》

任何一个构件都有其唯一的坐标,根据这个坐标可以定义其在仓库中的唯一存储路径,这便是Maven的仓库布局方式。例如log4j:log4j:1.2.15这一依赖,其对应的仓库路径为log4j/log4j/1.2.15/log4j-1.2.15.jar,细心的读者可以观察到,该路径与坐标的大致对应关系为groupId/artifactId/version/artifactId-version.packaging。下面看一段Maven的源码并结合具体的实例来理解Maven仓库的布局方式:

    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 );
    }

 

该pathOf()方法的目的是根据构件信息生成其在仓库中的路径。在阅读本段代码之前,读者可以先回顾一下上一章Maven坐标的相关内容。这里,我们根据一个实际的例子来分析路径的生成,考虑这样一个构件:groupId=org.testng、artifactId=testng、version=5.8、classifier=jdk15、packaging=jar,其对应的路径按如下步骤生成:

  1. 首先基于构件的groupId准备路径,formatAsDirectory()将groupId中的句点分隔符转换成路径分隔符,该例中,groupId org.testng就会被转换成org/testng,之后再加一个路径分隔符斜杠,那么org.testng就成为了org/testng/。
  2. 基于构件的artifactId准备路径,也就是在前面的基础上加上artifactId以及一个路径分隔符,该例中的artifactId为testng,那么在这一步过后路径就成为了org/testng/testng/。
  3. 接着使用版本信息,在前面的基础上加上version和路径分隔符,该例中版本是5.8,那么路径就成为了org/testng/tesgng/5.8/。
  4. 这一步再依次加上artifactId,构件分隔符连字号,以及version,于是构建的路径就变成了org/testng/testng/5.8/testng-5.8。读者可能会注意到这里使用了artifactId.getVersion(),而上一步用的是artifactId.getBaseVersion(),version和baseVersion的区别在本章讨论SNAPSHOT的时候会具体阐述。
  5. 紧接着如果构件有classifier,就加上构件分隔符和classifier,该例中构件的classifier是jdk15,那么路径就变成org/testng/testng/5.8/testng-5.8-jdk5。
  6. 最后第检查构件的extension,若extension存在,则加上句点分隔符和extension,从代码中可以看到,extension是从artifactHandler而非artifact获取,artifactHandler是由项目的packaging决定的,因此可以说,packaging决定了构件的扩展名,该例的packaging是的jar,因此最终的路径为org/testng/testng/5.8/testng-5.8-jdk5.jar。

到这里笔者(包括读者你)都应该感谢Maven开源社区,正是由于Maven的所有源代码都是开放的,我们才能仔细得深入到其内部工作的所有细节。
由于Maven仓库是基于简单文件系统存储的,现在我们又理解了其存储方式,因此当遇到一些与仓库相关的问题时,可以很方便的查找相关文件,方便定位问题。例如当Maven无法获得项目声明的依赖时,可以简单该依赖对应的文件在仓库中是否存在,如果不存在,是否有其它版本可用,等等。

12
2
分享到:
评论
4 楼 dearshor 2010-01-10  
juvenshun 写道
adler_sui 写道
您好,请教您个问题。当我在一个关联很多Maven项目的Maven project上运行 Maven的package命令时,报错:Embedded error: [项目路径]\target\classes (Access is denied)。请问,怎么解决。期待您的指导。谢谢

看起来文件被锁住了,试试mvn clean install,还不行的话重启机器(假设是windows)

我遇到过类似的问题, 在一个multi-module project里配置了maven-dependency-plugin, 并将dependency:copy-dependencies这个goal bind到缺省phase(process-sources), 结果在aggregator project执行clean install phase的时候, 报某个module的target\classes: Access is denied.

我是在Windows平台上遇到此问题的. Linux上未尝试.
使用unlocker(Windows平台上的一个实用工具, 可以分析进程对文件的"锁"的情况, 可以强制解除这些"锁")分析后, 并未发现有任何进程锁定了target\classes. 故很是纳闷.

后将dependency:copy-dependencies bind到package phase, 问题解决.
3 楼 juvenshun 2010-01-07  
adler_sui 写道
您好,请教您个问题。当我在一个关联很多Maven项目的Maven project上运行 Maven的package命令时,报错:Embedded error: [项目路径]\target\classes (Access is denied)。请问,怎么解决。期待您的指导。谢谢

看起来文件被锁住了,试试mvn clean install,还不行的话重启机器(假设是windows)
2 楼 adler_sui 2010-01-07  
您好,请教您个问题。当我在一个关联很多Maven项目的Maven project上运行 Maven的package命令时,报错:Embedded error: [项目路径]\target\classes (Access is denied)。请问,怎么解决。期待您的指导。谢谢
1 楼 yanguoyu 2009-12-14  
up up

相关推荐

Global site tag (gtag.js) - Google Analytics