maven-assembly-plugin 的includeBaseDirectory研究

需求:

这个问题一度困扰了我好几个小时,我一开始使用maven-assembly-plugin构建tar分发包的时候,发现每次最终打包,都会在最外层有个包装层,比如我要构建的tar分发包的artifactId为abc ,那么最终打包完的tar文件总是内含abc目录,然后才是其他子目录sub1,sub2。而我们所希望的是当untar时候,能够直接出来的是子目录(sub1,sub2),而不是abc目录+abc目录里的子目录(/abc/sub1,/abc/sub2)的形式。

解决方案:

其实只要在assembly.xml中加上<includeBaseDirectory>元素,并且让其设为false就可以了,如下:

<assembly>  
      
  <id>tarball</id>  
      
  <formats>  
      
    <format>tar</format>  
      
  </formats>  
      
        
      
  <!--fixed the wrapper folder issue-->  
      
  <includeBaseDirectory>false</includeBaseDirectory>  
      
       
      
  <fileSets>  
      
 ...

关于这个参数的含义,可以参见maven-assembly-plugin的官网:

http://maven.apache.org/plugins/maven-assembly-plugin/assembly.html

深入分析:

为什么这样可以呢,我们可以对maven-assembly-plugin的源代码进行研究。

首先,当我们在pom.xml中使用maven-assembly-plugin并且在<descriptor>中配置了assembly.xml文件的位置时候:

<build>  
                 <plugins>  
                          <plugin>  
                                   <groupId>org.apache.maven.plugins</groupId>  
                                   <artifactId>maven-assembly-plugin</artifactId>  
                                   <version>2.2.1</version>  
                                   <configuration>  
                                            <appendAssemblyId>false</appendAssemblyId>  
                                            <descriptors>  
                                                    <descriptor>src/main/assembly/assembly.xml</descriptor>  
                                            </descriptors>  
                                   </configuration>  
                                   <executions>  
                                            <execution>  
                                                    <id>make-assembly</id>  
                                                    <phase>package</phase>  
                                                    <goals>  
                                                             <goal>single</goal>  
                                                    </goals>  
                                            </execution>  
                                   </executions>  
                          </plugin>  
                         ..... 
                 </plugins>  
         </build>

插件会去调用DefaultAssemblyReader的readAssemblies()方法,然后调用如下代码进行遍历<descriptors>元素:

for ( int i = 0; i < descriptors.length; i++ ) 
          { 
              getLogger().info( "Reading assembly descriptor: " + descriptors[i] ); 
              addAssemblyFromDescriptor( descriptors[i], locator, configSource, assemblies ); 
          } 
      }

我们继续跟进到addAssemblyFromDescriptor方法,可以看出它其实是用来读取一个asssembly descriptor文件(也就是我们例子中的assembly.xml),忽略参数检查,它其实核心代码如下:

扫描二维码关注公众号,回复: 604132 查看本文章
private Assembly addAssemblyFromDescriptor( final String spec, final Locator locator, 
                                               final AssemblerConfigurationSource configSource, 
                                               final List<Assembly> assemblies ) 
       throws AssemblyReadException, InvalidAssemblerConfigurationException 
   { 
      ... 
       Reader r = null; 
       try
       { 
           // TODO use ReaderFactory.newXmlReader() when plexus-utils is upgraded to 1.4.5+ 
           r = new InputStreamReader( location.getInputStream(), "UTF-8" ); 
     
           File dir = null; 
           if ( location.getFile() != null ) 
           { 
               dir = location.getFile().getParentFile(); 
           } 
     
           final Assembly assembly = readAssembly( r, spec, dir, configSource ); 
     
           assemblies.add( assembly ); 
     
           return assembly; 
       } 
     ... 
   }

所以这里可以看出,它最终在11行新建InputStreamReader,并在第19行读取assembly descriptor文件,最终读取的结果存储在Assembly对象模型中,而Assembly这个模型是有includeBaseDirectory这个成员变量的:

/** 
    * Set includes a base directory in the final archive. For 
    * example, 
    *             if you are creating an assembly named 
    * "your-app", setting 
    *             includeBaseDirectory to true will create an 
    * archive that 
    *             includes this base directory. If this option is 
    * set to false 
    *             the archive created will unzip its content to 
    * the current 
    *             directory. Default value is true. 
    *  
    * @param includeBaseDirectory 
    */
   public void setIncludeBaseDirectory( boolean includeBaseDirectory ) 
   { 
       this.includeBaseDirectory = includeBaseDirectory; 
   } //-- void setIncludeBaseDirectory( boolean )

以上是解析assembly descriptor并且设置了includeBaseDirectory,现在我们来看下如何使用这个属性。很显然,在不看代码之前,我们很容易猜想到,它肯定影响了最终打包的行为,正如我们所期望的一样。

猜你喜欢

转载自fireinwind.iteye.com/blog/2103795