技术是资本经济中不友好的竞争者之间持续的、零和的游戏
核心概念:
约定优于配置:convention over configuration
插件plugin:一个Maven插件是一个单个或者多个目标的集合
目标goal:一个目标是一个明确的任务,它可以作为单独的目标运行,或者作为一个大的构建的一部分和其它目标一起运行
参数parameter:目标定义了一些参数,这些参数可以定义一些明智的默认值
构件artifact
项目对象模型POM:POM为项目命名,提供了项目的一组唯一标识符(坐标),
并且通过依赖 (dependencies) ,父 (parents) 和先决条件(prerequisite) 来定义和其它项目的关系
坐标 Coordinates:Maven坐标定义了一组标识,它们可以用来唯一标识一个项目,一个依赖,或者MavenPOM里的一个插件
groupId:团体,公司,小组,组织,项目,或者其它团体
artifactId:在groupId下的表示一个单独项目的唯一标识符
packaging:项目的类型,默认是jar,描述了项目打包后的输出
version:一个项目的特定版本
POM:
General Project Information(General,Contributors,Licenses)
Build Settings(build..(directories,extensions,resources,plugins),reporting..)
Build Environment(profiles,Environment Information,Maven Environment)
POM Relationships(Coordinate(groupId,artifactId,version),
Multi-Module,Inheritance,Dependencies)
项目总体信息
它包含了一个项目的而名称,项目的URL,发起组织,以及项目的开发者贡献者
列表和许可证。
构建设置
在这一部分,我们自定义Maven构建的默认行为。我们可以更改源码和测试代码
的位置,可以添加新的插件,可以将插件目标绑定到生命周期,我们还可以自定
义站点生成参数。
构建环境
构建环境包含了一些能在不同使用环境中 激活的profile。例如,在开发过程
中你可能会想要将应用部署到一个而开发服务器上,而在产品环境中你会需要将
应用部署到产品服务器上。构建环境为特定的环境定制了构建设置,通常它还会
由~/.m2中的自定义settings.xml补充。这个settings文件将会在第 11 章构 建
Profile中,以及第 A.1 节 “简介”中的附录 A, 附录: Settings细节小节中
讨论。
POM关系
一个项目很少孤立存在;它会依赖于其它项目,可能从父项目继承POM设置,它
要定义自身的坐标,可能还会包含子模块。
超级POM:/usr/local/maven/lib中的maven-2.0.9-uber.jar中包org.apache.maven.project下pom-4.0.0.xml
定制项目信息:licenses,organization 和 developers 元素是加在 dependencies元素之前的
添加新的依赖:
生命周期lifecycle:一个生命周期是一些阶段的序列
生命周期阶段phase:插件目标可以附着在生命周期阶段上
仓库repository:Maven仓库是通过结构来定义的,一个Maven仓库是项目构件的一个集合,这些构件存储在一个目录结构下面
一旦Maven已经从远程仓库下载了一个构件,它将永远不需要再下载一次,因为maven会首先在本地仓库查找插件,然后才是其它地方
Maven在本地项目中通过本地仓库来共享依赖
Maven同时下载构件和POM文件
依赖管理 Dependency Management:
传递性依赖:在Maven中一个依赖不仅仅是一个JAR。它是一个POM文件,这个POM可能也声明了对其它构件的依赖
Maven仓库不仅仅存贮二进制文件,也存储了这些构建的元数据(metadata),才使传递性依赖成为可能
依赖范围(dependency scope):
provided范围告诉Maven一个依赖在编译的时候需要,但是它不应该被捆绑在构建的输出中,这个范围告诉 Maven
jar 文件已经由容器“提供”了,因此不再需要包含在 war 中
插件:
1.archetype
archetype被定义为“一个原始的模型或者类型,在它之后其它类似的东西与之匹配;一个原型(prototype)”
基本项目:mvn archetype:create -DgroupId=org.sonatype.mavenbook.ch03 -DartifactId=simple -DpackageName=org.sonatype.mavenbook
web项目:-DarchetypeArtifactId=aven-archetype-webapp
多模块:
<groupId>org.sonatype.mavenbook.ch06</groupId>
<artifactId>simple-parent</artifactId>
<packaging>pom</packaging>
<version>1.0</version>
<name>Chapter 6 Simple Parent Project</name>
<modules>
<module>simple-weather</module>
<module>simple-webapp</module>
</modules>
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.sonatype.mavenbook.ch06</groupId>
<artifactId>simple-parent</artifactId>
<version>1-SNAPSHOT</version>
</parent>
<artifactId>simple-weather</artifactId>
<packaging>jar</packaging>
<name>Chapter 6 Simple Weather API</name>
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.sonatype.mavenbook.ch06</groupId>
<artifactId>simple-parent</artifactId>
<version>1-SNAPSHOT</version>
</parent>
<artifactId>simple-webapp</artifactId>
<packaging>war</packaging>
<name>Chapter 6 Simple Web Application Project</name>
2.help
四个目标(现在是九个)
help:active-profiles
列出当前构建中活动的Profile(项目的,用户的,全局的)。
help:effective-pom
显示当前构建的实际POM,包含活动的Profile。
help:effective-settings
打印出项目的实际settings, 包括从全局的settings和用户级别settings继承的配置。
help:describe
描述插件的属性。它不需要在项目目录下运行。但是你必须提供你想要描述插件的 groupId 和 artifactId
使用
mvn help:describe -Dplugin=help
mvn help:describe -Dplugin=help -Dfull
mvn help:describe -Dplugin=compiler -Dmojo=compile -Dfull
在Maven里面, 一个插件目标也被认为是一个 “Mojo”
3.Exec
Exec 插件让我们能够在不往 classpath 载入适当的依赖的情况下,运行这个程序
虽然 Exec 插件很有用,在开发过程中用来运行测试之外,你不应该依赖它来运行你的应用程序。 想要更健壮的解决方案,使用Maven Assembly 插件
4.Dependency
dependency:resolve 打印出已解决依赖的列
dependency:tree 项目的整个依赖树
mvn install -X 查看完整的依赖踪迹,包含那些因为冲突或者其它原因而被拒绝引入的构件,打开 Maven 的调试标记运行
mvn dependency:analyze
5.Surefire
忽略单元测试失败:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<testFailureIgnore>true</testFailureIgnore>
</configuration>
</plugin>
或者
$ mvn test -Dmaven.test.failure.ignore=true
跳过单元测试:
$ mvn install -Dmaven.test.skip=true
或者
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
6.Assembly
Maven Assembly 插件是一个用来创建你应用程序特有分发包的插件
如
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
</plugin>
----------------------------------------------
1.Jetty
使用 Maven Jetty 插件代替Jetty 或者 Apache Tomcat
<build>
<finalName>simple-webapp</finalName>
<plugins>
<plugin>
<groupId>org.mortbay.jetty</groupId>
<artifactId>maven-jetty-plugin</artifactId>
</plugin>
</plugins>
</build>
$ mvn jetty:run
2.Apache Geronimo
添加J2EE依赖
<dependency>
<groupId>org.apache.geronimo.specs</groupId>
<artifactId>geronimo-servlet_2.4_spec</artifactId>
<version>1.1.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.geronimo.specs</groupId>
<artifactId>geronimo-jsp_2.0_spec</artifactId>
<version>1.1</version>
<scope>provided</scope>
</dependency>
3.java运行
java -cp simple-weather-1.0-jar-with-dependencies.jar org.sonatype.mavenbook.weat
4.Hibernate
<dependencies>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-annotations</artifactId>
<version>3.3.0.ga</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-commons-annotations</artifactId>
<version>3.3.0.ga</version>
</dependency>
</dependencies>
@Entity
@NamedQueries({
@NamedQuery(name="Weather.byLocation",
query="from Weather w where w.location = :location")
})
public class Weather {
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
private Integer id;
@ManyToOne(cascade=CascadeType.ALL)
private Location location;
@OneToOne(mappedBy="weather",cascade=CascadeType.ALL)
private Condition condition;
@OneToOne(mappedBy="weather",cascade=CascadeType.ALL)
private Wind wind;
@OneToOne(mappedBy="weather",cascade=CascadeType.ALL)
private Atmosphere atmosphere;
private Date date;
public Weather() {}
public Integer getId() { return id; }
public void setId(Integer id) { this.id = id; }
// All getter and setter methods omitted...
}
$ mvn hibernate3:hbm2ddl 使用Hibernate3插件构造数据
-------------------------------------------------
优化依赖:
1.找出所有被用于一个以上模块的依赖,然后将其向上移到父POM的dependencyManagement片段;
2.为每个POM移除这些依赖的版本,否则它们会覆盖定义在父项目中的dependencyManagement;
3.修复hibernate-annotations和hibernate-commons-annotations的版本重复问题:
<properties>
<hibernate.annotations.version>3.3.0.ga</hibernate.annotations.version>
</properties>
<dependencyManagement>
...
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-annotations</artifactId>
<version>${hibernate.annotations.version}</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-commons-annotations</artifactId>
<version>${hibernate.annotations.version}</version>
</dependency>
4.兄弟依赖
一种方案是像其它依赖一样将它们移到父项目的dependencyManagement中,在最顶层的父项目中定义所有兄弟项目的版本
也可以使用内建属性org.sonatype.mavenbook和0.6-SNAPSHOT来解决这个版本问题:
<dependencies>
...
<dependency>
<groupId>org.sonatype.mavenbook</groupId>
<artifactId>simple-weather</artifactId>
<version>0.6-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.sonatype.mavenbook</groupId>
<artifactId>simple-persist</artifactId>
<version>0.6-SNAPSHOT</version>
</dependency>
...
</dependencies>
----------------------------------------------
生命周期:
项目有生命周期(lifecycle),生命周期中有一系列阶段,每个阶段都和一组goals绑定,goals由插件提供
对于一个项目来说,会可能使用以下公共生命周期阶段:
Validate – 验证项目正确性,以及所有必要的信息是否齐备;
Compile – 编译项目源代码;
Test – 使用单元测试框架测试编译过的源代码。这些测试无需代码被打包或者部署;
Package – 将编译过的代码打包,如JAR;
Integration-test – 为了集成测试能够进行,处理和部署应用到合时的环境;
Verify – 检查和检验package是否有效并且符合质量要求;
Install – 将package安装到本地仓库,供本地其他项目使用(作为依赖项);
Deploy – 在集成或者发布环境中,将最终的package拷贝到远程仓库,供其它开发人员或者项目共享。
记住,对于每个阶段,所有它之前的生命周期阶段都会执行
---------------------------------------------------
设置项目以使用构建生命周期
1.Packaging-goal
首先,是设置项目的packaging,默认为jar,所以不管你是否指定,packaging都会发生。每个packaging包含一系列绑定到特定阶段的goals。、
比如,对于JAR,会有以下goals绑定到生命周期:
阶段
Goal
Process-resources
Resources:resources
Compile
Compiler:compile
Precess-test-resources
Resources:testResources
Test-compile
Compiler:testCompile
Test
Surefire:test
Package
Jar:jar
Install
Install:install
Deploy
Deploy:deploy
2.插件(POM-goal)
第二种对阶段增加goals的方法就是在项目中配置插件。插件包含每个goal绑定到哪个阶段的信息。记住,仅仅增加插件还不够,你必须同时指定你需要的goals。
这些配置的goals将会加入到由packaging绑定到生命周期的goals。如果绑定到特定阶段的goal超过一个,那么来自packaging的goal会先执行,然后执行在POM配置的goal。
可以通过executions元素控制特定goals的顺序。
executions元素,这可以让你在需要时,使用不同的配置多次运行相同的goal。不同的execution可以给于不同的id,这样当用于继承或者应用profiles时,你就可以控制goal配置是否合并或者变成附加的execution中
某些goals可以用于多个阶段,并且没有默认值,对于这种情况,你可以(必须)自己指定阶段(phase)。比如,假设有一个goal touch:timestamp,用于将当前时间显示到文件中,你需要在process-test-resources阶段用它来指出测试是何时开始的,可以像下面那样配置:
...
<plugin>
<groupId>com.mycompany.example</groupId>
<artifactId>touch-maven-plugin</artifactId>
<executions>
<execution>
<phase>process-test-resources</phase>
<configuration>
<file>${project.output.directory}/timestamp.txt</file>
</configuration>
<goals>
<goal>timestamp</goal>
</goals>
</execution>
</executions>
</plugin>
...
其他:Dom4J, Log4J, Jaxen, Velocity, Commons IO
Struts2,Tapesty,Wicket,JSF,Waffle ,Plexus,Guice, Spring Framework