maven下产生一个包含依赖jar的可执行jar文件(create an executable JAR with dependencies using Maven)

 MAVEN  maven下产生一个包含依赖jar的可执行jar文件(create an executable JAR with dependencies using Maven)已关闭评论
4月 082021
 

想使用 java -jar xxx.jar 命令行直接执行一个可执行的jar包,而这个xxx.jar包是包含第三方的依赖包的,网上有许多文章描述如何修改pom.xml,但实际是没什么效果的,实验下来如下方法可以达到想要的效果:

 

  •  1.  pom.xml 的build下添加下列 plugin。
<build>
    <plugins>
      <plugin>
        <artifactId>maven-assembly-plugin</artifactId>
        <configuration>
          <archive>
            <manifest>
              <mainClass>com.ouu.App</mainClass>
            </manifest>
          </archive>
          <descriptorRefs>
            <descriptorRef>jar-with-dependencies</descriptorRef>
          </descriptorRefs>
        </configuration>
      </plugin>

    </plugins>
</build>
  • 2. 进入项目根目录, 在命令行下运行:

mvn clean compile assembly:single

这是在项目target目录下会产生一个xxxx-jar-with-dependencies.jar的可执行文件

mvn打包时出现“Could not transfer artifact xxx from/to central (http://repo1.maven.org/maven2/): Failed to transfer file … HTTPS Required. Return code is: 501 ” 解决办法

 MAVEN  mvn打包时出现“Could not transfer artifact xxx from/to central (http://repo1.maven.org/maven2/): Failed to transfer file … HTTPS Required. Return code is: 501 ” 解决办法已关闭评论
3月 092020
 

命令行mvn打包dubbo-admin时出现下面提示:

[INFO] Scanning for projects…

Downloading: http://repo1.maven.org/mavenDownloading: http://repo1.maven.org/mavenDownloading: http://repo1.maven.org/mavenDownloading: http://repo1.maven.org/mavenDownloading: http://repo1.maven.org/maven2/org/springframework/boot/spring-boot-starter-parent/2.1.4.RELEASE/spring-boot-starter-parent-2.1.4.RELEASE.pom

[ERROR] The build could not read 1 project -> [Help 1]

[ERROR]   

[ERROR]   The project org.apache:dubbo-admin:0.1 (/Users/jqzhu/Documents/codes/dubbo-admin/pom.xml) has 1 error

[ERROR]     Non-resolvable import POM: Could not transfer artifact org.springframework.boot:spring-boot-starter-parent:pom:2.1.4.RELEASE from/to central (http://repo1.maven.org/maven2/): Failed to transfer file: http://repo1.maven.org/maven2/org/springframework/boot/spring-boot-starter-parent/2.1.4.RELEASE/spring-boot-starter-parent-2.1.4.RELEASE.pom. Return code is: 501 , ReasonPhrase:HTTPS Required. @ line 90, column 16 -> [Help 2]

[ERROR]

[ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.

[ERROR] Re-run Maven using the -X switch to enable full debug logging.

[ERROR]

[ERROR] For more information about the errors and possible solutions, please read the following articles:

[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/ProjectBuildingException

[ERROR] [Help 2] http://cwiki.apache.org/confluence/display/MAVEN/UnresolvableModelException

看来需要使用https代替http。

 

原因:

Effective January 15, 2020, The Central Repository no longer supports insecure communication over plain HTTP and requires that all requests to the repository are encrypted over HTTPS.

解决办法:

Replace http://repo1.maven.org/maven2/ with https://repo1.maven.org/maven2/

Replace http://repo.maven.apache.org/maven2/ with https://repo.maven.apache.org/maven2/

If for any reason your environment cannot support HTTPS, you have the option of using :  http://insecure.repo1.maven.org/maven2/

maven POM.xml 标签详解

 MAVEN  maven POM.xml 标签详解已关闭评论
5月 282018
 

作为参考资料,记录下:

转自:http://blog.csdn.net/sunzhenhua0608/article/details/32938533 

 pom作为项目对象模型。通过xml表示maven项目,使用pom.xml来实现。主要描述了项目:包括配置文件;开发者需要遵循的规则,缺陷管理系统,组织和licenses,项目的url,项目的依赖性,以及其他所有的项目相关因素

具体描述如下:

<project xmlns=”http://maven.apache.org/POM/4.0.0″     
    xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance”     
xsi:schemaLocation=”http://maven.apache.org/POM/4.0.0http://maven.apache.org/maven-v4_0_0.xsd”>     
    <!–父项目的坐标。如果项目中没有规定某个元素的值,那么父项目中的对应值即为项目的默认值。 坐标包括group ID,artifact ID和 version。–>    
    <parent>    
     <!–被继承的父项目的构件标识符–>    
     <artifactId/>    
     <!–被继承的父项目的全球唯一标识符–>    
     <groupId/>    
     <!–被继承的父项目的版本–>    
     <version/>    
     <!– 父项目的pom.xml文件的相对路径。相对路径允许你选择一个不同的路径。默认值是../pom.xml。Maven首先在构建当前项目的地方寻找父项 目的pom,其次在文件系统的这个位置(relativePath位置),然后在本地仓库,最后在远程仓库寻找父项目的pom。–>    
     <relativePath/>    
 </parent>    
 <!–声明项目描述符遵循哪一个POM模型版本。模型本身的版本很少改变,虽然如此,但它仍然是必不可少的,这是为了当Maven引入了新的特性或者其他模型变更的时候,确保稳定性。–>       
    <modelVersion>4.0.0</modelVersion>     
    <!–项目的全球唯一标识符,通常使用全限定的包名区分该项目和其他项目。并且构建时生成的路径也是由此生成, 如com.mycompany.app生成的相对路径为:/com/mycompany/app–>     
    <groupId>asia.banseon</groupId>     
    <!– 构件的标识符,它和group ID一起唯一标识一个构件。换句话说,你不能有两个不同的项目拥有同样的artifact ID和groupID;在某个 特定的group ID下,artifact ID也必须是唯一的。构件是项目产生的或使用的一个东西,Maven为项目产生的构件包括:JARs,源 码,二进制发布和WARs等。–>     
    <artifactId>banseon-maven2</artifactId>     
    <!–项目产生的构件类型,例如jar、war、ear、pom。插件可以创建他们自己的构件类型,所以前面列的不是全部构件类型–>     
    <packaging>jar</packaging>     
    <!–项目当前版本,格式为:主版本.次版本.增量版本-限定版本号–>     
    <version>1.0-SNAPSHOT</version>     
    <!–项目的名称, Maven产生的文档用–>     
    <name>banseon-maven</name>     
    <!–项目主页的URL, Maven产生的文档用–>     
    <url>http://www.baidu.com/banseon</url>     
    <!– 项目的详细描述, Maven 产生的文档用。  当这个元素能够用HTML格式描述时(例如,CDATA中的文本会被解析器忽略,就可以包含HTML标 签), 不鼓励使用纯文本描述。如果你需要修改产生的web站点的索引页面,你应该修改你自己的索引页文件,而不是调整这里的文档。–>     
    <description>A maven project to study maven.</description>     
    <!–描述了这个项目构建环境中的前提条件。–>    
 <prerequisites>    
  <!–构建该项目或使用该插件所需要的Maven的最低版本–>    
    <maven/>    
 </prerequisites>    
 <!–项目的问题管理系统(Bugzilla, Jira, Scarab,或任何你喜欢的问题管理系统)的名称和URL,本例为 jira–>     
    <issueManagement>    
     <!–问题管理系统(例如jira)的名字,–>     
        <system>jira</system>     
        <!–该项目使用的问题管理系统的URL–>    
        <url>http://jira.baidu.com/banseon</url>     
    </issueManagement>     
    <!–项目持续集成信息–>    
 <ciManagement>    
  <!–持续集成系统的名字,例如continuum–>    
  <system/>    
  <!–该项目使用的持续集成系统的URL(如果持续集成系统有web接口的话)。–>    
  <url/>    
  <!–构建完成时,需要通知的开发者/用户的配置项。包括被通知者信息和通知条件(错误,失败,成功,警告)–>    
  <notifiers>    
   <!–配置一种方式,当构建中断时,以该方式通知用户/开发者–>    
   <notifier>    
    <!–传送通知的途径–>    
    <type/>    
    <!–发生错误时是否通知–>    
    <sendOnError/>    
    <!–构建失败时是否通知–>    
    <sendOnFailure/>    
    <!–构建成功时是否通知–>    
    <sendOnSuccess/>    
    <!–发生警告时是否通知–>    
    <sendOnWarning/>    
    <!–不赞成使用。通知发送到哪里–>    
    <address/>    
    <!–扩展配置项–>    
    <configuration/>    
   </notifier>    
  </notifiers>    
 </ciManagement>    
 <!–项目创建年份,4位数字。当产生版权信息时需要使用这个值。–>    
    <inceptionYear/>    
    <!–项目相关邮件列表信息–>     
    <mailingLists>    
     <!–该元素描述了项目相关的所有邮件列表。自动产生的网站引用这些信息。–>     
        <mailingList>     
         <!–邮件的名称–>    
            <name>Demo</name>     
            <!–发送邮件的地址或链接,如果是邮件地址,创建文档时,mailto: 链接会被自动创建–>     
            <post>[email protected]com</post>     
            <!–订阅邮件的地址或链接,如果是邮件地址,创建文档时,mailto: 链接会被自动创建–>     
            <subscribe>[email protected]</subscribe>     
            <!–取消订阅邮件的地址或链接,如果是邮件地址,创建文档时,mailto: 链接会被自动创建–>     
            <unsubscribe>[email protected]</unsubscribe>     
            <!–你可以浏览邮件信息的URL–>    
            <archive>http:/hi.baidu.com/banseon/demo/dev/</archive>     
        </mailingList>     
    </mailingLists>     
    <!–项目开发者列表–>     
    <developers>     
     <!–某个项目开发者的信息–>    
        <developer>     
         <!–SCM里项目开发者的唯一标识符–>    
            <id>HELLO WORLD</id>     
            <!–项目开发者的全名–>    
            <name>banseon</name>     
            <!–项目开发者的email–>    
            <email>[email protected]</email>     
            <!–项目开发者的主页的URL–>    
            <url/>    
            <!–项目开发者在项目中扮演的角色,角色元素描述了各种角色–>    
            <roles>     
                <role>Project Manager</role>     
                <role>Architect</role>     
            </roles>    
            <!–项目开发者所属组织–>    
            <organization>demo</organization>     
            <!–项目开发者所属组织的URL–>    
            <organizationUrl>http://hi.baidu.com/banseon</organizationUrl>     
            <!–项目开发者属性,如即时消息如何处理等–>    
            <properties>     
                <dept>No</dept>     
            </properties>    
            <!–项目开发者所在时区, -11到12范围内的整数。–>    
            <timezone>-5</timezone>     
        </developer>     
    </developers>     
    <!–项目的其他贡献者列表–>     
    <contributors>    
     <!–项目的其他贡献者。参见developers/developer元素–>    
     <contributor>    
   <name/><email/><url/><organization/><organizationUrl/><roles/><timezone/><properties/>    
     </contributor>         
    </contributors>       
    <!–该元素描述了项目所有License列表。 应该只列出该项目的license列表,不要列出依赖项目的 license列表。如果列出多个license,用户可以选择它们中的一个而不是接受所有license。–>     
    <licenses>    
     <!–描述了项目的license,用于生成项目的web站点的license页面,其他一些报表和validation也会用到该元素。–>     
        <license>    
         <!–license用于法律上的名称–>    
            <name>Apache 2</name>     
            <!–官方的license正文页面的URL–>    
            <url>http://www.baidu.com/banseon/LICENSE-2.0.txt</url>     
            <!–项目分发的主要方式:    
              repo,可以从Maven库下载    
              manual, 用户必须手动下载和安装依赖–>    
            <distribution>repo</distribution>     
            <!–关于license的补充信息–>    
            <comments>A business-friendly OSS license</comments>     
        </license>     
    </licenses>     
    <!–SCM(Source Control Management)标签允许你配置你的代码库,供Maven web站点和其它插件使用。–>     
    <scm>     
        <!–SCM的URL,该URL描述了版本库和如何连接到版本库。欲知详情,请看SCMs提供的URL格式和列表。该连接只读。–>     
        <connection>     
            scm:svn:http://svn.baidu.com/banseon/maven/banseon/banseon-maven2-trunk(dao-trunk)      
        </connection>     
        <!–给开发者使用的,类似connection元素。即该连接不仅仅只读–>    
        <developerConnection>     
            scm:svn:http://svn.baidu.com/banseon/maven/banseon/dao-trunk      
        </developerConnection>    
        <!–当前代码的标签,在开发阶段默认为HEAD–>    
        <tag/>           
        <!–指向项目的可浏览SCM库(例如ViewVC或者Fisheye)的URL。–>     
        <url>http://svn.baidu.com/banseon</url>     
    </scm>     
    <!–描述项目所属组织的各种属性。Maven产生的文档用–>     
    <organization>     
     <!–组织的全名–>    
        <name>demo</name>     
        <!–组织主页的URL–>    
        <url>http://www.baidu.com/banseon</url>     
    </organization>    
    <!–构建项目需要的信息–>    
    <build>    
     <!–该元素设置了项目源码目录,当构建项目的时候,构建系统会编译目录里的源码。该路径是相对于pom.xml的相对路径。–>    
  <sourceDirectory/>    
  <!–该元素设置了项目脚本源码目录,该目录和源码目录不同:绝大多数情况下,该目录下的内容 会被拷贝到输出目录(因为脚本是被解释的,而不是被编译的)。–>    
  <scriptSourceDirectory/>    
  <!–该元素设置了项目单元测试使用的源码目录,当测试项目的时候,构建系统会编译目录里的源码。该路径是相对于pom.xml的相对路径。–>    
  <testSourceDirectory/>    
  <!–被编译过的应用程序class文件存放的目录。–>    
  <outputDirectory/>    
  <!–被编译过的测试class文件存放的目录。–>    
  <testOutputDirectory/>    
  <!–使用来自该项目的一系列构建扩展–>    
  <extensions>    
   <!–描述使用到的构建扩展。–>    
   <extension>    
    <!–构建扩展的groupId–>    
    <groupId/>    
    <!–构建扩展的artifactId–>    
    <artifactId/>    
    <!–构建扩展的版本–>    
    <version/>    
   </extension>    
  </extensions>    
  <!–当项目没有规定目标(Maven2 叫做阶段)时的默认值–>    
  <defaultGoal/>    
  <!–这个元素描述了项目相关的所有资源路径列表,例如和项目相关的属性文件,这些资源被包含在最终的打包文件里。–>    
  <resources>    
   <!–这个元素描述了项目相关或测试相关的所有资源路径–>    
   <resource>    
    <!– 描述了资源的目标路径。该路径相对target/classes目录(例如${project.build.outputDirectory})。举个例 子,如果你想资源在特定的包里(org.apache.maven.messages),你就必须该元素设置为org/apache/maven /messages。然而,如果你只是想把资源放到源码目录结构里,就不需要该配置。–>    
    <targetPath/>    
    <!–是否使用参数值代替参数名。参数值取自properties元素或者文件里配置的属性,文件在filters元素里列出。–>    
    <filtering/>    
    <!–描述存放资源的目录,该路径相对POM路径–>    
    <directory/>    
    <!–包含的模式列表,例如**/*.xml.–>    
    <includes/>    
    <!–排除的模式列表,例如**/*.xml–>    
    <excludes/>    
   </resource>    
  </resources>    
  <!–这个元素描述了单元测试相关的所有资源路径,例如和单元测试相关的属性文件。–>    
  <testResources>    
   <!–这个元素描述了测试相关的所有资源路径,参见build/resources/resource元素的说明–>    
   <testResource>    
    <targetPath/><filtering/><directory/><includes/><excludes/>    
   </testResource>    
  </testResources>    
  <!–构建产生的所有文件存放的目录–>    
  <directory/>    
  <!–产生的构件的文件名,默认值是${artifactId}-${version}。–>    
  <finalName/>    
  <!–当filtering开关打开时,使用到的过滤器属性文件列表–>    
  <filters/>    
  <!–子项目可以引用的默认插件信息。该插件配置项直到被引用时才会被解析或绑定到生命周期。给定插件的任何本地配置都会覆盖这里的配置–>    
  <pluginManagement>    
   <!–使用的插件列表 。–>    
   <plugins>    
    <!–plugin元素包含描述插件所需要的信息。–>    
    <plugin>    
     <!–插件在仓库里的group ID–>    
     <groupId/>    
     <!–插件在仓库里的artifact ID–>    
     <artifactId/>    
     <!–被使用的插件的版本(或版本范围)–>    
     <version/>    
     <!–是否从该插件下载Maven扩展(例如打包和类型处理器),由于性能原因,只有在真需要下载时,该元素才被设置成enabled。–>    
     <extensions/>    
     <!–在构建生命周期中执行一组目标的配置。每个目标可能有不同的配置。–>    
     <executions>    
      <!–execution元素包含了插件执行需要的信息–>    
      <execution>    
       <!–执行目标的标识符,用于标识构建过程中的目标,或者匹配继承过程中需要合并的执行目标–>    
       <id/>    
       <!–绑定了目标的构建生命周期阶段,如果省略,目标会被绑定到源数据里配置的默认阶段–>    
       <phase/>    
       <!–配置的执行目标–>    
       <goals/>    
       <!–配置是否被传播到子POM–>    
       <inherited/>    
       <!–作为DOM对象的配置–>    
       <configuration/>    
      </execution>    
     </executions>    
     <!–项目引入插件所需要的额外依赖–>    
     <dependencies>    
      <!–参见dependencies/dependency元素–>    
      <dependency>    
       ……    
      </dependency>    
     </dependencies>         
     <!–任何配置是否被传播到子项目–>    
     <inherited/>    
     <!–作为DOM对象的配置–>    
     <configuration/>    
    </plugin>    
   </plugins>    
  </pluginManagement>    
  <!–使用的插件列表–>    
  <plugins>    
   <!–参见build/pluginManagement/plugins/plugin元素–>    
   <plugin>    
    <groupId/><artifactId/><version/><extensions/>    
    <executions>    
     <execution>    
      <id/><phase/><goals/><inherited/><configuration/>    
     </execution>    
    </executions>    
    <dependencies>    
     <!–参见dependencies/dependency元素–>    
     <dependency>    
      ……    
     </dependency>    
    </dependencies>    
    <goals/><inherited/><configuration/>    
   </plugin>    
  </plugins>    
 </build>    
 <!–在列的项目构建profile,如果被激活,会修改构建处理–>    
 <profiles>    
  <!–根据环境参数或命令行参数激活某个构建处理–>    
  <profile>    
   <!–构建配置的唯一标识符。即用于命令行激活,也用于在继承时合并具有相同标识符的profile。–>    
   <id/>    
   <!–自动触发profile的条件逻辑。Activation是profile的开启钥匙。profile的力量来自于它    
   能够在某些特定的环境中自动使用某些特定的值;这些环境通过activation元素指定。activation元素并不是激活profile的唯一方式。–>    
   <activation>    
    <!–profile默认是否激活的标志–>    
    <activeByDefault/>    
    <!–当匹配的jdk被检测到,profile被激活。例如,1.4激活JDK1.4,1.4.0_2,而!1.4激活所有版本不是以1.4开头的JDK。–>    
    <jdk/>    
    <!–当匹配的操作系统属性被检测到,profile被激活。os元素可以定义一些操作系统相关的属性。–>    
    <os>    
     <!–激活profile的操作系统的名字–>    
     <name>Windows XP</name>    
     <!–激活profile的操作系统所属家族(如 ‘windows’)–>    
     <family>Windows</family>    
     <!–激活profile的操作系统体系结构 –>    
     <arch>x86</arch>    
     <!–激活profile的操作系统版本–>    
     <version>5.1.2600</version>    
    </os>    
    <!–如果Maven检测到某一个属性(其值可以在POM中通过${名称}引用),其拥有对应的名称和值,Profile就会被激活。如果值    
    字段是空的,那么存在属性名称字段就会激活profile,否则按区分大小写方式匹配属性值字段–>    
    <property>    
     <!–激活profile的属性的名称–>    
     <name>mavenVersion</name>    
     <!–激活profile的属性的值–>    
     <value>2.0.3</value>    
    </property>    
    <!–提供一个文件名,通过检测该文件的存在或不存在来激活profile。missing检查文件是否存在,如果不存在则激活    
    profile。另一方面,exists则会检查文件是否存在,如果存在则激活profile。–>    
    <file>    
     <!–如果指定的文件存在,则激活profile。–>    
     <exists>/usr/local/hudson/hudson-home/jobs/maven-guide-zh-to-production/workspace/</exists>    
     <!–如果指定的文件不存在,则激活profile。–>    
     <missing>/usr/local/hudson/hudson-home/jobs/maven-guide-zh-to-production/workspace/</missing>    
    </file>    
   </activation>    
   <!–构建项目所需要的信息。参见build元素–>    
   <build>    
    <defaultGoal/>    
    <resources>    
     <resource>    
      <targetPath/><filtering/><directory/><includes/><excludes/>    
     </resource>    
    </resources>    
    <testResources>    
     <testResource>    
      <targetPath/><filtering/><directory/><includes/><excludes/>    
     </testResource>    
    </testResources>    
    <directory/><finalName/><filters/>    
    <pluginManagement>    
     <plugins>    
      <!–参见build/pluginManagement/plugins/plugin元素–>    
      <plugin>    
       <groupId/><artifactId/><version/><extensions/>    
       <executions>    
        <execution>    
         <id/><phase/><goals/><inherited/><configuration/>    
        </execution>    
       </executions>    
       <dependencies>    
        <!–参见dependencies/dependency元素–>    
        <dependency>    
         ……    
        </dependency>    
       </dependencies>    
       <goals/><inherited/><configuration/>    
      </plugin>    
     </plugins>    
    </pluginManagement>    
    <plugins>    
     <!–参见build/pluginManagement/plugins/plugin元素–>    
     <plugin>    
      <groupId/><artifactId/><version/><extensions/>    
      <executions>    
       <execution>    
        <id/><phase/><goals/><inherited/><configuration/>    
       </execution>    
      </executions>    
      <dependencies>    
       <!–参见dependencies/dependency元素–>    
       <dependency>    
        ……    
       </dependency>    
      </dependencies>    
      <goals/><inherited/><configuration/>    
     </plugin>    
    </plugins>    
   </build>    
   <!–模块(有时称作子项目) 被构建成项目的一部分。列出的每个模块元素是指向该模块的目录的相对路径–>    
   <modules/>    
   <!–发现依赖和扩展的远程仓库列表。–>    
   <repositories>    
    <!–参见repositories/repository元素–>    
    <repository>    
     <releases>    
      <enabled/><updatePolicy/><checksumPolicy/>    
     </releases>    
     <snapshots>    
      <enabled/><updatePolicy/><checksumPolicy/>    
     </snapshots>    
     <id/><name/><url/><layout/>    
    </repository>    
   </repositories>    
   <!–发现插件的远程仓库列表,这些插件用于构建和报表–>    
   <pluginRepositories>    
    <!–包含需要连接到远程插件仓库的信息.参见repositories/repository元素–>        
    <pluginRepository>    
     <releases>    
      <enabled/><updatePolicy/><checksumPolicy/>    
     </releases>    
     <snapshots>    
      <enabled/><updatePolicy/><checksumPolicy/>    
     </snapshots>    
     <id/><name/><url/><layout/>    
    </pluginRepository>    
   </pluginRepositories>    
   <!–该元素描述了项目相关的所有依赖。 这些依赖组成了项目构建过程中的一个个环节。它们自动从项目定义的仓库中下载。要获取更多信息,请看项目依赖机制。–>    
   <dependencies>    
    <!–参见dependencies/dependency元素–>    
    <dependency>    
     ……    
    </dependency>    
   </dependencies>    
   <!–不赞成使用. 现在Maven忽略该元素.–>    
   <reports/>       
   <!–该元素包括使用报表插件产生报表的规范。当用户执行“mvn site”,这些报表就会运行。 在页面导航栏能看到所有报表的链接。参见reporting元素–>    
   <reporting>    
    ……    
   </reporting>    
   <!–参见dependencyManagement元素–>    
   <dependencyManagement>    
    <dependencies>    
     <!–参见dependencies/dependency元素–>    
     <dependency>    
      ……    
     </dependency>    
    </dependencies>    
   </dependencyManagement>    
   <!–参见distributionManagement元素–>    
   <distributionManagement>    
    ……    
   </distributionManagement>    
   <!–参见properties元素–>    
   <properties/>    
  </profile>    
 </profiles>    
 <!–模块(有时称作子项目) 被构建成项目的一部分。列出的每个模块元素是指向该模块的目录的相对路径–>    
 <modules/>    
    <!–发现依赖和扩展的远程仓库列表。–>     
    <repositories>     
     <!–包含需要连接到远程仓库的信息–>    
        <repository>    
         <!–如何处理远程仓库里发布版本的下载–>    
         <releases>    
          <!–true或者false表示该仓库是否为下载某种类型构件(发布版,快照版)开启。 –>    
    <enabled/>    
    <!–该元素指定更新发生的频率。Maven会比较本地POM和远程POM的时间戳。这里的选项是:always(一直),daily(默认,每日),interval:X(这里X是以分钟为单位的时间间隔),或者never(从不)。–>    
    <updatePolicy/>    
    <!–当Maven验证构件校验文件失败时该怎么做:ignore(忽略),fail(失败),或者warn(警告)。–>    
    <checksumPolicy/>    
   </releases>    
   <!– 如何处理远程仓库里快照版本的下载。有了releases和snapshots这两组配置,POM就可以在每个单独的仓库中,为每种类型的构件采取不同的 策略。例如,可能有人会决定只为开发目的开启对快照版本下载的支持。参见repositories/repository/releases元素 –>    
   <snapshots>    
    <enabled/><updatePolicy/><checksumPolicy/>    
   </snapshots>    
   <!–远程仓库唯一标识符。可以用来匹配在settings.xml文件里配置的远程仓库–>    
   <id>banseon-repository-proxy</id>     
   <!–远程仓库名称–>    
            <name>banseon-repository-proxy</name>     
            <!–远程仓库URL,按protocol://hostname/path形式–>    
            <url>http://192.168.1.169:9999/repository/</url>     
            <!– 用于定位和排序构件的仓库布局类型-可以是default(默认)或者legacy(遗留)。Maven 2为其仓库提供了一个默认的布局;然 而,Maven 1.x有一种不同的布局。我们可以使用该元素指定布局是default(默认)还是legacy(遗留)。–>    
            <layout>default</layout>               
        </repository>     
    </repositories>    
    <!–发现插件的远程仓库列表,这些插件用于构建和报表–>    
    <pluginRepositories>    
     <!–包含需要连接到远程插件仓库的信息.参见repositories/repository元素–>    
  <pluginRepository>    
   ……    
  </pluginRepository>    
 </pluginRepositories>    
       
    <!–该元素描述了项目相关的所有依赖。 这些依赖组成了项目构建过程中的一个个环节。它们自动从项目定义的仓库中下载。要获取更多信息,请看项目依赖机制。–>     
    <dependencies>     
        <dependency>    
   <!–依赖的group ID–>    
            <groupId>org.apache.maven</groupId>     
            <!–依赖的artifact ID–>    
            <artifactId>maven-artifact</artifactId>     
            <!–依赖的版本号。 在Maven 2里, 也可以配置成版本号的范围。–>    
            <version>3.8.1</version>     
            <!– 依赖类型,默认类型是jar。它通常表示依赖的文件的扩展名,但也有例外。一个类型可以被映射成另外一个扩展名或分类器。类型经常和使用的打包方式对应, 尽管这也有例外。一些类型的例子:jar,war,ejb-client和test-jar。如果设置extensions为 true,就可以在 plugin里定义新的类型。所以前面的类型的例子不完整。–>    
            <type>jar</type>    
            <!– 依赖的分类器。分类器可以区分属于同一个POM,但不同构建方式的构件。分类器名被附加到文件名的版本号后面。例如,如果你想要构建两个单独的构件成 JAR,一个使用Java 1.4编译器,另一个使用Java 6编译器,你就可以使用分类器来生成两个单独的JAR构件。–>    
            <classifier></classifier>    
            <!–依赖范围。在项目发布过程中,帮助决定哪些构件被包括进来。欲知详情请参考依赖机制。    
                – compile :默认范围,用于编译      
                – provided:类似于编译,但支持你期待jdk或者容器提供,类似于classpath      
                – runtime: 在执行时需要使用      
                – test:    用于test任务时使用      
                – system: 需要外在提供相应的元素。通过systemPath来取得      
                – systemPath: 仅用于范围为system。提供相应的路径      
                – optional:   当项目自身被依赖时,标注依赖是否传递。用于连续依赖时使用–>     
            <scope>test</scope>       
            <!–仅供system范围使用。注意,不鼓励使用这个元素,并且在新的版本中该元素可能被覆盖掉。该元素为依赖规定了文件系统上的路径。需要绝对路径而不是相对路径。推荐使用属性匹配绝对路径,例如${java.home}。–>    
            <systemPath></systemPath>     
            <!–当计算传递依赖时, 从依赖构件列表里,列出被排除的依赖构件集。即告诉maven你只依赖指定的项目,不依赖项目的依赖。此元素主要用于解决版本冲突问题–>    
            <exclusions>    
             <exclusion>     
                    <artifactId>spring-core</artifactId>     
                    <groupId>org.springframework</groupId>     
                </exclusion>     
            </exclusions>       
            <!–可选依赖,如果你在项目B中把C依赖声明为可选,你就需要在依赖于B的项目(例如项目A)中显式的引用对C的依赖。可选依赖阻断依赖的传递性。–>     
            <optional>true</optional>    
        </dependency>    
    </dependencies>    
    <!–不赞成使用. 现在Maven忽略该元素.–>    
    <reports></reports>    
    <!–该元素描述使用报表插件产生报表的规范。当用户执行“mvn site”,这些报表就会运行。 在页面导航栏能看到所有报表的链接。–>    
 <reporting>    
  <!–true,则,网站不包括默认的报表。这包括“项目信息”菜单中的报表。–>    
  <excludeDefaults/>    
  <!–所有产生的报表存放到哪里。默认值是${project.build.directory}/site。–>    
  <outputDirectory/>    
  <!–使用的报表插件和他们的配置。–>    
  <plugins>    
   <!–plugin元素包含描述报表插件需要的信息–>    
   <plugin>    
    <!–报表插件在仓库里的group ID–>    
    <groupId/>    
    <!–报表插件在仓库里的artifact ID–>    
    <artifactId/>    
    <!–被使用的报表插件的版本(或版本范围)–>    
    <version/>    
    <!–任何配置是否被传播到子项目–>    
    <inherited/>    
    <!–报表插件的配置–>    
    <configuration/>    
    <!–一组报表的多重规范,每个规范可能有不同的配置。一个规范(报表集)对应一个执行目标 。例如,有1,2,3,4,5,6,7,8,9个报表。1,2,5构成A报表集,对应一个执行目标。2,5,8构成B报表集,对应另一个执行目标–>    
    <reportSets>    
     <!–表示报表的一个集合,以及产生该集合的配置–>    
     <reportSet>    
      <!–报表集合的唯一标识符,POM继承时用到–>    
      <id/>    
      <!–产生报表集合时,被使用的报表的配置–>    
      <configuration/>    
      <!–配置是否被继承到子POMs–>    
      <inherited/>    
      <!–这个集合里使用到哪些报表–>    
      <reports/>    
     </reportSet>    
    </reportSets>    
   </plugin>    
  </plugins>    
 </reporting>    
 <!– 继承自该项目的所有子项目的默认依赖信息。这部分的依赖信息不会被立即解析,而是当子项目声明一个依赖(必须描述group ID和 artifact ID信息),如果group ID和artifact ID以外的一些信息没有描述,则通过group ID和artifact ID 匹配到这里的依赖,并使用这里的依赖信息。–>    
 <dependencyManagement>    
  <dependencies>    
   <!–参见dependencies/dependency元素–>    
   <dependency>    
    ……    
   </dependency>    
  </dependencies>    
 </dependencyManagement>       
    <!–项目分发信息,在执行mvn deploy后表示要发布的位置。有了这些信息就可以把网站部署到远程服务器或者把构件部署到远程仓库。–>     
    <distributionManagement>    
        <!–部署项目产生的构件到远程仓库需要的信息–>    
        <repository>    
         <!–是分配给快照一个唯一的版本号(由时间戳和构建流水号)?还是每次都使用相同的版本号?参见repositories/repository元素–>    
   <uniqueVersion/>    
   <id>banseon-maven2</id>     
   <name>banseon maven2</name>     
            <url>file://${basedir}/target/deploy</url>     
            <layout/>    
  </repository>    
  <!–构件的快照部署到哪里?如果没有配置该元素,默认部署到repository元素配置的仓库,参见distributionManagement/repository元素–>     
  <snapshotRepository>    
   <uniqueVersion/>    
   <id>banseon-maven2</id>    
            <name>Banseon-maven2 Snapshot Repository</name>    
            <url>scp://svn.baidu.com/banseon:/usr/local/maven-snapshot</url>     
   <layout/>    
  </snapshotRepository>    
  <!–部署项目的网站需要的信息–>     
        <site>    
         <!–部署位置的唯一标识符,用来匹配站点和settings.xml文件里的配置–>     
            <id>banseon-site</id>     
            <!–部署位置的名称–>    
            <name>business api website</name>     
            <!–部署位置的URL,按protocol://hostname/path形式–>    
            <url>     
                scp://svn.baidu.com/banseon:/var/www/localhost/banseon-web      
            </url>     
        </site>    
  <!–项目下载页面的URL。如果没有该元素,用户应该参考主页。使用该元素的原因是:帮助定位那些不在仓库里的构件(由于license限制)。–>    
  <downloadUrl/>    
  <!–如果构件有了新的group ID和artifact ID(构件移到了新的位置),这里列出构件的重定位信息。–>    
  <relocation>    
   <!–构件新的group ID–>    
   <groupId/>    
   <!–构件新的artifact ID–>    
   <artifactId/>    
   <!–构件新的版本号–>    
   <version/>    
   <!–显示给用户的,关于移动的额外信息,例如原因。–>    
   <message/>    
  </relocation>    
  <!– 给出该构件在远程仓库的状态。不得在本地项目中设置该元素,因为这是工具自动更新的。有效的值有:none(默认),converted(仓库管理员从 Maven 1 POM转换过来),partner(直接从伙伴Maven 2仓库同步过来),deployed(从Maven 2实例部 署),verified(被核实时正确的和最终的)。–>    
  <status/>           
    </distributionManagement>    
    <!–以值替代名称,Properties可以在整个POM中使用,也可以作为触发条件(见settings.xml配置文件里activation元素的说明)。格式是<name>value</name>。–>    
    <properties/>    
</project>

maven依赖关系中Scope的取值

 MAVEN  maven依赖关系中Scope的取值已关闭评论
12月 162016
 

maven依赖关系中Scope的作用

可选择值

在POM 4中,<dependency>中还引入了<scope>,它主要管理依赖的部署。目前<scope>可以使用5个值: 
    * compile,缺省值,适用于所有阶段,会随着项目一起发布。 
    * provided,类似compile,期望JDK、容器或使用者会提供这个依赖。如servlet.jar。 
    * runtime,只在运行时使用,如JDBC驱动,适用运行和测试阶段。 
    * test,只在测试时使用,用于编译和运行测试代码。不会随项目发布。 
    * system,类似provided,需要显式提供包含依赖的jar,Maven不会在Repository中查找它。

注意

此属性没有配置的话,则默认的是compile范围的,而对于scope为test类型的话,则不会进行传递依赖

Maven打包可执行Jar的几种方法

 MAVEN  Maven打包可执行Jar的几种方法已关闭评论
11月 292016
 

一、无依赖其他任何jar

<build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-jar-plugin</artifactId>
                <version>2.4</version>
                <configuration>
                    <archive>
                        <manifest>
                            <addClasspath>true</addClasspath>
                            <classpathPrefix>lib/</classpathPrefix>
                            <mainClass>com.think.TestMain</mainClass>
                        </manifest>
                    </archive>
                </configuration>
            </plugin>
        </plugins>
    </build>

运行:mvn clean package,在target中找到打包出来的,命令后运行java -jar xxx.jar即可,但是如果程序有依赖其他包,比如程序依赖jdbc去查询db,这时候再执行就会出现找不到jdbc依赖,因为我们并没有将依赖包打进去

二、解决依赖其他包时,可执行jar的打包

1、

<build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-assembly-plugin</artifactId>
                <version>2.3</version>
                <configuration>
                    <appendAssemblyId>false</appendAssemblyId>
                    <descriptorRefs>
                        <descriptorRef>jar-with-dependencies</descriptorRef>
                    </descriptorRefs>
                    <archive>
                        <manifest>
                            <mainClass>com.think.TestMain</mainClass>
                        </manifest>
                    </archive>
                </configuration>
                <executions>
                    <execution>
                        <id>make-assembly</id>
                        <phase>package</phase>
                        <goals>
                            <goal>assembly</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

但以上方式用的比较少,因为我们依赖的jar,也会打进到我们最终生成的jar,这样不太好,假如你生成的jar要给别人使用,最好给一个纯净的。

一般用assembly会再用他另外一个功能,将我们的jar归档,打包成一个zip

2、打成一个zip包,发布项目的时候,将zip包copy到服务器上,直接unzip xxx.zip,里面包含要运行到jar以及依赖的lib,还有配置的config文件,即可直接启动服务

<build>
        <resources>
            <!-- 控制资源文件的拷贝 -->
            <resource>
                <directory>src/main/resources</directory>
                <targetPath>${project.build.directory}/classes</targetPath>
            </resource>
        </resources>
        <plugins>
            <!-- 设置源文件编码方式 -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>1.6</source>
                    <target>1.6</target>
                    <encoding>UTF-8</encoding>
                </configuration>
            </plugin>
            <!-- The configuration of maven-jar-plugin -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-jar-plugin</artifactId>
                <version>2.4</version>
                <!-- The configuration of the plugin -->
                <configuration>
                    <!-- Configuration of the archiver -->
                    <archive>

                        <!--
                            生成的jar中,不要包含pom.xml和pom.properties这两个文件
                        -->
                        <addMavenDescriptor>false</addMavenDescriptor>

                        <!-- Manifest specific configuration -->
                        <manifest>
                            <!--
                                是否要把第三方jar放到manifest的classpath中
                            -->
                            <addClasspath>true</addClasspath>
                            <!--
                               生成的manifest中classpath的前缀,因为要把第三方jar放到lib目录下,所以classpath的前缀是lib/
                           -->
                            <classpathPrefix>lib/</classpathPrefix>
                            <!--
                                应用的main class
                            -->
                            <mainClass>com.think.TestMain</mainClass>
                        </manifest>
                    </archive>
                    <!--
                        过滤掉不希望包含在jar中的文件
                    -->
                    <!--<excludes>-->
                        <!--<exclude>${project.basedir}/xml/*</exclude>-->
                    <!--</excludes>-->
                </configuration>
            </plugin>

            <!-- The configuration of maven-assembly-plugin -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-assembly-plugin</artifactId>
                <version>2.4</version>
                <!-- The configuration of the plugin -->
                <configuration>
                    <!-- Specifies the configuration file of the assembly plugin -->
                    <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>

还有一个重要的文件,名字可以随便起,我上面用的是 src/main/assembly/assembly.xml

<assembly>
    <id>bin</id>
    <includeBaseDirectory>false</includeBaseDirectory>
    <!-- 最终打包成一个用于发布的zip文件 -->
    <formats>
        <format>zip</format>
    </formats>

    <!-- Adds dependencies to zip package under lib directory -->
    <dependencySets>
        <dependencySet>
            <!--
               不使用项目的artifact,第三方jar不要解压,打包进zip文件的lib目录
           -->
            <useProjectArtifact>false</useProjectArtifact>
            <!--<outputDirectory>lib</outputDirectory>-->
            <unpack>false</unpack>
        </dependencySet>
    </dependencySets>

    <fileSets>
        <!-- 把项目相关的说明文件,打包进zip文件的根目录 -->
        <!--<fileSet>-->
            <!--<directory>${project.basedir}</directory>-->
            <!--<outputDirectory>/</outputDirectory>-->
        <!--</fileSet>-->

        <!-- 把项目的配置文件,打包进zip文件的config目录 -->
        <fileSet>
            <directory>${deploy.dir}/classes/</directory>
            <outputDirectory>/conf</outputDirectory>
            <includes>
                <include>*.xml</include>
                <include>*.properties</include>
            </includes>
        </fileSet>
        <!-- 把项目自己编译出来的jar文件,打包进zip文件的根目录 -->
        <fileSet>
            <directory>${project.build.directory}</directory>
            <outputDirectory></outputDirectory>
            <includes>
                <include>*.jar</include>
            </includes>
        </fileSet>
    </fileSets>
</assembly>

最终执行命令:mvn clean package,出来的是这样的

解压zip包,我们看到我们想要的,good

3、还有一种打包方式,上面相当于把我们想要的东西打成一个zip包,全部放到一起,看着整洁好看,但有点繁琐,我们其实可以用另外一个插件来完成,不打包,即看到上图解压后的文件

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.test</groupId>
    <artifactId>myTestJar</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>jar</packaging>

    <name>myTestJar</name>
    <url>http://maven.apache.org</url>

    <properties>
        <deploy.dir>./target/</deploy.dir>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>3.8.1</version>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.0.9</version>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.32</version>
        </dependency>
    </dependencies>

    <build>
        <finalName>myTest</finalName>
        <sourceDirectory>src/main/java</sourceDirectory>
        <resources>
            <!-- 控制资源文件的拷贝 -->
            <resource>
                <directory>src/main/resources</directory>
                <targetPath>${project.build.directory}</targetPath>
            </resource>
        </resources>
        <plugins>
            <!-- 设置源文件编码方式 -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <defaultLibBundleDir>lib</defaultLibBundleDir>
                    <source>1.6</source>
                    <target>1.6</target>
                    <encoding>UTF-8</encoding>
                </configuration>
            </plugin>
            <!-- 打包jar文件时,配置manifest文件,加入lib包的jar依赖 -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-jar-plugin</artifactId>
                <configuration>
                    <archive>
                        <manifest>
                            <addClasspath>true</addClasspath>
                            <classpathPrefix>lib/</classpathPrefix>
                            <mainClass>com.think.TestMain</mainClass>
                        </manifest>
                    </archive>
                </configuration>
            </plugin>
            <!-- 拷贝依赖的jar包到lib目录 -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-dependency-plugin</artifactId>
                <executions>
                    <execution>
                        <id>copy</id>
                        <phase>package</phase>
                        <goals>
                            <goal>copy-dependencies</goal>
                        </goals>
                        <configuration>
                            <!-- ${project.build.directory}是maven变量,内置的,表示target目录,如果不写,将在跟目录下创建/lib -->
                            <outputDirectory>${project.build.directory}/lib</outputDirectory>
                            <!-- excludeTransitive:是否不包含间接依赖包,比如我们依赖A,但是A又依赖了B,我们是否也要把B打进去 默认不打-->
                            <excludeTransitive>true</excludeTransitive>
                            <!-- 复制的jar文件去掉版本信息 -->
                            <stripVersion>true</stripVersion>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
            <!-- 解决资源文件的编码问题 -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-resources-plugin</artifactId>
                <version>2.3</version>
                <configuration>
                    <encoding>UTF-8</encoding>
                </configuration>
            </plugin>
            <!-- 打包source文件为jar文件 -->
            <plugin>
                <artifactId>maven-source-plugin</artifactId>
                <version>2.1</version>
                <configuration>
                    <attach>true</attach>
                    <encoding>UTF-8</encoding>
                </configuration>
                <executions>
                    <execution>
                        <phase>compile</phase>
                        <goals>
                            <goal>jar</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

</project>

这里采用的是maven-dependency-plugin插件,进行资源的copy。

4、

<build>
        <resources>
            <resource>
                <targetPath>${project.build.directory}/classes</targetPath>
                <directory>src/main/resources</directory>
                <filtering>true</filtering>
                <includes>
                    <include>**/*.xml</include>
                </includes>
            </resource>
        </resources>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.0</version>
                <configuration>
                    <source>1.6</source>
                    <target>1.6</target>
                    <encoding>UTF-8</encoding>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-shade-plugin</artifactId>
                <version>2.0</version>
                <executions>
                    <execution>
                        <phase>package</phase>
                        <goals>
                            <goal>shade</goal>
                        </goals>
                        <configuration>
                            <transformers>
                                <transformer
                                        implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                                    <mainClass>com.think.TestMain</mainClass>
                                </transformer>
                                <!--<transformer-->
                                        <!--implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">-->
                                    <!--<resource>applicationContext.xml</resource>-->
                                <!--</transformer>-->
                            </transformers>
                            <shadedArtifactAttached>true</shadedArtifactAttached>
                            <shadedClassifierName>executable</shadedClassifierName>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

这种方式打出来是柔和到一起,成为一个jar,

可以直接java -jar xxx.jar运行。

我们可以根据不同需要来打包,如果暴露给外面,可以采用第4种,如果是自己公司项目打包,建议2,3种,因为有时候只是改了个配置文件,不需要打包,直接把配置文件复制进去即可

转自:http://m.blog.csdn.net/article/details?id=51871705

web.xml is missing and is set to true解决

 MAVEN  web.xml is missing and is set to true解决已关闭评论
6月 132016
 

maven项目需要打包war文件时, pom.xml文件出现“web.xml is missing and <failOnMissingWebXml> is set to true”错误,可以在pom文件对应位置里添加下面一段解决 :

<build>

<plugins>

     

    <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-war-plugin</artifactId>
            <version>2.6</version>
            <configuration>
                <failOnMissingWebXml>false</failOnMissingWebXml>
            </configuration>
     </plugin>

</plugins>

</build>

 

10月 102015
 

这里介绍一个在父项目中的根结点中声明dependencyManagement和dependencies的区别

dependencyManagement

Maven 使用dependencyManagement 元素来提供了一种管理依赖版本号的方式。通常会在一个组织或者项目的最顶层的父POM 中看到dependencyManagement 元素。使用pom.xml 中的dependencyManagement 元素能让
所有在子项目中引用一个依赖而不用显式的列出版本号。Maven 会沿着父子层次向上走,直到找到一个拥有dependencyManagement 元素的项目,然后它就会使用在这个dependencyManagement 元素中指定的版本号。

 

例如在父项目里:

Xml代码  收藏代码

  1. <dependencyManagement>  
  2. <dependencies>  
  3. <dependency>  
  4. <groupId>mysql</groupId>  
  5. <artifactId>mysql-connector-java</artifactId>  
  6. <version>5.1.2</version>  
  7. </dependency>  
  8. …  
  9. <dependencies>  
  10. </dependencyManagement>  

然后在子项目里就可以添加mysql-connector时可以不指定版本号,例如:

 

Xml代码  收藏代码

  1. <dependencies>  
  2. <dependency>  
  3. <groupId>mysql</groupId>  
  4. <artifactId>mysql-connector-java</artifactId>  
  5. </dependency>  
  6. </dependencies>  

这样做的好处就是:如果有多个子项目都引用同一样依赖,则可以避免在每个使用的子项目里都声明一个版本号,这样当想升级或切换到另一个版本时,只需要在顶层父容器里更新,而不需要一个一个子项目的修改 ;另外如果某个子项目需要另外的一个版本,只需要声明version就可。

 

dependencyManagement里只是声明依赖,并不实现引入,因此子项目需要显式的声明需要用的依赖。

dependencies

相对于dependencyManagement,所有声明在dependencies里的依赖都会自动引入,并默认被所有的子项目继承。

 

classifier

如果你要发布同样的代码,但是由于技术原因需要生成两个单独的构件,你就要使用一个分类器(classifier)。例如,如果你想要构建两个单独的构件成JAR,一个使用Java 1.4 编译器,另一个使用Java 6 编译器,你就可以使用分类器
来生成两个单独的JAR构件,它们有同样的groupId:artifactId:version组合。如果你的项目使用本地扩展类库,你可以使用分类器为每一个目标平台生成一个构件。分类器常用于打包构件的源码,JavaDoc 或者二进制集合。

8月 272015
 

Sonar 概述

Sonar 是一个用于代码质量管理的开放平台。通过插件机制,Sonar 可以集成不同的测试工具,代码分析工具,以及持续集成工具。

与持续集成工具(例如 Hudson/Jenkins 等)不同,Sonar 并不是简单地把不同的代码检查工具结果(例如 FindBugs,PMD 等)直接显示在 Web 页面上,而是通过不同的插件对这些结果进行再加工处理,通过量化的方式度量代码质量的变化,从而可以方便地对不同规模和种类的工程进行代码质量管理。

在对其他工具的支持方面,Sonar 不仅提供了对 IDE 的支持,可以在 Eclipse 和 IntelliJ IDEA 这些工具里联机查看结果;同时 Sonar 还对大量的持续集成工具提供了接口支持,可以很方便地在持续集成中使用 Sonar。

此外,Sonar 的插件还可以对 Java 以外的其他编程语言提供支持,对国际化以及报告文档化也有良好的支持。

Sonar 的安装

Sonar 是 Codehaus 上面的一个开源项目,使用的是 LGPL V3 软件许可。我们可以在其官方网站上下载其源代码及安装包。

其源代码需要使用分布式版本控制软件 Git 进行检出(Check Out),命令行方式如下:

git clone git://github.com/SonarSource/sonar.git

本文主要介绍 Sonar 的使用方法,只需要到 Sonar 网站下载最近的发行包即可,本文写作时最新的版本为 2.11。

下载 zip 包后,直接解压到任意目录,由于 Sonar 自带了 Jetty 6 的应用服务器环境,所以不需要额外的安装就可以使用,值得一提的是 Sonar 也支持部署在 Apache Tomcat 应用服务器中。

在 windows 环境中,直接启动 Soanr 的 bin 目录下 windows-x86-64StartSonar.bat 即可。

然后在浏览器中访问:http://localhost:9000/

图 1. Sonar 访问界面

图 1. Sonar 访问界面

这样就成功安装并启动了 Sonar,但其中没有安装插件,需要用户下载并安装自己所需要的插件。本节以 Quality Index Plugin 为例,介绍如何下载及安装 Sonar 插件。

首先访问 Sonar 主页中 Dashboard > Sonar > Documentation > Sonar Plugin Library 路径

图 2. Sonar 插件的下载

图 2. Sonar 插件的下载

进入 Quality Index 插件,点击下载路径

图 3. Quality Index Plugin 下载

图 3. Quality Index Plugin 下载

然后将下载的 sonar-quality-index-plugin-1.1.3.jar 文件放到 sonar-2.11extensionsplugins 路径下。重启 Sonar,该插件就在 Sonar 的平台上运行并开始工作。

数据库设置

Sonar 默认使用的是 Derby 数据库,但这个数据库一般用于评估版本或者测试用途。商用及对数据库要求较高时,建议使用其他数据库。Sonar 可以支持大多数主流关系型数据库(例如 Microsoft SQL Server, MySQL, Oracle, PostgreSQL 等)

本文以 MySQL 为例说明如何更改 Sonar 的数据库设置:

  1. 在 MySQL 中创建 sonar 用户

    CREATE USER sonar IDENTIFIED BY 'sonar';
    
    GRANT ALL PRIVILEGES ON *.* TO 'sonar'@'localhost' 
    IDENTIFIED BY 'sonar' WITH GRANT OPTION;

  2. 将 MySQL 的驱动文件(如 mysql-connector-java-5.1.13.jar)拷贝到 sonar-2.11extensionsjdbc-drivermysql 目录
  3. 修改 sonar-2.11confsonar.properties 文件,用 # 注释原来 Derby 的配置项,并打开 MySQL 数据库的配置项:

    # Comment the following lines to deactivate the default embedded database.
    #sonar.jdbc.url: jdbc:derby://localhost:1527/sonar;create=true
    #sonar.jdbc.driverClassName: org.apache.derby.jdbc.ClientDriver
    #sonar.jdbc.validationQuery: values(1)
    
    ~~~~~~~~~~~~~~~省略部分~~~~~~~~~~~~~~~~~~
    
    #----- MySQL 5.x/6.x
    # Comment the embedded database and uncomment the following
    #properties to use MySQL. The validation query is optional.
    sonar.jdbc.url: 
    jdbc:mysql://localhost:3306/sonar?useUnicode=true&characterEncoding=utf8
    sonar.jdbc.driverClassName: com.mysql.jdbc.Driver
    #sonar.jdbc.validationQuery: select 1

  4. 重启 Sonar。

使用 Sonar 进行代码质量管理

为了不涉及代码的版权问题及方便读者试验,本节以开源项目 Mojo 为例,说明如何使用 Sonar 对源代码进行质量管理,在不涉及编译的情况下,本文尽量使用 Sonar 的 Nemo 演示功能。

首先,需要从 Mojo 首页上下载源代码(本文使用 TortoiseSVN 工具),如图所示,Mojo 项目包括了许多工程。

图 4. Mojo 工程文件夹

图 4. Mojo 工程文件夹

其中的每个工程都是一个 Maven 项目,如图所示:

图 5. Maven 工程文件

图 5. Maven 工程文件

编译命令如下:

mvn clean install

编译成功后,再使用如下命令:

mvn sonar:sonar

Maven 插件会自动把所需数据(如单元测试结果、静态检测结果等)上传到 Sonar 服务器上,需要说明的是,关于 Sonar 的配置并不在每个工程的 pom.xml 文件里,而是在 Maven 的配置文件 settings.xml 文件里,具体配置如下:

  <profile>
     <id>sonar</id>
     <activation>
         <activeByDefault>true</activeByDefault>
     </activation>
     <properties>
          <sonar.jdbc.url>
          jdbc:mysql://localhost:3306/sonar?useUnicode=true&characterEncoding=utf8
          </sonar.jdbc.url>
          <sonar.jdbc.driver>com.mysql.jdbc.Driver</sonar.jdbc.driver>
          <sonar.jdbc.username>sonar</sonar.jdbc.username>
          <sonar.jdbc.password>sonar</sonar.jdbc.password>
         <sonar.host.url>http://localhost:9000</sonar.host.url>
     </properties>
  </profile>

将 Soanr 所需要的数据上传到 Sonar 服务器上之后,Sonar 安装的插件会对这些数据进行分析和处理,并以各种方式显示给用户,从而使用户方便地对代码质量的监测和管理。

例如 Radiator 插件可以根据项目的规模进行排序,并用不同演示显示代码质量:

图 6. Radiator 插件的显示

图 6. Radiator 插件的显示

Sonar 插件的配置

前面已经提到,Sonar 的主要特色是对不同工具产生的检查结果进行再加工处理,Sonar 还向用户提供了对数据进行个性化处理的方法。

本节以 Technical Debt 插件为例说明如何通过设置参数影响最后的报告结果。首先了解一下这个插件中的“技术债务”的概念,这个概念最早是在 1992 年由 Ward Cunningham 在他的论文“The WyCash Portfolio Management System”中提出的,之后被软件工程界接受并推广,《重构》的作者 Martin Fowler 也在其 网站上对技术债务有所介绍。其实原理可以理解为“出来混早晚要还的”,当前不规范的代码,会对以后产品修改的成本造成影响。

Soanr 的 Technical Debt 插件提供了默认的计算公式,通过对其中的权重参数进行配置,可以适应不同公司和项目对技术债务的计算。

图 7. Technical Debt 计算公式

图 7. Technical Debt 计算公式

以上的各项数据指标,可以根据自己公司和项目的不同情况进行设置,如图所示:

图 8. Sonar 配置界面

图 8. Sonar 配置界面

例如默认参数下同一个项目的技术债务指标如下:

图 9. 默认参数下 Technical Debt 结果

图 9. 默认参数下 Technical Debt 结果

修改了参数后的结果为:

图 10. 配置参数后 Technical Debt 结果

图 10. 配置参数后 Technical Debt 结果

可见将 Average time to cover complexity of one (in hours) 从 0.2 修改为 0.01 后,Coverage 的权重变小了,从而达到忽略单元测试覆盖率的作用。不同的公司和项目可以根据需要调整各自的参数,参数的调优和策略不在本文的讨论范围之内。

通过以上的示例可以看出,Sonar 使用不同类型的图表显示给用户代码质量的结果,并且这些图表不是简单地对单元测试覆盖率或者静态检测工具的结果进行显示,而是根据软件工程理论进行了二次加工后的结果,更加科学和直观。

转自:http://www.ibm.com/developerworks/cn/java/j-lo-sonar/

 Posted by at 上午3:41
9月 032014
 

讲的很好,推荐 http://chenzhou123520.iteye.com/blog/1582166

一、聚合

为了能够使用一条命令就能构建 account-email account-persist两个模块,我们需要建立一个额外的名为 account-aggregator的模块,然后通过该模块构建整个项目的所有模块。 account-aggregator本身也是个 Maven项目,它的 POM如下
Xml代码  收藏代码

  1. <project>  
  2.     <modelVersion>4.0.0</modelVersion>  
  3.     <groupId>com.juvenxu.mvnbook.account</groupId>  
  4.     <artifactId>account-aggregator</artifactId>  
  5.     <version>1.0.0-SNAPSHOT</version>  
  6.     <packaging> pom </packaging>  
  7.     <name>Account Aggregator</name>  
  8.      <modules>  
  9.         <module>account-email</module>  
  10.         <module>account-persist</module>  
  11.      </modules>  
  12. </project>  

 注意:packaging的类型为pom module的值是一个以当前POM为主目录的相对路径。


二、继承

可声明父POM供子 POM继承

父模块POM如下:

 

Xml代码  收藏代码

  1. <project>  
  2.     <modelVersion>4.0.0</modelVersion>  
  3.     <groupId>com.juvenxu.mvnbook.account</groupId>  
  4.     <artifactId> account-parent </artifactId>  
  5.     <version>1.0.0-SNAPSHOT</version>  
  6.     <packaging>pom</packaging>  
  7.     <name>Account Parent</name>  
  8. </project>  

 子模块声明继承如下:

 

Xml代码  收藏代码

  1. <project>  
  2.     <modelVersion>4.0.0</modelVersion>  
  3.       
  4.     < parent >  
  5.         <groupId>com.juvenxu.mvnbook.account</groupId>  
  6.         <artifactId> account-parent </artifactId>  
  7.         <version>1.0.0-SNAPSHOT</version>  
  8.         < relativePath >../account-parent/pom.xml</ relativePath>  
  9.     </ parent >  
  10.       
  11.     <artifactId> account-email </artifactId>  
  12.     <name>Account Email</name>  
  13.   …  
  14. </project>  

 最后,同样还需要把 account-parent加入到聚合模块account-aggregator中。聚合的 POM如下:

 

Xml代码  收藏代码

  1. <project>  
  2.     <modelVersion>4.0.0</modelVersion>  
  3.     <groupId>com.juvenxu.mvnbook.account</groupId>  
  4.     <artifactId>account-aggregator</artifactId>  
  5.     <version>1.0.0-SNAPSHOT</version>  
  6.     <packaging> pom </packaging>  
  7.     <name>Account Aggregator</name>  
  8.     <modules>  
  9.         <module>account-email</module>  
  10.         <module>account-persist</module>  
  11.         <module> account-parent</module>  
  12.     </modules>  
  13. </project>  

 注意:

1、子模块没有声明groupIdversion, 这两个属性继承至父模块。但如果子模块有不同与父模块的 groupIdversion ,也可指定;

2、不应该继承artifactId,如果groupId versionartifactId 完全继承的话会造成坐标冲突;另外即使使用不同的 groupIdversion,同样的 artifactId也容易产生混淆。
3
、使用继承后 parent也必须像自模块一样加入到聚合模块中。也就是在在聚合模块的 pom中加入<module>account-parent</module>

 

三、聚合与继承的关系

区别 
1.对于聚合模块来说,它知道有哪些被聚合的模块,但那些被聚合的模块不知道这个聚合模块的存在。
2.对于继承关系的父 POM来说,它不知道有哪些子模块继承与它,但那些子模块都必须知道自己的父 POM是什么。

共同点 
1.聚合 POM与继承关系中的父POM packaging都是pom
2.聚合模块与继承关系中的父模块除了 POM之外都没有实际的内容。
Maven聚合关系与继承关系的比较
注:在现有的实际项目中一个 POM既是聚合POM,又是父 POM,这么做主要是为了方便
四、Maven可继承的POM 元素

Xml代码  收藏代码

  1. groupId :项目组 ID ,项目坐标的核心元素;  
  2. version :项目版本,项目坐标的核心元素;  
  3. description :项目的描述信息;  
  4. organization :项目的组织信息;  
  5. inceptionYear :项目的创始年份;  
  6. url :项目的 url 地址  
  7. develoers :项目的开发者信息;  
  8. contributors :项目的贡献者信息;  
  9. distributionManagerment :项目的部署信息;  
  10. issueManagement :缺陷跟踪系统信息;  
  11. ciManagement :项目的持续继承信息;  
  12. scm :项目的版本控制信息;  
  13. mailingListserv :项目的邮件列表信息;  
  14. properties :自定义的 Maven 属性;  
  15. dependencies :项目的依赖配置;  
  16. dependencyManagement :醒目的依赖管理配置;  
  17. repositories :项目的仓库配置;  
  18. build :包括项目的源码目录配置、输出目录配置、插件配置、插件管理配置等;  
  19. reporting :包括项目的报告输出目录配置、报告插件配置等。  

9月 032014
 

百度上看到的一篇文章,分享下http://wenku.baidu.com/view/7fa85631f111f18583d05a12.html

<project xmlns=”http://maven.apache.org/POM/4.0.0″   
    xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance”   
xsi:schemaLocation=”http://maven.apache.org/POM/4.0.0http://maven.apache.org/maven-v4_0_0.xsd”>   
    <!–父项目的坐标。如果项目中没有规定某个元素的值,那么父项目中的对应值即为项目的默认值。 坐标包括group ID,artifact ID和 version。–>  
    <parent>  
     <!–被继承的父项目的构件标识符–>  
     <artifactId/>  
     <!–被继承的父项目的全球唯一标识符–>  
     <groupId/>  
     <!–被继承的父项目的版本–>  
     <version/>  
     <!– 父项目的pom.xml文件的相对路径。相对路径允许你选择一个不同的路径。默认值是../pom.xml。Maven首先在构建当前项目的地方寻找父项 目的pom,其次在文件系统的这个位置(relativePath位置),然后在本地仓库,最后在远程仓库寻找父项目的pom。–>  
     <relativePath/>  
 </parent>  
 <!–声明项目描述符遵循哪一个POM模型版本。模型本身的版本很少改变,虽然如此,但它仍然是必不可少的,这是为了当Maven引入了新的特性或者其他模型变更的时候,确保稳定性。–>     
    <modelVersion>4.0.0</modelVersion>   
    <!–项目的全球唯一标识符,通常使用全限定的包名区分该项目和其他项目。并且构建时生成的路径也是由此生成, 如com.mycompany.app生成的相对路径为:/com/mycompany/app–>   
    <groupId>asia.banseon</groupId>   
    <!– 构件的标识符,它和group ID一起唯一标识一个构件。换句话说,你不能有两个不同的项目拥有同样的artifact ID和groupID;在某个 特定的group ID下,artifact ID也必须是唯一的。构件是项目产生的或使用的一个东西,Maven为项目产生的构件包括:JARs,源 码,二进制发布和WARs等。–>   
    <artifactId>banseon-maven2</artifactId>   
    <!–项目产生的构件类型,例如jar、war、ear、pom。插件可以创建他们自己的构件类型,所以前面列的不是全部构件类型–>   
    <packaging>jar</packaging>   
    <!–项目当前版本,格式为:主版本.次版本.增量版本-限定版本号–>   
    <version>1.0-SNAPSHOT</version>   
    <!–项目的名称, Maven产生的文档用–>   
    <name>banseon-maven</name>   
    <!–项目主页的URL, Maven产生的文档用–>   
    <url>http://www.baidu.com/banseon</url>   
    <!– 项目的详细描述, Maven 产生的文档用。  当这个元素能够用HTML格式描述时(例如,CDATA中的文本会被解析器忽略,就可以包含HTML标 签), 不鼓励使用纯文本描述。如果你需要修改产生的web站点的索引页面,你应该修改你自己的索引页文件,而不是调整这里的文档。–>   
    <description>A maven project to study maven.</description>   
    <!–描述了这个项目构建环境中的前提条件。–>  
 <prerequisites>  
  <!–构建该项目或使用该插件所需要的Maven的最低版本–>  
    <maven/>  
 </prerequisites>  
 <!–项目的问题管理系统(Bugzilla, Jira, Scarab,或任何你喜欢的问题管理系统)的名称和URL,本例为 jira–>   
    <issueManagement>  
     <!–问题管理系统(例如jira)的名字,–>   
        <system>jira</system>   
        <!–该项目使用的问题管理系统的URL–>  
        <url>http://jira.baidu.com/banseon</url>   
    </issueManagement>   
    <!–项目持续集成信息–>  
 <ciManagement>  
  <!–持续集成系统的名字,例如continuum–>  
  <system/>  
  <!–该项目使用的持续集成系统的URL(如果持续集成系统有web接口的话)。–>  
  <url/>  
  <!–构建完成时,需要通知的开发者/用户的配置项。包括被通知者信息和通知条件(错误,失败,成功,警告)–>  
  <notifiers>  
   <!–配置一种方式,当构建中断时,以该方式通知用户/开发者–>  
   <notifier>  
    <!–传送通知的途径–>  
    <type/>  
    <!–发生错误时是否通知–>  
    <sendOnError/>  
    <!–构建失败时是否通知–>  
    <sendOnFailure/>  
    <!–构建成功时是否通知–>  
    <sendOnSuccess/>  
    <!–发生警告时是否通知–>  
    <sendOnWarning/>  
    <!–不赞成使用。通知发送到哪里–>  
    <address/>  
    <!–扩展配置项–>  
    <configuration/>  
   </notifier>  
  </notifiers>  
 </ciManagement>  
 <!–项目创建年份,4位数字。当产生版权信息时需要使用这个值。–>  
    <inceptionYear/>  
    <!–项目相关邮件列表信息–>   
    <mailingLists>  
     <!–该元素描述了项目相关的所有邮件列表。自动产生的网站引用这些信息。–>   
        <mailingList>   
         <!–邮件的名称–>  
            <name>Demo</name>   
            <!–发送邮件的地址或链接,如果是邮件地址,创建文档时,mailto: 链接会被自动创建–>   
            <post>[email protected]</post>   
            <!–订阅邮件的地址或链接,如果是邮件地址,创建文档时,mailto: 链接会被自动创建–>   
            <subscribe>[email protected]</subscribe>   
            <!–取消订阅邮件的地址或链接,如果是邮件地址,创建文档时,mailto: 链接会被自动创建–>   
            <unsubscribe>[email protected]</unsubscribe>   
            <!–你可以浏览邮件信息的URL–>  
            <archive>http:/hi.baidu.com/banseon/demo/dev/</archive>   
        </mailingList>   
    </mailingLists>   
    <!–项目开发者列表–>   
    <developers>   
     <!–某个项目开发者的信息–>  
        <developer>   
         <!–SCM里项目开发者的唯一标识符–>  
            <id>HELLO WORLD</id>   
            <!–项目开发者的全名–>  
            <name>banseon</name>   
            <!–项目开发者的email–>  
            <email>[email protected]</email>   
            <!–项目开发者的主页的URL–>  
            <url/>  
            <!–项目开发者在项目中扮演的角色,角色元素描述了各种角色–>  
            <roles>   
                <role>Project Manager</role>   
                <role>Architect</role>   
            </roles>  
            <!–项目开发者所属组织–>  
            <organization>demo</organization>   
            <!–项目开发者所属组织的URL–>  
            <organizationUrl>http://hi.baidu.com/banseon</organizationUrl>   
            <!–项目开发者属性,如即时消息如何处理等–>  
            <properties>   
                <dept>No</dept>   
            </properties>  
            <!–项目开发者所在时区, -11到12范围内的整数。–>  
            <timezone>-5</timezone>   
        </developer>   
    </developers>   
    <!–项目的其他贡献者列表–>   
    <contributors>  
     <!–项目的其他贡献者。参见developers/developer元素–>  
     <contributor>  
   <name/><email/><url/><organization/><organizationUrl/><roles/><timezone/><properties/>  
     </contributor>       
    </contributors>     
    <!–该元素描述了项目所有License列表。 应该只列出该项目的license列表,不要列出依赖项目的 license列表。如果列出多个license,用户可以选择它们中的一个而不是接受所有license。–>   
    <licenses>  
     <!–描述了项目的license,用于生成项目的web站点的license页面,其他一些报表和validation也会用到该元素。–>   
        <license>  
         <!–license用于法律上的名称–>  
            <name>Apache 2</name>   
            <!–官方的license正文页面的URL–>  
            <url>http://www.baidu.com/banseon/LICENSE-2.0.txt</url>   
            <!–项目分发的主要方式:  
              repo,可以从Maven库下载  
              manual, 用户必须手动下载和安装依赖–>  
            <distribution>repo</distribution>   
            <!–关于license的补充信息–>  
            <comments>A business-friendly OSS license</comments>   
        </license>   
    </licenses>   
    <!–SCM(Source Control Management)标签允许你配置你的代码库,供Maven web站点和其它插件使用。–>   
    <scm>   
        <!–SCM的URL,该URL描述了版本库和如何连接到版本库。欲知详情,请看SCMs提供的URL格式和列表。该连接只读。–>   
        <connection>   
            scm:svn:http://svn.baidu.com/banseon/maven/banseon/banseon-maven2-trunk(dao-trunk)    
        </connection>   
        <!–给开发者使用的,类似connection元素。即该连接不仅仅只读–>  
        <developerConnection>   
            scm:svn:http://svn.baidu.com/banseon/maven/banseon/dao-trunk    
        </developerConnection>  
        <!–当前代码的标签,在开发阶段默认为HEAD–>  
        <tag/>         
        <!–指向项目的可浏览SCM库(例如ViewVC或者Fisheye)的URL。–>   
        <url>http://svn.baidu.com/banseon</url>   
    </scm>   
    <!–描述项目所属组织的各种属性。Maven产生的文档用–>   
    <organization>   
     <!–组织的全名–>  
        <name>demo</name>   
        <!–组织主页的URL–>  
        <url>http://www.baidu.com/banseon</url>   
    </organization>  
    <!–构建项目需要的信息–>  
    <build>  
     <!–该元素设置了项目源码目录,当构建项目的时候,构建系统会编译目录里的源码。该路径是相对于pom.xml的相对路径。–>  
  <sourceDirectory/>  
  <!–该元素设置了项目脚本源码目录,该目录和源码目录不同:绝大多数情况下,该目录下的内容 会被拷贝到输出目录(因为脚本是被解释的,而不是被编译的)。–>  
  <scriptSourceDirectory/>  
  <!–该元素设置了项目单元测试使用的源码目录,当测试项目的时候,构建系统会编译目录里的源码。该路径是相对于pom.xml的相对路径。–>  
  <testSourceDirectory/>  
  <!–被编译过的应用程序class文件存放的目录。–>  
  <outputDirectory/>  
  <!–被编译过的测试class文件存放的目录。–>  
  <testOutputDirectory/>  
  <!–使用来自该项目的一系列构建扩展–>  
  <extensions>  
   <!–描述使用到的构建扩展。–>  
   <extension>  
    <!–构建扩展的groupId–>  
    <groupId/>  
    <!–构建扩展的artifactId–>  
    <artifactId/>  
    <!–构建扩展的版本–>  
    <version/>  
   </extension>  
  </extensions>  
  <!–当项目没有规定目标(Maven2 叫做阶段)时的默认值–>  
  <defaultGoal/>  
  <!–这个元素描述了项目相关的所有资源路径列表,例如和项目相关的属性文件,这些资源被包含在最终的打包文件里。–>  
  <resources>  
   <!–这个元素描述了项目相关或测试相关的所有资源路径–>  
   <resource>  
    <!– 描述了资源的目标路径。该路径相对target/classes目录(例如${project.build.outputDirectory})。举个例 子,如果你想资源在特定的包里(org.apache.maven.messages),你就必须该元素设置为org/apache/maven /messages。然而,如果你只是想把资源放到源码目录结构里,就不需要该配置。–>  
    <targetPath/>  
    <!–是否使用参数值代替参数名。参数值取自properties元素或者文件里配置的属性,文件在filters元素里列出。–>  
    <filtering/>  
    <!–描述存放资源的目录,该路径相对POM路径–>  
    <directory/>  
    <!–包含的模式列表,例如**/*.xml.–>  
    <includes/>  
    <!–排除的模式列表,例如**/*.xml–>  
    <excludes/>  
   </resource>  
  </resources>  
  <!–这个元素描述了单元测试相关的所有资源路径,例如和单元测试相关的属性文件。–>  
  <testResources>  
   <!–这个元素描述了测试相关的所有资源路径,参见build/resources/resource元素的说明–>  
   <testResource>  
    <targetPath/><filtering/><directory/><includes/><excludes/>  
   </testResource>  
  </testResources>  
  <!–构建产生的所有文件存放的目录–>  
  <directory/>  
  <!–产生的构件的文件名,默认值是${artifactId}-${version}。–>  
  <finalName/>  
  <!–当filtering开关打开时,使用到的过滤器属性文件列表–>  
  <filters/>  
  <!–子项目可以引用的默认插件信息。该插件配置项直到被引用时才会被解析或绑定到生命周期。给定插件的任何本地配置都会覆盖这里的配置–>  
  <pluginManagement>  
   <!–使用的插件列表 。–>  
   <plugins>  
    <!–plugin元素包含描述插件所需要的信息。–>  
    <plugin>  
     <!–插件在仓库里的group ID–>  
     <groupId/>  
     <!–插件在仓库里的artifact ID–>  
     <artifactId/>  
     <!–被使用的插件的版本(或版本范围)–>  
     <version/>  
     <!–是否从该插件下载Maven扩展(例如打包和类型处理器),由于性能原因,只有在真需要下载时,该元素才被设置成enabled。–>  
     <extensions/>  
     <!–在构建生命周期中执行一组目标的配置。每个目标可能有不同的配置。–>  
     <executions>  
      <!–execution元素包含了插件执行需要的信息–>  
      <execution>  
       <!–执行目标的标识符,用于标识构建过程中的目标,或者匹配继承过程中需要合并的执行目标–>  
       <id/>  
       <!–绑定了目标的构建生命周期阶段,如果省略,目标会被绑定到源数据里配置的默认阶段–>  
       <phase/>  
       <!–配置的执行目标–>  
       <goals/>  
       <!–配置是否被传播到子POM–>  
       <inherited/>  
       <!–作为DOM对象的配置–>  
       <configuration/>  
      </execution>  
     </executions>  
     <!–项目引入插件所需要的额外依赖–>  
     <dependencies>  
      <!–参见dependencies/dependency元素–>  
      <dependency>  
       ……  
      </dependency>  
     </dependencies>       
     <!–任何配置是否被传播到子项目–>  
     <inherited/>  
     <!–作为DOM对象的配置–>  
     <configuration/>  
    </plugin>  
   </plugins>  
  </pluginManagement>  
  <!–使用的插件列表–>  
  <plugins>  
   <!–参见build/pluginManagement/plugins/plugin元素–>  
   <plugin>  
    <groupId/><artifactId/><version/><extensions/>  
    <executions>  
     <execution>  
      <id/><phase/><goals/><inherited/><configuration/>  
     </execution>  
    </executions>  
    <dependencies>  
     <!–参见dependencies/dependency元素–>  
     <dependency>  
      ……  
     </dependency>  
    </dependencies>  
    <goals/><inherited/><configuration/>  
   </plugin>  
  </plugins>  
 </build>  
 <!–在列的项目构建profile,如果被激活,会修改构建处理–>  
 <profiles>  
  <!–根据环境参数或命令行参数激活某个构建处理–>  
  <profile>  
   <!–构建配置的唯一标识符。即用于命令行激活,也用于在继承时合并具有相同标识符的profile。–>  
   <id/>  
   <!–自动触发profile的条件逻辑。Activation是profile的开启钥匙。profile的力量来自于它  
   能够在某些特定的环境中自动使用某些特定的值;这些环境通过activation元素指定。activation元素并不是激活profile的唯一方式。–>  
   <activation>  
    <!–profile默认是否激活的标志–>  
    <activeByDefault/>  
    <!–当匹配的jdk被检测到,profile被激活。例如,1.4激活JDK1.4,1.4.0_2,而!1.4激活所有版本不是以1.4开头的JDK。–>  
    <jdk/>  
    <!–当匹配的操作系统属性被检测到,profile被激活。os元素可以定义一些操作系统相关的属性。–>  
    <os>  
     <!–激活profile的操作系统的名字–>  
     <name>Windows XP</name>  
     <!–激活profile的操作系统所属家族(如 ‘windows’)–>  
     <family>Windows</family>  
     <!–激活profile的操作系统体系结构 –>  
     <arch>x86</arch>  
     <!–激活profile的操作系统版本–>  
     <version>5.1.2600</version>  
    </os>  
    <!–如果Maven检测到某一个属性(其值可以在POM中通过${名称}引用),其拥有对应的名称和值,Profile就会被激活。如果值  
    字段是空的,那么存在属性名称字段就会激活profile,否则按区分大小写方式匹配属性值字段–>  
    <property>  
     <!–激活profile的属性的名称–>  
     <name>mavenVersion</name>  
     <!–激活profile的属性的值–>  
     <value>2.0.3</value>  
    </property>  
    <!–提供一个文件名,通过检测该文件的存在或不存在来激活profile。missing检查文件是否存在,如果不存在则激活  
    profile。另一方面,exists则会检查文件是否存在,如果存在则激活profile。–>  
    <file>  
     <!–如果指定的文件存在,则激活profile。–>  
     <exists>/usr/local/hudson/hudson-home/jobs/maven-guide-zh-to-production/workspace/</exists>  
     <!–如果指定的文件不存在,则激活profile。–>  
     <missing>/usr/local/hudson/hudson-home/jobs/maven-guide-zh-to-production/workspace/</missing>  
    </file>  
   </activation>  
   <!–构建项目所需要的信息。参见build元素–>  
   <build>  
    <defaultGoal/>  
    <resources>  
     <resource>  
      <targetPath/><filtering/><directory/><includes/><excludes/>  
     </resource>  
    </resources>  
    <testResources>  
     <testResource>  
      <targetPath/><filtering/><directory/><includes/><excludes/>  
     </testResource>  
    </testResources>  
    <directory/><finalName/><filters/>  
    <pluginManagement>  
     <plugins>  
      <!–参见build/pluginManagement/plugins/plugin元素–>  
      <plugin>  
       <groupId/><artifactId/><version/><extensions/>  
       <executions>  
        <execution>  
         <id/><phase/><goals/><inherited/><configuration/>  
        </execution>  
       </executions>  
       <dependencies>  
        <!–参见dependencies/dependency元素–>  
        <dependency>  
         ……  
        </dependency>  
       </dependencies>  
       <goals/><inherited/><configuration/>  
      </plugin>  
     </plugins>  
    </pluginManagement>  
    <plugins>  
     <!–参见build/pluginManagement/plugins/plugin元素–>  
     <plugin>  
      <groupId/><artifactId/><version/><extensions/>  
      <executions>  
       <execution>  
        <id/><phase/><goals/><inherited/><configuration/>  
       </execution>  
      </executions>  
      <dependencies>  
       <!–参见dependencies/dependency元素–>  
       <dependency>  
        ……  
       </dependency>  
      </dependencies>  
      <goals/><inherited/><configuration/>  
     </plugin>  
    </plugins>  
   </build>  
   <!–模块(有时称作子项目) 被构建成项目的一部分。列出的每个模块元素是指向该模块的目录的相对路径–>  
   <modules/>  
   <!–发现依赖和扩展的远程仓库列表。–>  
   <repositories>  
    <!–参见repositories/repository元素–>  
    <repository>  
     <releases>  
      <enabled/><updatePolicy/><checksumPolicy/>  
     </releases>  
     <snapshots>  
      <enabled/><updatePolicy/><checksumPolicy/>  
     </snapshots>  
     <id/><name/><url/><layout/>  
    </repository>  
   </repositories>  
   <!–发现插件的远程仓库列表,这些插件用于构建和报表–>  
   <pluginRepositories>  
    <!–包含需要连接到远程插件仓库的信息.参见repositories/repository元素–>      
    <pluginRepository>  
     <releases>  
      <enabled/><updatePolicy/><checksumPolicy/>  
     </releases>  
     <snapshots>  
      <enabled/><updatePolicy/><checksumPolicy/>  
     </snapshots>  
     <id/><name/><url/><layout/>  
    </pluginRepository>  
   </pluginRepositories>  
   <!–该元素描述了项目相关的所有依赖。 这些依赖组成了项目构建过程中的一个个环节。它们自动从项目定义的仓库中下载。要获取更多信息,请看项目依赖机制。–>  
   <dependencies>  
    <!–参见dependencies/dependency元素–>  
    <dependency>  
     ……  
    </dependency>  
   </dependencies>  
   <!–不赞成使用. 现在Maven忽略该元素.–>  
   <reports/>     
   <!–该元素包括使用报表插件产生报表的规范。当用户执行“mvn site”,这些报表就会运行。 在页面导航栏能看到所有报表的链接。参见reporting元素–>  
   <reporting>  
    ……  
   </reporting>  
   <!–参见dependencyManagement元素–>  
   <dependencyManagement>  
    <dependencies>  
     <!–参见dependencies/dependency元素–>  
     <dependency>  
      ……  
     </dependency>  
    </dependencies>  
   </dependencyManagement>  
   <!–参见distributionManagement元素–>  
   <distributionManagement>  
    ……  
   </distributionManagement>  
   <!–参见properties元素–>  
   <properties/>  
  </profile>  
 </profiles>  
 <!–模块(有时称作子项目) 被构建成项目的一部分。列出的每个模块元素是指向该模块的目录的相对路径–>  
 <modules/>  
    <!–发现依赖和扩展的远程仓库列表。–>   
    <repositories>   
     <!–包含需要连接到远程仓库的信息–>  
        <repository>  
         <!–如何处理远程仓库里发布版本的下载–>  
         <releases>  
          <!–true或者false表示该仓库是否为下载某种类型构件(发布版,快照版)开启。 –>  
    <enabled/>  
    <!–该元素指定更新发生的频率。Maven会比较本地POM和远程POM的时间戳。这里的选项是:always(一直),daily(默认,每日),interval:X(这里X是以分钟为单位的时间间隔),或者never(从不)。–>  
    <updatePolicy/>  
    <!–当Maven验证构件校验文件失败时该怎么做:ignore(忽略),fail(失败),或者warn(警告)。–>  
    <checksumPolicy/>  
   </releases>  
   <!– 如何处理远程仓库里快照版本的下载。有了releases和snapshots这两组配置,POM就可以在每个单独的仓库中,为每种类型的构件采取不同的 策略。例如,可能有人会决定只为开发目的开启对快照版本下载的支持。参见repositories/repository/releases元素 –>  
   <snapshots>  
    <enabled/><updatePolicy/><checksumPolicy/>  
   </snapshots>  
   <!–远程仓库唯一标识符。可以用来匹配在settings.xml文件里配置的远程仓库–>  
   <id>banseon-repository-proxy</id>   
   <!–远程仓库名称–>  
            <name>banseon-repository-proxy</name>   
            <!–远程仓库URL,按protocol://hostname/path形式–>  
            <url>http://192.168.1.169:9999/repository/</url>   
            <!– 用于定位和排序构件的仓库布局类型-可以是default(默认)或者legacy(遗留)。Maven 2为其仓库提供了一个默认的布局;然 而,Maven 1.x有一种不同的布局。我们可以使用该元素指定布局是default(默认)还是legacy(遗留)。–>  
            <layout>default</layout>             
        </repository>   
    </repositories>  
    <!–发现插件的远程仓库列表,这些插件用于构建和报表–>  
    <pluginRepositories>  
     <!–包含需要连接到远程插件仓库的信息.参见repositories/repository元素–>  
  <pluginRepository>  
   ……  
  </pluginRepository>  
 </pluginRepositories>  
     
    <!–该元素描述了项目相关的所有依赖。 这些依赖组成了项目构建过程中的一个个环节。它们自动从项目定义的仓库中下载。要获取更多信息,请看项目依赖机制。–>   
    <dependencies>   
        <dependency>  
   <!–依赖的group ID–>  
            <groupId>org.apache.maven</groupId>   
            <!–依赖的artifact ID–>  
            <artifactId>maven-artifact</artifactId>   
            <!–依赖的版本号。 在Maven 2里, 也可以配置成版本号的范围。–>  
            <version>3.8.1</version>   
            <!– 依赖类型,默认类型是jar。它通常表示依赖的文件的扩展名,但也有例外。一个类型可以被映射成另外一个扩展名或分类器。类型经常和使用的打包方式对应, 尽管这也有例外。一些类型的例子:jar,war,ejb-client和test-jar。如果设置extensions为 true,就可以在 plugin里定义新的类型。所以前面的类型的例子不完整。–>  
            <type>jar</type>  
            <!– 依赖的分类器。分类器可以区分属于同一个POM,但不同构建方式的构件。分类器名被附加到文件名的版本号后面。例如,如果你想要构建两个单独的构件成 JAR,一个使用Java 1.4编译器,另一个使用Java 6编译器,你就可以使用分类器来生成两个单独的JAR构件。–>  
            <classifier></classifier>  
            <!–依赖范围。在项目发布过程中,帮助决定哪些构件被包括进来。欲知详情请参考依赖机制。  
                – compile :默认范围,用于编译    
                – provided:类似于编译,但支持你期待jdk或者容器提供,类似于classpath    
                – runtime: 在执行时需要使用    
                – test:    用于test任务时使用    
                – system: 需要外在提供相应的元素。通过systemPath来取得    
                – systemPath: 仅用于范围为system。提供相应的路径    
                – optional:   当项目自身被依赖时,标注依赖是否传递。用于连续依赖时使用–>   
            <scope>test</scope>     
            <!–仅供system范围使用。注意,不鼓励使用这个元素,并且在新的版本中该元素可能被覆盖掉。该元素为依赖规定了文件系统上的路径。需要绝对路径而不是相对路径。推荐使用属性匹配绝对路径,例如${java.home}。–>  
            <systemPath></systemPath>   
            <!–当计算传递依赖时, 从依赖构件列表里,列出被排除的依赖构件集。即告诉maven你只依赖指定的项目,不依赖项目的依赖。此元素主要用于解决版本冲突问题–>  
            <exclusions>  
             <exclusion>   
                    <artifactId>spring-core</artifactId>   
                    <groupId>org.springframework</groupId>   
                </exclusion>   
            </exclusions>     
            <!–可选依赖,如果你在项目B中把C依赖声明为可选,你就需要在依赖于B的项目(例如项目A)中显式的引用对C的依赖。可选依赖阻断依赖的传递性。–>   
            <optional>true</optional>  
        </dependency>  
    </dependencies>  
    <!–不赞成使用. 现在Maven忽略该元素.–>  
    <reports></reports>  
    <!–该元素描述使用报表插件产生报表的规范。当用户执行“mvn site”,这些报表就会运行。 在页面导航栏能看到所有报表的链接。–>  
 <reporting>  
  <!–true,则,网站不包括默认的报表。这包括“项目信息”菜单中的报表。–>  
  <excludeDefaults/>  
  <!–所有产生的报表存放到哪里。默认值是${project.build.directory}/site。–>  
  <outputDirectory/>  
  <!–使用的报表插件和他们的配置。–>  
  <plugins>  
   <!–plugin元素包含描述报表插件需要的信息–>  
   <plugin>  
    <!–报表插件在仓库里的group ID–>  
    <groupId/>  
    <!–报表插件在仓库里的artifact ID–>  
    <artifactId/>  
    <!–被使用的报表插件的版本(或版本范围)–>  
    <version/>  
    <!–任何配置是否被传播到子项目–>  
    <inherited/>  
    <!–报表插件的配置–>  
    <configuration/>  
    <!–一组报表的多重规范,每个规范可能有不同的配置。一个规范(报表集)对应一个执行目标 。例如,有1,2,3,4,5,6,7,8,9个报表。1,2,5构成A报表集,对应一个执行目标。2,5,8构成B报表集,对应另一个执行目标–>  
    <reportSets>  
     <!–表示报表的一个集合,以及产生该集合的配置–>  
     <reportSet>  
      <!–报表集合的唯一标识符,POM继承时用到–>  
      <id/>  
      <!–产生报表集合时,被使用的报表的配置–>  
      <configuration/>  
      <!–配置是否被继承到子POMs–>  
      <inherited/>  
      <!–这个集合里使用到哪些报表–>  
      <reports/>  
     </reportSet>  
    </reportSets>  
   </plugin>  
  </plugins>  
 </reporting>  
 <!– 继承自该项目的所有子项目的默认依赖信息。这部分的依赖信息不会被立即解析,而是当子项目声明一个依赖(必须描述group ID和 artifact ID信息),如果group ID和artifact ID以外的一些信息没有描述,则通过group ID和artifact ID 匹配到这里的依赖,并使用这里的依赖信息。–>  
 <dependencyManagement>  
  <dependencies>  
   <!–参见dependencies/dependency元素–>  
   <dependency>  
    ……  
   </dependency>  
  </dependencies>  
 </dependencyManagement>     
    <!–项目分发信息,在执行mvn deploy后表示要发布的位置。有了这些信息就可以把网站部署到远程服务器或者把构件部署到远程仓库。–>   
    <distributionManagement>  
        <!–部署项目产生的构件到远程仓库需要的信息–>  
        <repository>  
         <!–是分配给快照一个唯一的版本号(由时间戳和构建流水号)?还是每次都使用相同的版本号?参见repositories/repository元素–>  
   <uniqueVersion/>  
   <id>banseon-maven2</id>   
   <name>banseon maven2</name>   
            <url>file://${basedir}/target/deploy</url>   
            <layout/>  
  </repository>  
  <!–构件的快照部署到哪里?如果没有配置该元素,默认部署到repository元素配置的仓库,参见distributionManagement/repository元素–>   
  <snapshotRepository>  
   <uniqueVersion/>  
   <id>banseon-maven2</id>  
            <name>Banseon-maven2 Snapshot Repository</name>  
            <url>scp://svn.baidu.com/banseon:/usr/local/maven-snapshot</url>   
   <layout/>  
  </snapshotRepository>  
  <!–部署项目的网站需要的信息–>   
        <site>  
         <!–部署位置的唯一标识符,用来匹配站点和settings.xml文件里的配置–>   
            <id>banseon-site</id>   
            <!–部署位置的名称–>  
            <name>business api website</name>   
            <!–部署位置的URL,按protocol://hostname/path形式–>  
            <url>   
                scp://svn.baidu.com/banseon:/var/www/localhost/banseon-web    
            </url>   
        </site>  
  <!–项目下载页面的URL。如果没有该元素,用户应该参考主页。使用该元素的原因是:帮助定位那些不在仓库里的构件(由于license限制)。–>  
  <downloadUrl/>  
  <!–如果构件有了新的group ID和artifact ID(构件移到了新的位置),这里列出构件的重定位信息。–>  
  <relocation>  
   <!–构件新的group ID–>  
   <groupId/>  
   <!–构件新的artifact ID–>  
   <artifactId/>  
   <!–构件新的版本号–>  
   <version/>  
   <!–显示给用户的,关于移动的额外信息,例如原因。–>  
   <message/>  
  </relocation>  
  <!– 给出该构件在远程仓库的状态。不得在本地项目中设置该元素,因为这是工具自动更新的。有效的值有:none(默认),converted(仓库管理员从 Maven 1 POM转换过来),partner(直接从伙伴Maven 2仓库同步过来),deployed(从Maven 2实例部 署),verified(被核实时正确的和最终的)。–>  
  <status/>         
    </distributionManagement>  
    <!–以值替代名称,Properties可以在整个POM中使用,也可以作为触发条件(见settings.xml配置文件里activation元素的说明)。格式是<name>value</name>。–>  
    <properties/>  
</project>  
  
<!–参考文献:  
 http://maven.apache.org/ref/2.0.9/maven-model/maven.html  
–> 

 Posted by at 下午3:04  Tagged with:
5月 212014
 

关于maven的文章,特别对于打包可执行jar文件对我很有帮助。

Maven 是为 Java™ 开发人员提供的一个极为优秀的构建工具,您也可以使用它来管理您的项目生命周期。作为一个生命周期管理工具,Maven 是基于阶段操作的,而不像 Ant 是基于 “任务” 构建的。Maven 完成项目生命周期的所有阶段,包括验证、代码生成、编译、测试、打包、集成测试、安装、部署、以及项目网站创建和部署。

为了更好地理解 Maven 和传统构建工具的不同,我们来看看构建一个 JAR 文件和一个 EAR 文件的过程。使用 Ant,您可能需要定义专有任务来组装每个工件。另一方面,Maven 可以为您完成大部分工作:您只需要告诉它是一个 JAR 文件还是一个 EAR 文件,然后指示它来完成 “打包” 过程。Maven 将会找到所需的资源,然后构建文件。

在本文的 参考资料 部分,您将发现大量介绍 Maven 的入门教程。本文的 5 个技巧目的是帮助您解决即将出现的一些问题:使用 Maven 管理您的应用程序的生命周期时,将会出现的编程场景。

1. 可执行的 JAR 文件

使用 Maven 构建一个 JAR 文件比较容易:只要定义项目包装为 “jar”,然后执行包装生命周期阶段即可。但是定义一个可执行 JAR 文件却比较麻烦。采取以下步骤可以更高效:

  1. 在您定义可执行类的 JAR 的 MANIFEST.MF 文件中定义一个 main 类。(MANIFEST.MF 是包装您的应用程序时 Maven 生成的。)
  2. 找到您项目依赖的所有库。
  3. 在您的 MANIFEST.MF 文件中包含那些库,便于您的应用程序找到它们。

您可以手工进行这些操作,或者要想更高效,您可以使用两个 Maven 插件帮助您完成:maven-jar-plugin 和 maven-dependency-plugin。

maven-jar-plugin

maven-jar-plugin 可以做很多事情,但在这里,我们只对使用它来修改默认 MANIFEST.MF 文件的内容感兴趣。在您的 POM 文件的插件部分添加清单 1 所示代码:

清单 1. 使用 maven-jar-plugin 修改 MANIFEST.MF
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-jar-plugin</artifactId>
                <configuration>
                    <archive>
                        <manifest>
                            <addClasspath>true</addClasspath>
                            <classpathPrefix>lib/</classpathPrefix>
                            <mainClass>com.mypackage.MyClass</mainClass>
                        </manifest>
                    </archive>
                </configuration>
            </plugin>

所有 Maven 插件通过一个 <configuration> 元素公布了其配置,在本例中,maven-jar-plugin 修改它的 archive 属性,特别是存档文件的 manifest 属性,它控制 MANIFEST.MF 文件的内容。包括 3 个元素:

  • addClassPath:将该元素设置为 true 告知 maven-jar-plugin 添加一个 Class-Path 元素到 MANIFEST.MF 文件,以及在 Class-Path 元素中包括所有依赖项。
  • classpathPrefix:如果您计划在同一目录下包含有您的所有依赖项,作为您将构建的 JAR,那么您可以忽略它;否则使用classpathPrefix 来指定所有依赖 JAR 文件的前缀。在清单 1 中,classpathPrefix 指出,相对存档文件,所有的依赖项应该位于 “lib” 文件夹。
  • mainClass:当用户使用 lib 命令执行 JAR 文件时,使用该元素定义将要执行的类名。

maven-dependency-plugin

当您使用这 3 个元素配置好了 MANIFEST.MF 文件之后,下一步是将所有的依赖项复制到 lib 文件夹。为此,使用 maven-dependency-plugin,如清单 2 所示:

清单 2. 使用 maven-dependency-plugin 将依赖项复制到库
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-dependency-plugin</artifactId>
                <executions>
                    <execution>
                        <id>copy</id>
                        <phase>install</phase>
                        <goals>
                            <goal>copy-dependencies</goal>
                        </goals>
                        <configuration>
                            <outputDirectory>
                              ${project.build.directory}/lib
                            </outputDirectory>
                        </configuration>
                    </execution>
                </executions>
            </plugin>

maven-dependency-plugin 有一个 copy-dependencies,目标是将您的依赖项复制到您所选择的目录。本例中,我将依赖项复制到build 目录下的 lib 目录(project-home/target/lib)。

将您的依赖项和修改的 MANIFEST.MF 放在适当的位置后,您就可以用一个简单的命令启动应用程序:

java -jar jarfilename.jar

2. 定制 MANIFEST.MF

虽然 maven-jar-plugin 允许您修改 MANIFEST.MF 文件的共有部分,但有时候您需要一个更个性化的 MANIFEST.MF。解决方案是双重的:

  1. 在一个 “模板” MANIFEST.MF 文件中定义您的所有定制配置。
  2. 配置 maven-jar-plugin 来使用您的 MANIFEST.MF 文件,然后使用一些 Maven 配置增强。

例如,考虑一个包含 Java 代理的 JAR 文件。要运行一个 Java 代理,需要定义 Premain-Class 和设置许可。清单 3 展示了这样一个 MANIFEST.MF 文件的内容:

清单 3. 在一个定制的 MANIFEST.MF 文件中定义 Premain-Class
Manifest-Version: 1.0
Premain-Class: com.geekcap.openapm.jvm.agent.Agent
Can-Redefine-Classes: true
Can-Retransform-Classes: true
Can-Set-Native-Method-Prefix: true

在 清单 3 中,我已指定 Premain-Class – com.geekcap.openapm.jvm.agent.Agent 被授权许可来对类进行重定义和再转换。接下来,我更新 maven-jar-plugin 代码来包含 MANIFEST.MF 文件。如清单 4 所示:

清单 4. 包含 Premain-Class
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-jar-plugin</artifactId>
                <configuration>
                    <archive>
                        <manifestFile>
                          src/main/resources/META-INF/MANIFEST.MF
                        </manifestFile>
                        <manifest>
                            <addClasspath>true</addClasspath>
                            <classpathPrefix>lib/</classpathPrefix>
                            <mainClass>
                              com.geekcap.openapm.ui.PerformanceAnalyzer
                            </mainClass>
                        </manifest>
                    </archive>
                </configuration>
            </plugin>

Maven 3

Maven 2 已确立了它作为一种最流行和最易使用的开源 Java 生命周期管理工具的地位。Maven 3,2010 年 9 月升级为 alpha 5,带来一些期待已久的改进。在 参考资料部分寻找 Maven 的新功能。

这是一个很有趣的示例,因为它既定义了一个 Premain-Class — 允许 JAR 文件作为一个 Java 代理运行,也有一个 mainClass — 允许它作为一个可执行的 JAR 文件运行。在这个特殊的例子中,我使用 OpenAPM(我已构建的一个代码跟踪工具)来定义将被 Java 代理和一个用户界面记录的代码跟踪。简而言之,这个示例展示一个显式清单文件与动态修改相结合的力量。

3. 依赖项树

Maven 一个最有用的功能是它支持依赖项管理:您只需要定义您应用程序依赖的库,Maven 找到它们、下载它们、然后使用它们编译您的代码。

必要时,您需要知道具体依赖项的来源 — 这样您就可以找到同一个 JAR 文件的不同版本的区别和矛盾。这种情况下,您将需要防止将一个版本的 JAR 文件包含在您的构建中,但是首先您需要定位保存 JAR 的依赖项。

一旦您知道下列命令,那么定位依赖项往往是相当容易的:

mvn dependency:tree

dependency:tree 参数显示您的所有直接依赖项,然后显示所有子依赖项(以及它们的子依赖项,等等)。例如,清单 5 节选自我的一个依赖项所需要的客户端库:

清单 5. Maven 依赖项树
[INFO] ------------------------------------------------------------------------
[INFO] Building Client library for communicating with the LDE
[INFO]    task-segment: [dependency:tree]
[INFO] ------------------------------------------------------------------------
[INFO] [dependency:tree {execution: default-cli}]
[INFO] com.lmt.pos:sis-client:jar:2.1.14
[INFO] +- org.codehaus.woodstox:woodstox-core-lgpl:jar:4.0.7:compile
[INFO] |  - org.codehaus.woodstox:stax2-api:jar:3.0.1:compile
[INFO] +- org.easymock:easymockclassextension:jar:2.5.2:test
[INFO] |  +- cglib:cglib-nodep:jar:2.2:test
[INFO] |  - org.objenesis:objenesis:jar:1.2:test

在 清单 5 中您可以看到 sis-client 项目需要 woodstox-core-lgpl 和 easymockclassextension 库。easymockclassextension库反过来需要 cglib-nodep 库和 objenesis 库。如果我的 objenesis 出了问题,比如出现两个版本,1.2 和 1.3,那么这个依赖项树可能会向我显示,1.2 工件是直接由 easymockclassextension 库导入的。

dependency:tree 参数为我节省了很多调试时间,我希望对您也同样有帮助。

4. 使用配置文件

多数重大项目至少有一个核心环境,由开发相关的任务、质量保证(QA)、集成和生产组成。管理所有这些环境的挑战是配置您的构建,这必须连接到正确的数据库中,执行正确的脚本集、并为每个环境部署正确的工件。使用 Maven 配置文件让您完成这些任务,而无需为每个环境分别建立明确指令。

关键在于环境配置文件和面向任务的配置文件的合并。每个环境配置文件定义其特定的位置、脚本和服务器。因此,在我的 pox.xml 文件中,我将定义面向任务的配置文件 “deploywar”,如清单 6 所示:

清单 6. 部署配置文件
    <profiles>
        <profile>
            <id>deploywar</id>
            <build>
                <plugins>
                    <plugin>
                        <groupId>net.fpic</groupId>
                        <artifactId>tomcat-deployer-plugin</artifactId>
                        <version>1.0-SNAPSHOT</version>
                        <executions>
                            <execution>
                                <id>pos</id>
                                <phase>install</phase>
                                <goals>
                                    <goal>deploy</goal>
                                </goals>
                                <configuration>
                                    <host>${deploymentManagerRestHost}</host>
                                    <port>${deploymentManagerRestPort}</port>
                                    <username>${deploymentManagerRestUsername}</username>
                                    <password>${deploymentManagerRestPassword}</password>
                                    <artifactSource>
                                      address/target/addressservice.war
                                    </artifactSource>
                                </configuration>
                            </execution>
                        </executions>
                    </plugin>
                </plugins>
            </build>
        </profile>
    </profiles>

这个配置文件(通过 ID “deploywar” 区别)执行 tomcat-deployer-plugin,被配置来连接一个特定主机和端口,以及指定用户名和密码证书。所有这些信息使用变量来定义,比如 ${deploymentmanagerRestHost}。这些变量在我的 profiles.xml 文件中定义,如清单 7 所示:

清单 7. profiles.xml
        <!-- Defines the development deployment information -->
        <profile>
            <id>dev</id>
            <activation>
                <property>
                    <name>env</name>
                    <value>dev</value>
                </property>
            </activation>
            <properties>
                <deploymentManagerRestHost>10.50.50.52</deploymentManagerRestHost>
                <deploymentManagerRestPort>58090</deploymentManagerRestPort>
                <deploymentManagerRestUsername>myusername</deploymentManagerRestUsername>
                <deploymentManagerRestPassword>mypassword</deploymentManagerRestPassword>
            </properties>
        </profile>

        <!-- Defines the QA deployment information -->
        <profile>
            <id>qa</id>
            <activation>
                <property>
                    <name>env</name>
                    <value>qa</value>
                </property>
            </activation>
            <properties>
                <deploymentManagerRestHost>10.50.50.50</deploymentManagerRestHost>
                <deploymentManagerRestPort>58090</deploymentManagerRestPort>
                <deploymentManagerRestUsername>
                  myotherusername
                </deploymentManagerRestUsername>
                <deploymentManagerRestPassword>
                  myotherpassword
                </deploymentManagerRestPassword>
            </properties>
        </profile>

部署 Maven 配置文件

在 清单 7 的 profiles.xml 文件中,我定义了两个配置文件,并根据 env (环境)属性的值激活它们。如果 env 属性被设置为 dev,则使用开发部署信息。如果 env 属性被设置为 qa,那么将使用 QA 部署信息,等等。

这是部署文件的命令:

mvn -Pdeploywar -Denv=dev clean install

-Pdeploywar 标记通知要明确包含 deploywar 配置文件。-Denv=dev 语句创建一个名为 env 的系统属性,并将其值设为 dev,这激活了开发配置。传递 -Denv=qa 将激活 QA 配置。

5. 定制 Maven 插件

Maven 有十几个预构建插件供您使用,但是有时候您只想找到自己需要的插件,构建一个定制的 Maven 插件比较容易:

  1. 用 POM packaging 创建一个新项目,设置为 “maven-plugin”。
  2. 包括一个 maven-plugin-plugin 调用,可以定义您的公布插件目标。
  3. 创建一个 Maven 插件 “mojo” 类 (一个扩展 AbstractMojo 的类)。
  4. 为类的 Javadoc 做注释来定义目标,并为每个将被作为配置参数公布的变量做注解。
  5. 实现一个 execute() 方法,该方法在调用您的插件是将被调用。

例如,清单 8 显示了一个定制插件(为了部署 Tomcat)的相关部分:

清单 8. TomcatDeployerMojo.java
package net.fpic.maven.plugins;

import java.io.File;
import java.util.StringTokenizer;

import net.fpic.tomcatservice64.TomcatDeploymentServerClient;

import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;

import com.javasrc.server.embedded.CommandRequest;
import com.javasrc.server.embedded.CommandResponse;
import com.javasrc.server.embedded.credentials.Credentials;
import com.javasrc.server.embedded.credentials.UsernamePasswordCredentials;
import com.javasrc.util.FileUtils;

/**
 * Goal that deploys a web application to Tomcat
 *
 * @goal deploy
 * @phase install
 */
public class TomcatDeployerMojo extends AbstractMojo
{
	/**
	 * The host name or IP address of the deployment server
	 *
	 * @parameter alias="host" expression="${deploy.host}" @required
	 */
	private String serverHost;

	/**
	 * The port of the deployment server
	 *
	 * @parameter alias="port" expression="${deploy.port}" default-value="58020"
	 */
	private String serverPort;

	/**
	 * The username to connect to the deployment manager (if omitted then the plugin
	 * attempts to deploy the application to the server without credentials)
	 *
	 * @parameter alias="username" expression="${deploy.username}"
	 */
	private String username;

	/**
	 * The password for the specified username
	 *
	 * @parameter alias="password" expression="${deploy.password}"
	 */
	private String password;

	/**
	 * The name of the source artifact to deploy, such as target/pos.war
	 *
	 * @parameter alias="artifactSource" expression=${deploy.artifactSource}"
	 * @required
	 */
	private String artifactSource;

	/**
	 * The destination name of the artifact to deploy, such as ROOT.war.
	 * If not present then the
	 * artifact source name is used (without pathing information)
	 *
	 * @parameter alias="artifactDestination"
	 *   expression=${deploy.artifactDestination}"
	 */
	private String artifactDestination;

    public void execute() throws MojoExecutionException
    {
    	getLog().info( "Server Host: " + serverHost +
    			       ", Server Port: " + serverPort +
    			       ", Artifact Source: " + artifactSource +
    			       ", Artifact Destination: " + artifactDestination );

    	// Validate our fields
    	if( serverHost == null )
    	{
    		throw new MojoExecutionException(
    		  "No deployment host specified, deployment is not possible" );
    	}
    	if( artifactSource == null )
    	{
    		throw new MojoExecutionException(
    		  "No source artifact is specified, deployment is not possible" );
    	}

        ...
   }
}

在这个类的头部,@goal 注释指定 MOJO 执行的目标,而 @phase 指出目标执行的阶段。除了一个映射到一个有真实值的系统属性的表达式之外,每个公布的属性有一个 @phase 注释,通过将被执行的参数指定别名。如果属性有一个 @required 注释,那么它是必须的。如果它有一个 default-value,那么如果没有指定的话,将使用这个值。在 execute() 方法中,您可以调用 getLog() 来访问 Maven 记录器,根据记录级别,它将输出具体消息到标准输出设备。如果插件发生故障,抛出一个 MojoExecutionException 将导致构建失败。

转自:https://www.ibm.com/developerworks/cn/java/j-5things13/

5月 212014
 

一直觉得使用两个 Maven 插件maven-jar-plugin 和 maven-dependency-plugin并copy文件的方式来完成可执行jar包打包比较麻烦(参考文章:maven所不知道的5件事),今天看到一片文章对onejar-maven-plugin的介绍,真是太好了,一次搞定,good,强烈推荐!

1、问题背景

我们有时要开发一个Java Application,就是main来直接运行的那种,虽然有好多工具可以帮助我们打为jar。
但会有以下两个问题:

第一种是需要lib目录依赖一起来运行。(需要依赖文件,一个jar不可以运行)
第二种就是是把其它依赖的jar解开和你的类放在一个jar中。(框架的限制,包依赖之间的冲突,解压替换内容的过程产生类与资源的混乱)

第一种的问题显而易见需要copy太多东西(lib/*.jar)太麻烦。
第二种虽然可以做到一个jar运行的效果,但因为是解开再合再一起,尤其是jar中类有冲突时将和你在ide中不解开执行的效果不一样。(如eclipse可以运行,打包出来就不可以运行)

2、用One-JAR来解决

这个工具很好的解决了这一点,它相当于做一了一个启动壳。可以不改变你的jar与依赖的jar包,也不用解开。
简单理解就是jar中有jar。运行可以达到ide或配类路径运行一样的效果。

One-JAR有maven下的插件onejar-maven-plugin,所以对于maven的jar工程来说打包很方便。
pom.xml只需要加入以下plugin内容

01 <plugin>
02     <groupId>org.apache.maven.plugins</groupId>
03     <artifactId>maven-jar-plugin</artifactId>
04     <configuration>
05         <archive>
06             <manifest>
07                 <mainClass>org.noahx.onejartest.Launcher</mainClass>
08             </manifest>
09         </archive>
10     </configuration>
11 </plugin>
12  
13 <plugin>
14     <groupId>com.jolira</groupId>
15     <artifactId>onejar-maven-plugin</artifactId>
16     <version>1.4.4</version>
17     <executions>
18         <execution>
19             <configuration>
20                 <attachToBuild>true</attachToBuild>
21                 <classifier>onejar</classifier>
22             </configuration>
23             <goals>
24                 <goal>one-jar</goal>
25             </goals>
26         </execution>
27     </executions>
28 </plugin>

maven-jar-plugin大家比较熟悉,主要的加启动类。

onejar-maven-plugin是我们的主角。有了它,你再运行mvn package时,就会多生成一个xxxxxx.one-jar.jar文件。

这个文件直接可以java -jar xxxxxx.one-jar.jar来单独运行。
而且就这一个jar。不需要其它依赖。copy起来很方便。

转自:http://my.oschina.net/noahxiao/blog/78241

5月 092014
 

结合上一篇文章《一个多maven项目聚合的实例》应该就能配置出需要的多web配置。

在一个大项目中拆分maven工程时,很有可能会把js、css、jsp等文件放在不同的工程里(根据业务模块划分)。因为如果都集中在一个maven webapp里,那么这个maven webapp会太大,而且在业务上也比较分散 

但是这些持有js、css、jsp的maven工程,如果packaging设置为jar是不合适的,因为外围要读取内部的这些文件就会很困难。在这种场景下,一个很自然的想法就是打成war包,然后用某种方式将多个war包归并起来,得到最终的war包 

这就是overlays发挥作用的地方 

以下举一个例子: 

这里有2个web工程,一个是task-sla-web,一个是task-web-dist,packaging类型都是war,目录结构如下: 

 

 

下面是task-sla-web的pom文件: 

Xml代码  收藏代码

  1. <modelVersion>4.0.0</modelVersion>  
  2.     <groupId>com.huawei.inoc.wfm.task</groupId>  
  3.     <artifactId>task-sla-web</artifactId>  
  4.     <packaging>war</packaging>  
  5.     <version>0.0.1-SNAPSHOT</version>  
  6.     <name>task-sla-web</name>  

该工程就是打成一个war包,但是这个war是无法运行的,而是稍后用来合并的。(其中放了 一个空的web.xml,因为maven-war-plugin的package goal有强制要求) 

下面是task-web-dist的pom文件: 

Xml代码  收藏代码

  1. <modelVersion>4.0.0</modelVersion>  
  2.     <groupId>com.huawei.inoc.wfm.task</groupId>  
  3.     <artifactId>task-web-dist</artifactId>  
  4.     <packaging>war</packaging>  
  5.     <version>0.0.1-SNAPSHOT</version>  
  6.     <name>task-web-dist</name>  

Xml代码  收藏代码

  1. <!– 合并多个war –>  
  2.             <plugin>  
  3.                 <groupId>org.apache.maven.plugins</groupId>  
  4.                 <artifactId>maven-war-plugin</artifactId>  
  5.                 <version>2.1.1</version>  
  6.                 <configuration>  
  7.                     <overlays>  
  8.                         <overlay>  
  9.                             <groupId>com.huawei.inoc.wfm.task</groupId>  
  10.                             <artifactId>task-sla-web</artifactId>  
  11.                         </overlay>  
  12.                     </overlays>  
  13.                 </configuration>  
  14.             </plugin>  

Xml代码  收藏代码

  1. <!– 配置依赖 –>  
  2.     <dependencies>  
  3.         <dependency>  
  4.             <groupId>com.huawei.inoc.wfm.task</groupId>  
  5.             <artifactId>task-sla-web</artifactId>  
  6.             <version>0.0.1-SNAPSHOT</version>  
  7.             <type>war</type>  
  8.         </dependency>  
  9.     </dependencies>  

以上片段主要要注意几点: 

1、task-web-dist自身的packaging类型也是war 
2、在<overlay>中配置要归并的webapp的groupId和artifactId,注意的是,该pom所在的webapp工程是主工程,会覆盖掉所有待归并工程的同名文件,包括web.xml 
3、要归并的webapp,必须声明为依赖 

归并后的最终war包如下: 

 

其中的文件和.class都是由2个war包归并得到的,task-web-dist是主war包,如果多个war包中存在重名文件,则会被task-web-dist的文件覆盖,比如web.xml

5月 092014
 

好文章,大家一起来学习下(转自:http://www.infoq.com/cn/news/2011/01/xxb-maven-3-pom-refactoring/

在本专栏的上一篇文章POM重构之增还是删中,我们讨论了一些简单实用的POM重构技巧,包括重构的前提——持续集成,以及如何通过添加或者删除内容来提高POM的可读性和构建的稳定性。但在实际的项目中,这些技巧还是不够的,特别值得一提的是,实际的Maven项目基本都是多模块的,如果仅仅重构单个POM而不考虑模块之间的关系,那就会造成无谓的重复。本文就讨论一些基于多模块的POM重构技巧。

重复,还是重复

程序员应该有狗一般的嗅觉,要能嗅到重复这一最常见的坏味道,不管重复披着怎样的外衣,一旦发现,都应该毫不留情地彻底地将其干掉。不要因为POM不是产品代码而纵容重复在这里发酵,例如这样一段代码就有重复:

<dependency>
  <groupId>org.springframework</groupId>
  <artifactid>spring-beans</artifactId>
  <version>2.5</version>
</dependency>
<dependency>
  <groupId>org.springframework</groupId>
  <artifactid>spring-context</artifactId>
  <version>2.5</version>
</dependency>
<dependency>
  <groupId>org.springframework</groupId>
  <artifactid>spring-core</artifactId>
  <version>2.5</version>
</dependency>

你会在一个项目中使用不同版本的SpringFramework组件么?答案显然是不会。因此这里就没必要重复写三次<version>2.5</version>,使用Maven属性将2.5提取出来如下:

<properties>
  <spring.version>2.5</spring.version>
</properties>
<depencencies>
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactid>spring-beans</artifactId>
    <version>${spring.version}</version>
  </dependency>
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactid>spring-context</artifactId>
    <version>${spring.version}</version>
  </dependency>
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactid>spring-core</artifactId>
    <version>${spring.version}</version>
  </dependency>
</depencencies>

现在2.5只出现在一个地方,虽然代码稍微长了点,但重复消失了,日后升级依赖版本的时候,只需要修改一处,而且也能避免漏掉升级某个依赖。

读者可能已经非常熟悉这个例子了,我这里再啰嗦一遍是为了给后面做铺垫,多模块POM重构的目的和该例一样,也是为了消除重复,模块越多,潜在的重复就越多,重构就越有必要。

消除多模块依赖配置重复

考虑这样一个不大不小的项目,它有10多个Maven模块,这些模块分工明确,各司其职,相互之间耦合度比较小,这样大家就能够专注在自己的模块中进行开发而不用过多考虑他人对自己的影响。(好吧,我承认这是比较理想的情况)那我开始对模块A进行编码了,首先就需要引入一些常见的依赖如JUnit、Log4j等等:

  <dependency>
    <groupId>junit</groupId>
    <artifactid>junit</artifactId>
    <version>4.8.2</version>
    <scope>test</scope>
  </dependency>
  <dependency>
    <groupId>log4j</groupId>
    <artifactid>log4j</artifactId>
    <version>1.2.16</version>
  </dependency>

我的同事在开发模块B,他也要用JUnit和Log4j(我们开会讨论过了,统一单元测试框架为JUnit而不是TestNG,统一日志实现为Log4j而不是JUL,为什么做这个决定就不解释了,总之就这么定了)。同事就写了如下依赖配置:

  <dependency>
    <groupId>junit</groupId>
    <artifactid>junit</artifactId>
    <version>3.8.2</version>
  </dependency>
  <dependency>
    <groupId>log4j</groupId>
    <artifactid>log4j</artifactId>
    <version>1.2.9</version>
  </dependency>

看出什么问题来没有?对的,他漏了JUnit依赖的scope,那是因为他不熟悉Maven。还有什么问题?对,版本!虽然他和我一样都依赖了JUnit及Log4j,但版本不一致啊。我们开会讨论没有细化到具体用什么版本,但如果一个项目同时依赖某个类库的多个版本,那是十分危险的!OK,现在只是两个模块的两个依赖,手动修复一下没什么问题,但如果是10个模块,每个模块10个依赖或者更多呢?看来这真是一个泥潭,一旦陷进去就难以收拾了。

好在Maven提供了优雅的解决办法,使用继承机制以及dependencyManagement元素就能解决这个问题。注意,是dependencyMananget而非dependencies。也许你已经想到在父模块中配置dependencies,那样所有子模块都自动继承,不仅达到了依赖一致的目的,还省掉了大段代码,但这么做是有问题的,例如你将模块C的依赖spring-aop提取到了父模块中,但模块A和B虽然不需要spring-aop,但也直接继承了。dependencyManagement就没有这样的问题,dependencyManagement只会影响现有依赖的配置,但不会引入依赖。例如我们可以在父模块中配置如下:

<dependencyManagement>
  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactid>junit</artifactId>
      <version>4.8.2</version>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>log4j</groupId>
      <artifactid>log4j</artifactId>
      <version>1.2.16</version>
    </dependency>
  </dependencies>
</dependencyManagement>

这段配置不会给任何子模块引入依赖,但如果某个子模块需要使用JUnit和Log4j的时候,我们就可以简化依赖配置成这样:

  <dependency>
    <groupId>junit</groupId>
    <artifactid>junit</artifactId>
  </dependency>
  <dependency>
    <groupId>log4j</groupId>
    <artifactid>log4j</artifactId>
  </dependency>

现在只需要groupId和artifactId,其它元素如version和scope都能通过继承父POM的dependencyManagement得到,如果有依赖配置了exclusions,那节省的代码就更加可观。但重点不在这,重点在于现在能够保证所有模块使用的JUnit和Log4j依赖配置是一致的。而且子模块仍然可以按需引入依赖,如果我不配置dependency,父模块中dependencyManagement下的spring-aop依赖不会对我产生任何影响。

也许你已经意识到了,在多模块Maven项目中,dependencyManagement几乎是必不可少的,因为只有它是才能够有效地帮我们维护依赖一致性

本来关于dependencyManagement我想介绍的也差不多了,但几天前和Sunng的一次讨论让我有了更多的内容分享。那就是在使用dependencyManagement的时候,我们可以不从父模块继承,而是使用特殊的import scope依赖。Sunng将其列为自己的Maven Recipe #0,我再简单介绍下。

我们知道Maven的继承和Java的继承一样,是无法实现多重继承的,如果10个、20个甚至更多模块继承自同一个模块,那么按照我们之前的做法,这个父模块的dependencyManagement会包含大量的依赖。如果你想把这些依赖分类以更清晰的管理,那就不可能了,import scope依赖能解决这个问题。你可以把dependencyManagement放到单独的专门用来管理依赖的POM中,然后在需要使用依赖的模块中通过import scope依赖,就可以引入dependencyManagement。例如可以写这样一个用于依赖管理的POM:

<project>
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.juvenxu.sample</groupId>
  <artifactId>sample-dependency-infrastructure</artifactId>
  <packaging>pom</packaging>
  <version>1.0-SNAPSHOT</version>
  <dependencyManagement>
    <dependencies>
        <dependency>
          <groupId>junit</groupId>
          <artifactid>junit</artifactId>
          <version>4.8.2</version>
          <scope>test</scope>
        </dependency>
        <dependency>
          <groupId>log4j</groupId>
          <artifactid>log4j</artifactId>
          <version>1.2.16</version>
        </dependency>
    </dependencies>
  </dependencyManagement>
</project>

然后我就可以通过非继承的方式来引入这段依赖管理配置:

  <dependencyManagement>
    <dependencies>
        <dependency>
          <groupId>com.juvenxu.sample</groupId>
          <artifactid>sample-dependency-infrastructure</artifactId>
          <version>1.0-SNAPSHOT</version>
          <type>pom</type>
          <scope>import</scope>
        </dependency>
    </dependencies>
  </dependencyManagement>

  <dependency>
    <groupId>junit</groupId>
    <artifactid>junit</artifactId>
  </dependency>
  <dependency>
    <groupId>log4j</groupId>
    <artifactid>log4j</artifactId>
  </dependency>

这样,父模块的POM就会非常干净,由专门的packaging为pom的POM来管理依赖,也契合的面向对象设计中的单一职责原则。此外,我们还能够创建多个这样的依赖管理POM,以更细化的方式管理依赖。这种做法与面向对象设计中使用组合而非继承也有点相似的味道。

消除多模块插件配置重复

与dependencyManagement类似的,我们也可以使用pluginManagement元素管理插件。一个常见的用法就是我们希望项目所有模块的使用Maven Compiler Plugin的时候,都使用Java 1.5,以及指定Java源文件编码为UTF-8,这时可以在父模块的POM中如下配置pluginManagement:

<build>
  <pluginManagement>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>2.3.2</version>
        <configuration>
          <source>1.5</source>
          <target>1.5</target>
          <encoding>UTF-8</encoding>
        </configuration>
      </plugin>
    </plugins>
  </pluginManagement>
</build>

这段配置会被应用到所有子模块的maven-compiler-plugin中,由于Maven内置了maven-compiler-plugin与生命周期的绑定,因此子模块就不再需要任何maven-compiler-plugin的配置了。

与依赖配置不同的是,通常所有项目对于任意一个依赖的配置都应该是统一的,但插件却不是这样,例如你可以希望模块A运行所有单元测试,模块B要跳过一些测试,这时就需要配置maven-surefire-plugin来实现,那样两个模块的插件配置就不一致了。这也就是说,简单的把插件配置提取到父POM的pluginManagement中往往不适合所有情况,那我们在使用的时候就需要注意了,只有那些普适的插件配置才应该使用pluginManagement提取到父POM中。

关于插件pluginManagement,Maven并没有提供与import scope依赖类似的方式管理,那我们只能借助继承关系,不过好在一般来说插件配置的数量远没有依赖配置那么多,因此这也不是一个问题。

小结

关于Maven POM重构的介绍,在此就告一段落了。基本上如果你掌握了本篇和上一篇Maven专栏讲述的重构技巧,并理解了其背后的目的原则,那么你肯定能让项目的POM变得更清晰易懂,也能尽早避免一些潜在的风险。虽然Maven只是用来帮助你构建项目和管理依赖的工具,POM也并不是你正式产品代码的一部分。但我们也应该认真对待POM,这有点像测试代码,以前可能大家都觉得测试代码可有可无,更不会去用心重构优化测试代码,但随着敏捷开发和TDD等方式越来越被人接受,测试代码得到了开发人员越来越多的关注。因此这里我希望大家不仅仅满足于一个“能用”的POM,而是能够积极地去修复POM中的坏味道。

5月 092014
 

关于maven下多web项目合并的另一篇文章:

 在项目管理的过程中,初期可能一个项目并不大,所以建立了一个独立的web项目,但随着项目的发展,业务功能越来越多,但从业务依赖的角度来说,却是可以划分为多项目的。于是需要将这个庞大的web项目拆分成一个个独立的子web项目。这样的好处是,代码按模块划分,代码独立打成war包后,可以独立部署,如果某应用访问量大的话,也可以独立出来做分布式应用。
        以上是一般项目发展的历程,而这里我想说的是,在项目建立初期,就已经预见到了未来会是多项目依赖的这种情况,那在这个阶段,可以考虑直接划分为多个模块,而在打包的过程中直接构建成为一个war包来运行:
        1、按模块划分,采用标准的svn目录结构创建多个web项目(各模块可以独立运行),一个common项目(各模块的公用模块,打成jar包)
2、为每个项目创建pom-{projectName}.xml,编写好相应的配置
3、选择其中一个项目,增加一个合并打包的配置pom-all.xml,增加如下配置:
 1 <plugin>

 2         <artifactId>maven-war-plugin</artifactId>
 3         <version>2.1.1</version>
 4         <configuration>
 5             <warSourceDirectory>src/main/WebContent</warSourceDirectory>
 6             <overlays>
 7                 <overlay>
 8                     <groupId>com.xyz</groupId>
 9                     <artifactId>cms</artifactId>
10                     <excludes>
11                         <exclude>WEB-INF/lib/*</exclude>
12                         <exclude>WEB-INF/web.xml</exclude>
13                     </excludes>
14                 </overlay>
15             </overlays>
16         </configuration>
17     </plugin>
18 
19     <dependency>
20           <groupId>com.xyz</groupId>
21           <artifactId>cms</artifactId>
22           <version>1.0</version>
23           <type>war</type>
24           <scope>runtime</scope>
25     </dependency>


4、举例:先运行mvn install -f pom-cms.xml
              再运行mvn package -f pom-all.xml 即可

转自:http://www.blogjava.net/iduido/archive/2013/01/21/394520.html