由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(∩_∩)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(∩_∩)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权威指南

GoodNight.

@author    :Galaxias.Sapphire.REN

@Date        :2015年7月3日02:12:04

posted @ 2015-07-03 22:09  Galaxias.Sapphi.REN  阅读(1667)  评论(5编辑  收藏  举报