crespo09 发表于 2017-3-1 11:23:32

由MAVEN入手浅谈项目构建与管理

Prologue . 前言
    第一次写博客,希望爱学习的小伙伴们喜欢。
    JAVA软件开发领域很喜欢一个名词,叫做"约定大于配置 "。我在此当然约法三章。
  


      写博客优先级很低。希望借此激发学习动力。


      参考权威和官方文档,独立思考,希望错误的观点被指正。


      对过去一段时间工作中的技术预研的思考总结。
  
    准备工作之外花费了很多时间。作为前端小白接触样式并适应博客园。选择了MAVEN为切入点,因为工作中吃饭睡觉打豆豆都是用MAVEN。希望能分享一些基础的观念,并且送给自己一份毕业周年的礼物。搞起~!@
  

Chapter one . Article Purpose
    目的:学会使用工具帮助开发者做繁琐的事情。
    内容:本文由maven入手,浅谈我在工作中对于 JAVA项目构建与管理 的理解。
    特色:在maven基础框架理解中提出的观点与质疑。
    侧重点:maven的学习理解。
    O(∩_∩)O
  

Chapter two . Introduce Maven

what is Maven


official interpretation
  英标:[`meivin]
  英译:专家
  释义:Apache 指出Maven 是一个项目管理工具。它的内容有:







  内容


  英文




  项目对象模型


  Project Object Model




  标准集合


  Standard Collection




  项目生命周期和阶段


  Project Lifecycle and Phase




  依赖管理系统


  Dependency Management System




  插件和目标


  Plugin and Goal




  仓库


  Repositories








  部分内容会在下文中讲述。

personal understand

    简单说maven还真他喵的是款项目管理工具。

    他可以帮助我们:



      整理复杂的jar依赖层次依赖。
      处理项目父子关系。
      了解项目构建结构和周期。
      集成各种插件。
      持续集成工具。

    如果我们简读过一些开源框架,会发现框架(尤其是apache 项目)很重要的编程观点:
      基于XML编程

      约定大于配置

    Maven是基于pom.xml文件的管理工具。它解析用户配置的pom文件,将其中的节点解读成一个个构件。
    (插件、依赖、输出都可以是一个构件)。
    一个MAVEN项目的结构的基本约定如下所示:







  路径


  描述




  src/main/java/


  java源代码包,编译后通过getClass()




  src/main/resource/


  配置文件资源包,编译后通过getResource()读取




  src/test/java/


  test源码包




  src/test/resource/


  对应资源包




  target/


  compile、site、report目标路径




  pom.xml


  POM文件




    备注:你可以根据resource插件自己定义你需要的目录结构。


preparatory knowledge

    下面我们可能要理解一些基本概念的简单栗子。



[*]依赖 dependency

    我们举个例子,你有一座葡萄酒工厂,(公司。)

    新疆的红葡萄生产红葡萄酒。加州的白葡萄生产白葡萄酒。(项目。)

    是的,你酿制葡萄酒使用了许多步骤(依赖。)

    这么多步骤组成了一个秘方。(依赖树。)

    开心的是,秘方还可以任意组合搭配,你一定很富有。

    每个员工都不会愿意酿制葡萄酒时自己去仓库取一堆葡萄和酒精。(一组jar包。)

    要是有差别味道会很差。(jdk版本的差异都会对开发造成影响。)

    这时候你想要拥有一条装配线。(maven工具)

    生产葡萄酒的员工们仅仅需要一份秘方。(pom.xml文件)

    派送的师傅就会把葡萄和原料送到员工手上。(仓库Repositories。)

     (别闹,我在激发写作兴趣=。=)

  
     在pom.xml中声明一个依赖节点dependency。它大概长这个样子。






1 <properties>
2
3   <junit.version>3.8.2</junit.version>
4
5 </properties>
6
7 <dependencys>
8
9   <dependency>
10
11   <groupId>junit</groupId>
12
13   <artifactId>junit</artifactId>
14
15   <version>${junit.version}</version>
16
17   <scope>test</scope>
18
19   </dependency>
20
21 </dependencys>            
View Code     同时,依赖具有传递性。



[*]坐标 Coordinates

    每一个依赖都是唯一的项目坐标。

    上述节点定义







  groupId


  artifactId


  version




  组织


  项目


  版本




    这是全世界唯一的值,用来描述一个JAR包。我认为这是maven的逻辑归档。

    备注:这个唯一有偏颇,事实上唯一的是:

    groupId.artifactId-major_version.minor_version.incremental_version-classifier.package

  
    根据坐标,你可以找到你想要的任何jar包。






mvn clean install -Dmaven.test.skip=true;
View Code    将你配置在pom.xml文件中的依赖从远程仓库下载到本机仓库,实现自动依赖。




[*]apache maven安装目录






  路径


  描述




  bin/


  maven运行脚本




  boot/


  类装载器




  conf/


  全局变量settings.xml文件 .part7




  lib/


  自身核心jar包




  LICENSE


  Apache软件许可证




  NOTICE


  通知权限




  README.txt


  安装指令





有了基本概念,就一起走入maven世界吧。O(&cap;_&cap;)O
why me maven


  虽然maven功能强大,但是个人用maven做下述事情:

    管理第三方jar包版本和依赖。      配置远程仓库nexus repository。
      使用插件做项目构建。
      项目代码质量检测。(PMD, findbugs, checkstyle你懂的。)
      方便集成持续集成工具。
      管理分布式应用多项目依赖关系。  


  其他的不做解释。
how to maven

install maven : http://maven.apache.org
    Maven安装的详细步骤我不做说明。


    安装JAVA       配置JAVA环境变量
      安装MAVEN
      配置MAVEN环境变量


  备注:我本机桌面不在C盘,所以不配置本机仓库路径。






mvn –v;
mvn help:system;
View Code

    All right,这时候本机上就会有一个几M小的可怜的maven。嘿,别高兴太早,它只是maven工程的最小集合。每当你使用一个命令(每个命令都是maven插件plugin的一个目标goal)。maven根据pom.xml把依赖树中缺失的依赖包含的jar文件下载,我们称这个过程为安装install。



touch maven in CMD

    请务必像我一样使用前先熟悉下基本操作。
    shirt + right click open CMD anywhere:






mvn -v; //查看mvn版本
mvn help:system; //查看系统变量
mvn archetype:generate -DgroupId=sapphire.webtest
-DartifactId=firstweb -DarchetypeArtifactId=maven-archetype-webapp -Dversion=1.0;
//创建一个maven we b原型项目firstweb,其中让你输入一个数字,表示发行快照SNAPSHOT版本
cd firstweb;
mvn eclipse:eclipse; //将项目转换为eclipse web项目方便导入。
mvn clean install -U -e -B;
//将项目target文件清空并重新编译安装(参数分别表示强制检出SNAPSHOT,打印失败日志,批处理)
mvn help:effective-pom; //输出有效pom文件,这可以帮助你了解superpom结构,或者优化pom依赖。
View Code  是的,单单上面的步骤,你就要下载好久。

maven projects manage  
    maven管理多级项目通过在pom.xml中配置父节点和子节点。
      父工程中:





<modules>
<module>simple-son1</module>
<module>simple-son2</module>
</modules>
View Code

      子工程中



<parent>
<groupId>…</groupId>
<artifactId>simple-parent1</artifactId>
<version>1.0</version>
</parent>


    maven还支持引用依赖实现继承.





<project>
<dependencies>
<dependency>
<groupId>…</groupId>
<artifactId> simple-parent1</artifactId>
<version>1.0</version>
<type>pom</type>
</dependency>
</dependencies>
</project>
View Code

    这里比普通的依赖多了一个type:






  类型


  作用




  Jar


  产生一个JAR 文件,子工程不能继承




  War


  产生一个web 应用,子工程不能继承




  Pom


  产生一个父工程





Chapter three . Build a Project



identification
    项目构建:翻阅了许多资料,也没有发现对于构建准确的解释。(一定是我太蠢T. T)




personal understand

    构建是一个生成输出的过程,在项目中。构建做以下事情。
      代码编译    source code

      依赖整理    order dependency

      发布文档    release and report

      变更记录    change log

      生成目录    publish structure

    举个栗子:有个宝贝,你将蔬菜水果沙拉生肉牛奶统统丢进去,自动做好香甜可口的饭菜。

    项目构建就是这么个过程,哪怕宝贝是你的爪子=。=,将代码构建成可执行软件并发布。


question:


    什么是可执行软件?应用目录如何在服务器上工作?

    一个应用的目录概念如下表:
    




执行环境:eclipse Maven Tomcat CentOS  




eclipse web项目
maven工程项目


  src
  config

  webContent



  src
  resource

  webapp









Tomcat是基于web.xml配置的服务器,当你使用eclipse tomcat插件时,eclipse自动编译JAVA文件,并根据项目结构构建出目录,放到tomcat的webapp下。tomcat我日后会抽时间单独总结。O(&cap;_&cap;)O

project structure

    我们引申一个概念:项目结构。我比较喜欢酱紫描述一个普通的JAVA应用结构概念。







  目录


  是否必要


  描述




  static/


  否,一般都有静态资源的概念,除非你有静态资源服务器。


  静态资源。




  META-INF/


  否


  描述信息。




  WEB-INF/


  是


  WEB信息。




    然后再看看WEB-INF/下的内容。







  目录


  是否必要


  描述




  classes/


  是


  应用程序编译好的class文件




  lib/


  是


  第三方依赖jar包。(本来觉得不必要,不过一想你不要servlet包玩毛web啊=。=)




  tags/


  否


  自定义标签




  src/


  否


  源码




  config/


  是


  配置文件,如数据库连接、可配变量等。




  views/


  是


  Web程序总需要有视图层吧。jsp freemaker velocity随你啦。




  web.xml


  是


  Web.xml文件




    当你将这样一个目录结构放在tomcat的webapp文件夹下,tomcat寻找到web.xml读取相关配置文件,
    读取配置文件,加载class文件和jar包class文件,启动并运行。~

  
    备注:即使你的项目结构不是这样的,你可以通过配置pom.xml达到目的:






<build>
<Directory>target</directory>
<sourceDirectory>src</sourceDirectory>
<testSourceDirectory>test</testSourceDirectory>
<outputDirectory>bin</outputDirectory>
</build>
View Code




experience

    然并卵,如果你想将应用放在linux服务器上eclipse可没什么用。公司可不会给你视图工具操作服务器,你需要自己去构建工程。处于创业型公司,我对构建项目的概念真的是从无到有,虽然现在也没有高明到哪里去。下面我会介绍一年来在封闭开发,加班开发,日常开发中(夭折啦)对构建项目的失败经验。





[*]石器时代

    使用Beyond Compare软件直接创建目录结构,当项目简单时我们确实用过这种蛮夷的方式构建项目。使用7z压缩软件将目录文件压缩成tar.gz包再压缩成zip文件用ftp工具上传到服务器的tomcat/webapp里。命令行连接服务器工具至今我还使用putty.





Ls ll; //查看可执行权限,没权限,我做过这种蠢事。T. T
ps –ef|grep ${tomcatname}
kill -9 ${pid} //shutdown tomcat只会关闭tomcat守护线程,我做过这种蠢事。T. T
cd ${tomcat/webapp}
unzip ${appname}.zip; //解压
tar -zxvf ${appname}.tar.gz; //解压
vi ${properties and xml} //修改配置文件,请确认端口唯一,我做过这种蠢事。T. T
cd ${tomcat/logs}
rm –rf *; //如果你删除logs目录tomcat无法正常启动的,我做过这种蠢事。T. T
cd ${tomcat/bin}
./start.sh //不能有空格,我做过这种蠢事。T. T
cd ${tomcat/logs}
tail –f catalina.out //查看项目启动有木有报错,常用这个逼格命令,外行人看起来很酷。
View Code





[*]
青铜时代
    使用ant工具打包。配置build.xml
    这段时间的经验让我感受到一些基本概念。


    xml编程       target概念
      build生命周期
    其中最重要一段:





<target name="package" depends="prepare,build.jars,build.conf,generate-tar-gz,generate-zip">
</target>
View Code

  弃用的主要原因是我是一个二把刀,每次添加一个配置文件都需要修改build.xml脚本中build.conf过程。
  而且会也没有更好的方式处理项目间依赖关系。随着项目增重,我放弃了这一方式。


[*]
铁器时代
  Eclipse导出war包打包。
  war包是tomcat可读应用包,eclipse支持导出一个web项目的war包。tomcat会感应webapp下war包的修改并热部署。war包会先构建一个类似上面描述的项目目录,然后tomcat解析运行.热部署意味着:tomcat启动时如果删除war包会导致构建目录也删掉。T. T




[*]
蒸汽时代
     利用maven插件打包。
  随着项目增多,体系多级依赖,甚至父工程间也存在依赖关系。使用maven插件。






  插件名称


  描述


  备注




  maven-antrun-plugin


  Ant的maven插件


  别和我提ant。




  maven-assembly-plugin


  打包工具


  Maven推荐的打包工具,可以打成tar.gz包等多种类型。




  maven-war-plugin


  打包工具


  将web项目打成war包,包含项目重命名,输出定向,过滤文件,归档等功能。




  maven-source-plugin


  打包辅助工具


  帮助打包你的源码








maven打包工具多样,各类具体配置网上都容易查到。最好的学习网站还是官网。

在我日常构建过程中,单纯在编译时期打包并无法满足需求。   为了说明这个问题这里引用maven一个概念:
    maven属于JAR包依赖而非工程依赖,这意味着执行子项目前,你需要把父工程安装完毕。这意味着,如果你的父项目依赖其他核心组件,例如技术中间件,业务中间件,业务接口等。你需要先deploy到服务器上,然后再使用项目构建,把发布到仓库里的其他项目安装下来。=。= 我说的很糊涂,请忘细。


[*]
信息时代
    持续集成。Continuous integration。持续集成是敏捷开发的阿哈利姆的神杖。^_^
    最近在网络上看了许多jenkins和hudson的使用案例,觉得很棒,它在本文中不是浅谈重点,所以有机会会有一个单独的总结意愿。这里只贴个头~~~






  持续集成Continuous integration




  提出


  针对复杂度高的项目提出"早集成,常集成,频繁集成"来帮助项目在早期发现项目风险和质量问题




  作用


  减少风险




  减少重复过程




  任何时间、任何地点生成可部署的软件




  增强项目的可见性




  建立团队对开发产品的信心




  概念


  持续集成是一种软件开发实践,对于提高软件开发效率并保障软件开发质量提供了理论基础。持续集成是一种软件开发实践,对于提高软件开发效率并保障软件开发质量提供了理论基础。





Chapter four . Lifecycle and Phase



question
    相信各位和我一样在初学maven时最郁闷的事是:有病啊为啥命令非要这么复杂。
  mvn clean compile site
  笑一笑,这里就涉及到maven命令的生命周期和过程。



生命周期 Lifecycle



identification
    生命周期是对所有的构建过程的进行抽象和统一。
    因为操作人员构建方式千变万化,所有公司的构建模式都大致相同。
    我曾翻遍maven核心代码寻找这个生命周期阶段,直到我在官方介绍上看到这么一句话:
   default lifecycle is defined without any associated. Bindings are defined separately for every packaging.
  链接:http://maven.apache.org/ref/3.0.4/maven-core/lifecycles.html
  然而,机智的我在maven-core.jar和maven-plugins.jar了解到这一内容。
    Maven包含三种不同且独立生命周期:






  生命周期


  描述




  clean


  清理项目,一般用来清除target编译目录。




  default


  构建项目,默认生命周期。




  site


  建立项目站点。




    网上针对该版块介绍很多,对于clean 和 site lifecycle略。
    这里介绍最常用default lifecycle默认生命周期,请往下看。



阶段 Phase
    机智的我同时在maven插件开发中发现这样一个注解,描述了生命周期各个阶段
    org.apache.maven.plugins.annotations.lifecycleParse






  过程


  描述




  validate


  验证项目是否正确,以及所有为了完整构建必要的信息是否可用。




  generate-sources


  生成所有需要包含在编译过程中的源代码




  process-sources


  处理源代码,比如过滤一些值




  generate-resources


  生成所有需要包含在打包过程中的资源文件




  process-resources


  复制并处理资源文件至目标目录,准备打包




  compile


  编译项目的源代码




  process-classes


  后处理编译生成的文件,例如对Java 类进行字节码增强(bytecode enhancement)




  generate-test-sources


  生成所有包含在测试编译过程中的测试源码




  process-test-sources


  处理测试源码,比如过滤一些值




  generate-test-resources


  生成测试需要的资源文件




  process-test-resources


  复制并处理测试资源文件至测试目标目录




  test-compile


  编译测试源码至测试目标目录




  test


  使用合适的单元测试框架运行测试。这些测试应该不需要代码被打包或发布




  prepare-package


  在真正打包前,执行准备打包必要的操作。这通常会产生一个包的展开的处理过的版本。




  package


  将编译好的代码打包成可分发的格式,如JAR,WAR,或者EAR




  pre-integration-test


  执行一些在集成测试运行之前需要的动作。如建立集成测试需要的环境




  integration-test


  如果有必要的话,处理包并发布至集成测试可以运行的环境




  post-integration-test


  执行一些在集成测试运行之后需要的动作。如清理集成测试环境。




  verify


  执行所有检查,验证包是有效的,符合质量规范




  install


  安装包至本地仓库,以备本地的其它项目作为依赖使用




  deploy


  复制最终的包至远程仓库,共享给其它开发人员和项目(通常和一次正式的发布相关)




  你没有看错,上面这个表完全是在凑!字!数!
  其中比较重要的有:(插件列是maven绑定在默认生命周期中的各个过程阶段插件。)






  过程


  插件


  作用




  compile


  compiler


  编译src/main/java源代码和其他配置的资源目录,到输出目录。




  resource


  resources


  复制src/main/resource资源和其它配置的测试资源目录,到测试输出目录。




  test


  surefire


  运行所有的测试并且创建那些捕捉详细测试结果的输出文件。




  package


  jar


  把输出目录打包成JAR 文件。




  install


  install


  将项目输出或某指定的文件加入到本机库




  deploy


  deploy


  将项目输出或某指定的文件加入到仓库中。




  maven源码将lifecycle中每一个phase放在一个LinkedList里,而在此phase运行命令时,  
    会使LinkedList前面的节点被链式调用。 
    比如:
    你可以编译。
   mvn clean compile;


    也可以直接安装,会同样执行编译阶段上的所有插件。(该命令跳过测试阶段)
   mvn clean install –Dmaven.test.skip=true;
    所以你要知道的是:




[*]当你使用一条maven命令,实质上,它不是maven的bin命令,它常常是maven默认的插件中的默认目标goal当goal执行时,触发LinkedList里以前的节点上配置的插件全部执行。




[*]每个阶段仅仅是阶段而已,如果没有在pom.xml中安装插件,阶段只执行默认插件。

Chapter five . Scope and Archetype
  这两个问题不深入探讨。



使用范围 Scope



qustion
    我已经解释了项目中每一个依赖在maven管理中就是一个depandency节点。Maven里如何控制节点范围呢。





<dependency>
<groupId>i.need.wlan</groupId>
<artifactId>i.need.wlan</artifactId>
<version>1.0.0</version>
<scope>test</scope>
</dependency>
View Code

    请原谅我不能举出更生动的例子,我断网了。还好有存货。枚举scope。






  范围


  描述




  Compile(默认)


  编译范围。




  Provided


  已提供范围。当JDK 或者一个容器已提供该依赖之后才使用。




  Runtime


  运行时范围。依赖在运行和测试系统的时候需要,但在编译的时候不需要。




  Test


  测试范围。在测试编译和测试运行阶段可用




  System


  已提供范围。显式的提供一个对于本地系统中JAR 文件的路径







骨架原型 Archetype

nature
    是maven工程自己的项目结构。
    常用的原型有:






  Artifact


  Group


  Description




  maven-archetype-j2ee-simple


  org.apache.maven.archetypes


  A simple J2EE Java application




  maven-archetype-quickstart


  org.apache.maven.archetypes





  maven-archetype-simple


  org.apache.maven.archetypes





  maven-archetype-webapp


  org.apache.maven.archetypes


  A simple Java web application




   当你不使用命令行创建maven项目时,你并不需要考虑骨架原型。
   使用eclipse创建项目时,你需要new maven project/module,选择archetype,创建一个原始maven工程。
   然后通过添加resource folder和eclipse project Facets转换功能,将新建的maven工程转变为eclipse工程。

Chapter six . Plugin and goals



identification
    Maven的核心包如此之小是因为它仅仅定义了抽象的生命周期,和开发API。具体的任务是交由插件完成的,插件以"独立"的构建形式存在。
    比如:




[*]maven-dependency-plugin插件
    分析项目依赖,找到重复的依赖,列出项目的依赖树。




[*]maven-source-plugin插件
    这个可能是最核心的插件了,因为它负责下载maven中央库中的依赖。

different



    插件和普通依赖在pom.xml中的区别。







  依赖


  插件




  package


  Pom       父工程


  package



  maven-plugin   




  Jar         子普通工程




  War      子web工程




  impl


  (nothing)


  impl


  org.apache.maven.plugin.Mojo






  在设计插件时,你需要声明多个任务goal。每个goal实现不同的功能。现在你可以通过 mvn plugin:goal 调用mvn命令了。








mvn clean:clean
mvn dependency:tree
mvn help:system
mvn idea:idea
mvn jetty:run
mvn hibernate3:hbm2ddl
View Code

  它们就好像ant中target一样。
  插件地址: http://maven.apache.org/plugins/index.html

Chapter seven . setting.xml and nexus



配置文件 Setting.xml
    Maven工作文件为pom.xml,而本身默认配置文件是setting.xml。
    在setting.xml中你可以配置:






  说明


  配置




  Maven依赖管理路径,最终系统下载下来的依赖都会放进去。


  <localRepository> usr/local/maven </localRepository>




  权限设置,控制与远程私服库依赖的关联,能否deploy


  <server>
   <id>snapshot-distributed</id>
   <username>…</username>
   <password>…</password>
  </server>




    这里给出一个setting.xml文件的详细配置解读,这样很蠢,但是能说明问题。
    忘了在哪里拷贝的。





1 <?xml version="1.0" encoding="UTF-8"?>
2 <settings xmlns=http://maven.apache.org/POM/4.0.0
3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/settings-1.0.0.xsd">
5<!--本地仓库。该值表示构建系统本地仓库的路径。其默认值为~/.m2/repository。 -->
6<localRepository>usr/local/maven</localRepository>
7<!--Maven是否需要和用户交互以获得输入。默认为true。-->
8<interactiveMode>true</interactiveMode>
9<!--Maven是否需要使用plugin-registry.xml文件来管理插件版本。默认为false。-->
10<usePluginRegistry>false</usePluginRegistry>
11<!--表示Maven是否需要在离线模式下运行。默认为false。当由于网络安全因素,构建服务器不能连接远程仓库的时候,该配置就十分有用。 -->
12<offline>false</offline>
13<!--当插件的组织Id(groupId)没有显式提供时,供搜寻插件组织Id(groupId)的列表。该元素包含一个pluginGroup元素列表,每个子元素包含了一个组织Id(groupId)。当我们使用某个插件,并且没有在命令行为其提供组织Id(groupId)的时候,Maven就会使用该列表。默认情况下该列表包含了org.apache.maven.plugins。 -->
14<pluginGroups>
15   <!--plugin的组织Id(groupId) -->
16   <pluginGroup>org.codehaus.mojo</pluginGroup>
17</pluginGroups>
18<!--用来配置不同的代理,多代理profiles 可以应对笔记本或移动设备的工作环境:通过简单的设置profile id就可以很容易的更换整个代理配置。 -->
19<proxies>
20   <!--代理元素包含配置代理时需要的信息-->
21   <proxy>
22    <!--代理的唯一定义符,用来区分不同的代理元素。-->
23    <id>myproxy</id>
24    <!--该代理是否是激活的那个。声明一组代理而只需要激活一个的时候,该元素就可以派上用处。 -->
25    <active>true</active>
26    <!--代理的协议。 协议://主机名:端口,分隔成离散的元素以方便配置。-->
27    <protocol>http</protocol>
28    <!--代理的主机名。协议://主机名:端口,分隔成离散的元素以方便配置。-->
29    <host>proxy.somewhere.com</host>
30    <!--代理的端口。协议://主机名:端口,分隔成离散的元素以方便配置。 -->
31    <port>8080</port>
32    <!--代理的用户名,用户名和密码表示代理服务器认证的登录名和密码。 -->
33    <username>proxyuser</username>
34    <!--代理的密码,用户名和密码表示代理服务器认证的登录名和密码。 -->
35    <password>somepassword</password>
36    <!--不该被代理的主机名列表。该列表的分隔符由代理服务器指定;使用了竖线分隔符,逗号分隔。-->
37    <nonProxyHosts>*.google.com|ibiblio.org</nonProxyHosts>
38   </proxy>
39</proxies>
40<!--配置服务端的一些设置。一些设置如安全证书不应该和pom.xml一起分发。存在于settings.xml文件中。-->
41<servers>
42   <!--服务器元素包含配置服务器时需要的信息 -->
43   <server>
44    <!--这是server的id,该id与distributionManagement中repository元素的id相匹配。-->
45    <id>server001</id>
46    <!--鉴权用户名。鉴权用户名和鉴权密码表示服务器认证所需要的登录名和密码。 -->
47    <username>my_login</username>
48    <!--鉴权密码 。鉴权用户名和鉴权密码表示服务器认证所需要的登录名和密码。 -->
49    <password>my_password</password>
50    <!--鉴权时使用的私钥位置。和前两个元素类似,私钥位置和私钥密码指定了一个私钥的路径(默认是/home/hudson/.ssh/id_dsa)以及如果需要的话,一个密语。将来passphrase和password元素可能会被提取到外部,但目前它们必须在settings.xml文件以纯文本的形式声明。 -->
51    <privateKey>${usr.home}/.ssh/id_dsa</privateKey>
52    <!--鉴权时使用的私钥密码。-->
53    <passphrase>some_passphrase</passphrase>
54    <!--文件被创建时的权限。如果在部署的时候会创建一个仓库文件或者目录,这时候就可以使用权限(permission)。这两个元素合法的值是一个三位数字,其对应了unix文件系统的权限,如664,或者775。 -->
55    <filePermissions>664</filePermissions>
56    <!--目录被创建时的权限。 -->
57    <directoryPermissions>775</directoryPermissions>
58    <!--传输层额外的配置项 -->
59    <configuration></configuration>
60   </server>
61</servers>
62<!--为仓库列表配置的下载镜像列表。 -->
63<mirrors>
64   <!--给定仓库的下载镜像。 -->
65   <mirror>
66    <!--该镜像的唯一标识符。id用来区分不同的mirror元素。 -->
67    <id>planetmirror.com</id>
68    <!--镜像名称 -->
69    <name>PlanetMirror Australia</name>
70    <!--该镜像的URL。构建系统会优先考虑使用该URL,而非使用默认的服务器URL。 -->
71    <url>http://downloads.planetmirror.com/pub/maven2</url>
72    <!--被镜像的服务器的id。例如,如果我们要设置了一个Maven中央仓库(http://repo1.maven.org/maven2)的镜像,就需要将该元素设置成central。这必须和中央仓库的id central完全一致。-->
73    <mirrorOf>central</mirrorOf>
74   </mirror>
75</mirrors>
76<!--根据环境参数来调整构建配置的列表。settings.xml中的profile元素是pom.xml中profile元素的裁剪版本。它包含了id,activation, repositories, pluginRepositories和 properties元素。这里的profile元素只包含这五个子元素是因为这里只关心构建系统这个整体(这正是settings.xml文件的角色定位),而非单独的项目对象模型设置。如果一个settings中的profile被激活,它的值会覆盖任何其它定义在POM中或者profile.xml中的带有相同id的profile。 -->
77<profiles>
78   <!--根据环境参数来调整的构件的配置-->
79   <profile>
80    <!--该配置的唯一标识符。 -->
81    <id>test</id>
82    <!--自动触发profile的条件逻辑。Activation是profile的开启钥匙。如POM中的profile一样,profile的力量来自于它能够在某些特定的环境中自动使用某些特定的值;这些环境通过activation元素指定。activation元素并不是激活profile的唯一方式。settings.xml文件中的activeProfile元素可以包含profile的id。profile也可以通过在命令行,使用-P标记和逗号分隔的列表来显式的激活(如,-P test)。-->
83    <activation>
84   <!--profile默认是否激活的标识-->
85   <activeByDefault>false</activeByDefault>
86   <!--当匹配的jdk被检测到,profile被激活。例如,1.4激活JDK1.4,1.4.0_2,而!1.4激活所有版本不是以1.4开头的JDK。-->
87   <jdk>1.5</jdk>
88   <!--当匹配的操作系统属性被检测到,profile被激活。os元素可以定义一些操作系统相关的属性。-->
89   <os>
90      <!--激活profile的操作系统的名字 -->
91      <name>Windows XP</name>
92      <!--激活profile的操作系统所属家族(如 'windows')-->
93      <family>Windows</family>
94      <!--激活profile的操作系统体系结构-->
95      <arch>x86</arch>
96      <!--激活profile的操作系统版本-->
97      <version>5.1.2600</version>
98   </os>
99   <!--如果Maven检测到某一个属性(其值可以在POM中通过${名称}引用),其拥有对应的名称和值,Profile就会被激活。如果值字段是空的,那么存在属性名称字段就会激活profile,否则按区分大小写方式匹配属性值字段-->
100   <property>
101      <!--激活profile的属性的名称-->
102      <name>mavenVersion</name>
103      <!--激活profile的属性的值 -->
104      <value>2.0.3</value>
105   </property>
106   <!--提供一个文件名,通过检测该文件的存在或不存在来激活profile。missing检查文件是否存在,如果不存在则激活profile。另一方面,exists则会检查文件是否存在,如果存在则激活profile。-->
107   <file>
108      <!--如果指定的文件存在,则激活profile。 -->
109      <exists>/usr/local/hudson/hudson-home/jobs/maven-guide-zh-to-production/workspace/</exists>
110      <!--如果指定的文件不存在,则激活profile。-->
111   <missing>/usr/local/hudson/hudson-home/jobs/maven-guide-zh-to-production/workspace/</missing>
112   </file>
113    </activation>
114    <!--对应profile的扩展属性列表。Maven属性和Ant中的属性一样,可以用来存放一些值。这些值可以在POM中的任何地方使用标记${X}来使用,这里X是指属性的名称。属性有五种不同的形式,并且都能在settings.xml文件中访问。
115    1. env.X: 在一个变量前加上"env."的前缀,会返回一个shell环境变量。例如,"env.PATH"指代了$path环境变量(在Windows上是%PATH%)。
116    2. project.x:指代了POM中对应的元素值。
117    3. settings.x: 指代了settings.xml中对应元素的值。
118    4. Java System Properties: 所有可通过java.lang.System.getProperties()访问的属性都能在POM中使用该形式访问,
119   如/usr/lib/jvm/java-1.6.0-openjdk-1.6.0.0/jre。
120    5. x: 在<properties/>元素中,或者外部文件中设置,以${someVar}的形式使用。 -->
121    <properties>
122   <user.install>/ebs1/build-machine/usr/local/hudson/hudson-home/jobs/maven-guide-</user.install>
123    </properties>
124    <!--远程仓库列表,它是Maven用来填充构建系统本地仓库所使用的一组远程项目。 -->
125    <repositories>
126   <!--包含需要连接到远程仓库的信息 -->
127   <repository>
128      <!--远程仓库唯一标识-->
129      <id>codehausSnapshots</id>
130      <!--远程仓库名称 -->
131      <name>Codehaus Snapshots</name>
132      <!--如何处理远程仓库里发布版本的下载-->
133      <releases>
134       <!--true或者false表示该仓库是否为下载某种类型构件(发布版,快照版)开启。-->
135       <enabled>false</enabled>
136       <!--该元素指定更新发生的频率。Maven会比较本地POM和远程POM的时间戳。这里的选项是:always(一直),daily(默认,每日),interval:X(这里X是以分钟为单位的时间间隔),或者never(从不)。 -->
137       <updatePolicy>always</updatePolicy>
138       <!--当Maven验证构件校验文件失败时该怎么做-ignore(忽略),fail(失败),或者warn(警告)。-->
139       <checksumPolicy>warn</checksumPolicy>
140      </releases>
141      <!--如何处理远程仓库里快照版本的下载。有了releases和snapshots这两组配置,POM就可以在每个单独的仓库中,为每种类型的构件采取不同的策略。例如,可能有人会决定只为开发目的开启对快照版本下载的支持。参见repositories/repository/releases元素-->
142      <snapshots>
143       <enabled/><updatePolicy/><checksumPolicy/>
144      </snapshots>
145      <!--远程仓库URL,按protocol://hostname/path形式 -->
146      <url>http://snapshots.maven.codehaus.org/maven2</url>
147      <!--用于定位和排序构件的仓库布局类型-可以是default(默认)或者legacy(遗留)。Maven 2为其仓库提供了一个默认的布局;然而,Maven 1.x有一种不同的布局。我们可以使用该元素指定布局是default(默认)还是legacy(遗留)。 -->
148      <layout>default</layout>
149   </repository>
150    </repositories>
151    <!--发现插件的远程仓库列表。仓库是两种主要构件的家。第一种构件被用作其它构件的依赖。这是中央仓库中存储的大部分构件类型。另外一种构件类型是插件。Maven插件是一种特殊类型的构件。由于这个原因,插件仓库独立于其它仓库。pluginRepositories元素的结构和repositories元素的结构类似。每个pluginRepository元素指定一个Maven可以用来寻找新插件的远程地址。-->
152    <pluginRepositories>
153   <!--包含需要连接到远程插件仓库的信息.参见profiles/profile/repositories/repository元素的说明-->
154         <pluginRepository>            
155      <releases>      
156       <enabled/><updatePolicy/><checksumPolicy/>
157      </releases>
158      <snapshots>
159       <enabled/><updatePolicy/><checksumPolicy/>
160      </snapshots>
161      <id/><name/><url/><layout/>
162         </pluginRepository>
163         </pluginRepositories>
164         <!--手动激活profiles的列表,按照profile被应用的顺序定义activeProfile。 该元素包含了一组activeProfile元素,每个activeProfile都含有一个profile id。任何在activeProfile中定义的profile id,不论环境设置如何,其对应的
165         profile都会被激活。如果没有匹配的profile,则什么都不会发生。例如,env-test是一个activeProfile,则在pom.xml(或者profile.xml)中对应id的profile会被激活。如果运行过程中找不到这样一个profile,Maven则会像往常一样运行。 -->
166    <activeProfiles>
167   <!-- -->
168   <activeProfile>env-test</activeProfile>
169    </activeProfiles>
170   </profile>
171</profiles>
172 </settings>
View Code


Nexus服务器



question
    你一定觉得喵的玩了这么久,居然还是玩单机!
  这里需要提出一个概念:仓库repository
  maven的仓库包含:






  本地仓库:你本机的仓库,就是你在setting.xml配置的localRepository




  远程仓库:


  私服:maven提供的nexus服务器




  中央仓库:maven公共库,所有的插件、依赖都在这里




  然后请不要取笑我的草率=。=我没网。
  
  nexus私服是建立在local repo和central repo间的构件管理服务器。他的机制是代理一些广域网上的远程仓库,供局域网内的Maven用户使用。上图画的并不严谨,因为宿主仓库nexus和中央仓库(central repo是最大的远程仓库)存在并列关系,只是优先级不同。当多台用户连接一个远程仓库时,nexus仓库只需要在外网的中央仓库下载一次依赖,所有的用户都会在nexus仓库中检测到依赖直接使用。

  详细如何安装nexus服务器请自己查阅。



        win      :   http://www.cnblogs.com/dingyingsi/p/3687077.html


        linux      :   http://www.cnblogs.com/leefreeman/archive/2013/04/03/2998315.html      
     在本小节结束的最后,根据我的肤浅经验,我不得不提出一条忠告:



       如果你修改了第三方依赖源码并上传到私服上,请同时上传源码包。

     源码包和依赖包唯一的区别就是:







  依赖包名称


  源码包名称




  example.jar


  example-source.jar





Chapter eight. Super Pom




identification


question
    说了半天,什么是pom.xml?

    对于maven pom.xml最终会被解析为项目对象模型(Project Object Model)。Maven通过pom文件管理项目依赖。使用者创建的maven工程pom.xml文件隐式继承super.pom你可以在maven-model-builder.jar找到。它声明了中央仓库的位置,约定了项目结构,引入了一些打包和编译的插件.你可以参考:http://maven.apache.org/ref/3-LATEST/maven-model-builder/super-pom.html
   它解析读取xml节点,最终通过LinkedHashSet实现每个依赖DataModel的坐标,并构造一个树依赖通过LinkedHashMap管理。下载依赖时,会得到LinkedHashMap中的依赖树依次下载。具体的pom配置我不详细描述,你可以参考:blog.csdn.net/yaerfeng/article/details/26448417   


Chapter nine . optimalize Conflict
       Maven中最痛苦的事情就是依赖的优化与冲突,所以这里单独拉出一个章节说明。

       这种现象的根本原因是由于依赖的复杂度:





[*]版本兼容性问题。





[*]间接依赖,多重依赖问题。

     举个栗子:

        小明和小毛,小淙是朋友。

        小淙和小涛是朋友。

        小涛和小毛见面就打架。

        问题是他们四个能不能长久一起愉快的玩耍?

        你一定会说,跳皮筋小涛,小明,小淙玩。打沙包小明,小毛,小淙玩。

     呵呵,单纯。Maven当然想到了这一点:scope范围界定运行时依赖。

     然而运行时所依赖包最终是要安装到生产环境的,这部分工作 Maven 并不能完成。

  

     怎么办呢,这时候你就需要改源码,或者google之……

  

    你可以通过一个命令查询该maven项目有效的pom当前依赖。






mvn help:effective-pom;
View Code
Chapter final . never be end
    这篇文章并没有什么真正的技术含量,在工作中算是日经帖。希望这是我接触开源技术社区的第一步吧。学习maven过程对我来说是一个漫长的过程,直到现在为止我也只接触了八个月。这篇杂谈着实没有什么逻辑。
    希望给更多初学者启发,也希望带给高端玩家新的学习乐趣。
    这篇博客耗时20小时,又花了数个小时调整样式,都是这周内午夜11点到凌晨2点完成的。写作过程中并没有参考什么文章,文中的链接是半年多积累的书签和大家分享。文中忽略了许多技术细节,具体问题具体分析。还有一些概念没有涉及,比如:maven如何管理运行时参数。…
    在写作过程中发现这几篇文章,对我帮助很大。




[*]Maven权威指南




[*]http://www.cnblogs.com/BigTall/archive/2011/03/23/1993253.html   




[*]http://stackoverflow.com/questions/184618/what-is-the-best-comment-in-source-code-you-have-ever-encountered (have fun ^_^)
  GoodNight.
  @author    :Galaxias.Sapphire.REN
  @Date      :2015年7月3日02:12:04
页: [1]
查看完整版本: 由MAVEN入手浅谈项目构建与管理