由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>
同时,依赖具有传递性。
- 坐标 Coordinates
每一个依赖都是唯一的项目坐标。
上述节点定义
groupId |
artifactId |
version |
组织 |
项目 |
版本 |
这是全世界唯一的值,用来描述一个JAR包。我认为这是maven的逻辑归档。
备注:这个唯一有偏颇,事实上唯一的是:
groupId.artifactId-major_version.minor_version.incremental_version-classifier.package
根据坐标,你可以找到你想要的任何jar包。
mvn clean install -Dmaven.test.skip=true;
将你配置在pom.xml文件中的依赖从远程仓库下载到本机仓库,实现自动依赖。
- apache maven安装目录
路径 |
描述 |
bin/ |
maven运行脚本 |
boot/ |
类装载器 |
conf/ |
全局变量settings.xml文件 .part7 |
lib/ |
自身核心jar包 |
LICENSE |
Apache软件许可证 |
NOTICE |
通知权限 |
README.txt |
安装指令 |
why me maven
配置远程仓库nexus repository。
使用插件做项目构建。
项目代码质量检测。(PMD, findbugs, checkstyle你懂的。)
方便集成持续集成工具。
管理分布式应用多项目依赖关系。
how to maven
install maven : http://maven.apache.org
Maven安装的详细步骤我不做说明。
配置JAVA环境变量
安装MAVEN
配置MAVEN环境变量
mvn –v; mvn help:system;
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依赖。
是的,单单上面的步骤,你就要下载好久。
maven projects manage
maven管理多级项目通过在pom.xml中配置父节点和子节点。
父工程中:
<modules> <module>simple-son1</module> <module>simple-son2</module> </modules>
子工程中
<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>
这里比普通的依赖多了一个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 |
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>
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 //查看项目启动有木有报错,常用这个逼格命令,外行人看起来很酷。
-
青铜时代
使用ant工具打包。配置build.xml
这段时间的经验让我感受到一些基本概念。
target概念
build生命周期
其中最重要一段:
<target name="package" depends="prepare,build.jars,build.conf,generate-tar-gz,generate-zip"> </target>
弃用的主要原因是我是一个二把刀,每次添加一个配置文件都需要修改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属于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>
请原谅我不能举出更生动的例子,我断网了。还好有存货。枚举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
它们就好像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>
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;
Chapter final . never be end
这篇文章并没有什么真正的技术含量,在工作中算是日经帖。希望这是我接触开源技术社区的第一步吧。学习maven过程对我来说是一个漫长的过程,直到现在为止我也只接触了八个月。这篇杂谈着实没有什么逻辑。
希望给更多初学者启发,也希望带给高端玩家新的学习乐趣。
这篇博客耗时20小时,又花了数个小时调整样式,都是这周内午夜11点到凌晨2点完成的。写作过程中并没有参考什么文章,文中的链接是半年多积累的书签和大家分享。文中忽略了许多技术细节,具体问题具体分析。还有一些概念没有涉及,比如:maven如何管理运行时参数。…
在写作过程中发现这几篇文章,对我帮助很大。
- Maven权威指南
GoodNight.
@author :Galaxias.Sapphire.REN
@Date :2015年7月3日02:12:04
作者:牧伯流水
World need ur smile O(∩_∩)O Copyright ©2015 Galaxias.Sapphi.REN