maven

Maven有三套相互独立的生命周期,请注意这里说的是“三套”,而且“相互独立”,初学者容易将Maven的生命周期看成一个整体,其实不然。这三套生命周期分别是:
Clean Lifecycle 在进行真正的构建之前进行一些清理工作。
Default Lifecycle 构建的核心部分,编译,测试,打包,部署等等。
Site Lifecycle 生成项目报告,站点,发布站点。

每套生命周期都由一组阶段(Phase)组成,我们平时在命令行输入的命令总会对应于一个特定的阶段。比如,运行mvn clean ,这个的clean是Clean生命周期的一个阶段。有点绕?要知道有Clean生命周期,也有clean阶段。Clean生命周期一共包含了三个阶段:
pre-clean  执行一些需要在clean之前完成的工作
clean  移除所有上一次构建生成的文件
post-clean  执行一些需要在clean之后立刻完成的工作
mvn clean 中的clean就是上面的clean,在一个生命周期中,运行某个阶段的时候,它之前的所有阶段都会被运行,也就是说,mvn clean 等同于 mvn pre-clean clean ,如果我们运行 mvn post-clean ,那么 pre-clean,clean 都会被运行。这是Maven很重要的一个规则,可以大大简化命令行的输入。
Site生命周期的各个阶段:
pre-site     执行一些需要在生成站点文档之前完成的工作
site    生成项目的站点文档
post-site     执行一些需要在生成站点文档之后完成的工作,并且为部署做准备
site-deploy     将生成的站点文档部署到特定的服务器上
这里经常用到的是site阶段和site-deploy阶段,用以生成和发布Maven站点
Maven的最重要的Default生命周期,绝大部分工作都发生在这个生命周期中:
validate
generate-sources
process-sources
generate-resources
process-resources     复制并处理资源文件,至目标目录,准备打包。
compile     编译项目的源代码。
process-classes
generate-test-sources
process-test-sources
generate-test-resources
process-test-resources     复制并处理资源文件,至目标测试目录。
test-compile     编译测试源代码。
process-test-classes
test     使用合适的单元测试框架运行测试。这些测试代码不会被打包或部署。
prepare-package
package     接受编译好的代码,打包成可发布的格式,如 JAR 。
pre-integration-test
integration-test
post-integration-test
verify
install     将包安装至本地仓库,以让其它项目依赖。
deploy     将最终的包复制到远程的仓库,以让其它开发人员与项目共享。



第一步:配置maven环境

将下载文件解压,然后设置maven环境
如我的maven环境为:C:\maven\apache-maven-3.0.3
变量名:M2_HOME
变量值:C:\maven\apache-maven-3.0.3
打开命令提示符,检查我们的java环境和maven环境是否有误。$ mvn -v

第二步:修改仓库位置
修改我们仓库地址,仓库用于存放我们项目所依赖的所有jar包。
我的仓库路径:c:\maven\repo----这个路径是我自己创建,你可以将路径创建在任何位置。
我们打开…\apache-maven-3.0.3\conf\目录下的setting.xml文件,设置成我们创建的仓库路径
<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 http://maven.apache.org/xsd/settings-1.0.0.xsd">
  <!-- localRepository
   | The path to the local repository maven will use to store artifacts.
   |
   | Default: ~/.m2/repository
  <localRepository>/path/to/local/repo</localRepository>
  -->
    <localRepository>C:/mvn_repository</localRepository>
    
下面我们用一个命令验证一下。打开命令提示符,输入:mvn help:system
该命令会打印出所有的java系统属性和环境变量。这些信息对我们日常的编程工作很有帮且。

第三步:创建maven项目
mvn archetype:create -DgroupId=com.camps -DartifactId=camps -DpackageName=com.camps -Dversion=1.0
因为是第一次构建项目,所有依赖的jar包都要从maven的中央仓库下载,所以需要时间等待。等以后我们的本地仓库中积累了我们常用的jar包后,我们的开发将变得非常规范和方便。

pom.xml
<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.camps</groupId>
  <artifactId>camps</artifactId>
  <version>1.0</version>
  <packaging>pom</packaging>
  <name>camps</name>
  <url>http://maven.apache.org</url>

  <properties>
    <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>
  </dependencies>
</project>
modelVersion:指明POM使用的对象模型的版本。这个值很少改动。
groupId:指明创建项目的组织或者小组的唯一标识。GroupId是项目的关键标识,典型的,此标识以组织的完全限定名来定义。比如,org.apache.maven.plugins是所有Maven插件项目指定的groupId。
artifactId:指明此项目产生的主要产品的基本名称。项目的主要产品通常为一个JAR文件。第二,象源代码包通常使用artifactId作为最后名称的一部分。典型的产品名称使用这个格式: <artifactId>- <version>. <extension>
version:项目产品的版本号。Maven帮助你管理版本,可以经常看到SNAPSHOT这个版本,表明项目处于开发阶段
name:项目的显示名称,通常用于maven产生的文档中。
url:指定项目站点,通常用于maven产生的文档中。
description:描述此项目,通常用于maven产生的文档中。

第四步:编译项目代码
我们的项目已经创建完成。但我们点开目录发现,它并不是我们eclipse所需要的项目目录格式。我们需要把它构建成我们 eclipse可以导入的项目。
在命令提示符下进入到我们的创建的项目目录下,执行:mvn clean compile
Clean 告诉maven清理输入出目录target/,compile告诉maven编译项目主代码。
不要急,我们又需要一段时间来下载,相关jar包。
项目是编译完了,但项目的目录结构还不是我们想要的eclipse的项目结构,是不能导入到eclipse中的。所以,还需要执行一个命令:mvn eclipse:eclipse
命令执行完成后就得我们需要的项目目录了。

第五步:导入eclipse工具
打开的我们的eclipse工具。
先配置maven仓库路径
Window----Perferences-----java-----Build Path-----Classpath Variables
New一个变量的类路径。
M2_REPO : C:/C:/mvn_repository

第六步:包的更新与下载

 

打开项目发现我们junit 是3.8.1的,有点老了。那我想换成4.7的,如何通过maven的方式更换呢。其实,很简单,打开我们项目下的的pom.xml文件
<dependencies>
  <dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.8.1</version>
    <scope>test</scope>
  </dependency>
</dependencies>
更改变,junit的版本号,然后重新执行:mvn eclipse:eclipse  

Maven 中央仓库地址:http://search.maven.org

假如,我们想下载一个struts 的jar包。在搜索框内搜索strruts ,会要列出中央仓库中的所有struts版本。
我们在pom.xml中加入:
<groupId>stuts</groupId>
<artifactId>struts-scription</artifactId>
<version>1.0.1</version>
然后更新项目就可从中央仓库下载我们想要的任意jar包

1. 如何创建一个web项目。
其实非常简单,只是比普通项目多加一个参数DarchetypeArtifactId ,命令如下:
mvn archetype:generate -DgroupId=com.chongshi.test -DartifactId=mywebapps  -DarchetypeArtifactId=maven-archetype-webapp -Dversion=1.0
定位到创建项目的目录下构建成eclipse项目:$ mvn eclipse:eclipse


Eclipse 构建Maven项目 可以通过安装m2eclipse插件

Maven 多模块
所有用Maven管理的真实的项目都应该是分模块的,每个模块都对应着一个pom.xml。它们之间通过继承和聚合(也称作多模块,multi- module)相互关联。

假设有这样一个项目,很常见的Java Web应用。在这个应用中,我们分了几层:
    * Dao层负责数据库交互,封装了Hibernate交互的类。
    * Service层处理业务逻辑,放一些Service接口和实现相关的Bean。
    * Web层负责与客户端交互,主要有一些Structs的Action类。

对应的,在一个项目中,我们会看到一些包名:
    * org.myorg.app.dao
    * org.myorg.app.service
    * org.myorg.app.web
    * org.myorg.app.util

这样整个项目的框架就清晰了,但随着项目的进行,你可能会遇到如下问题:
1. 这个应用可能需要有一个前台和一个后台管理端(web或者swing),你发现大部分dao,一些service,和大部分util是在两个应用中可。这样的问题,你一周内遇到了好几次。
2. pom.xml中的依赖列表越来越长以重用的,但是,由于目前只有一个项目(WAR),你不得不新建一个项目依赖这个WAR,这变得非常的恶心,因为在Maven中配置对WAR的依赖远不如依赖JAR那样简单明了,而且你根本不需要org.myorg.app.web。有人修改了dao,提交到 svn并且不小心导致build失败了,你在编写service的代码,发现编译不过,只能等那人把dao修复了,你才能继续进行,很多人都在修改,到后来你根本就不清楚哪个依赖是谁需要的,渐渐的,很多不必要的依赖被引入。甚至出现了一个依赖有多个版本存在。
3. build整个项目的时间越来越长,尽管你只是一直在web层工作,但你不得不build整个项目。
4. 某个模块,比如util,你只想让一些经验丰富的人来维护,可是,现在这种情况,每个开发者都能修改,这导致关键模块的代码质量不能达到你的要求。

我们会发现,其实这里实际上没有遵守一个设计模式原则:“高内聚,低耦合”。虽然我们通过包名划分了层次,并且你还会说,这些包的依赖都是单向的,没有包的环依赖。这很好,但还不够,因为就构建层次来说,所有东西都被耦合在一起了。因此我们需要使用Maven划分模块。

一个简单的Maven模块结构是这样的:
---- app-parent
             |-- pom.xml (pom)
             |
             |-- app-util
             |        |-- pom.xml (jar)
             |
             |-- app-dao
             |        |-- pom.xml (jar)
             |
             |-- app-service
             |        |-- pom.xml (jar)
             |
             |-- app-web
                      |-- pom.xml (war)   

上述简单示意图中,有一个父项目(app-parent)聚合很多子项目(app-util, app-dao, app-service, app-web)。每个项目,不管是父子,都含有一个pom.xml文件。而且要注意的是,小括号中标出了每个项目的打包类型。父项目是pom,也只能是 pom。子项目有jar,或者war。根据它包含的内容具体考虑。

这些模块的依赖关系如下:
app-dao      --> app-util
app-service --> app-dao
app-web     --> app-service

注意依赖的传递性(大部分情况是传递的,除非你配置了特殊的依赖scope),app-dao依赖于app-util,app-service依赖于app-dao,于是app-service也依赖于app-util。同理,app-web依赖于app-dao,app-util。

用项目层次的划分替代包层次的划分能给我们带来如下好处:
   1. 方便重用,如果你有一个新的swing项目需要用到app-dao和app-service,添加对它们的依赖即可,你不再需要去依赖一个 WAR。而有些模块,如app-util,完全可以渐渐进化成公司的一份基础工具类库,供所有项目使用。这是模块化最重要的一个目的。
   2. 由于你现在划分了模块,每个模块的配置都在各自的pom.xml里,不用再到一个混乱的纷繁复杂的总的POM中寻找自己的配置。
   3. 如果你只是在app-dao上工作,你不再需要build整个项目,只要在app-dao目录运行mvn命令进行build即可,这样可以节省时间,尤其是当项目越来越复杂,build越来越耗时后。
   4. 某些模块,如app-util被所有人依赖,但你不想给所有人修改,现在你完全可以从这个项目结构出来,做成另外一个项目,svn只给特定的人访问,但仍提供jar给别人使用。
   5. 多模块的Maven项目结构支持一些Maven的更有趣的特性(如DepencencyManagement),这留作以后讨论。

接下来讨论一下POM配置细节
app-parent的pom.xml:
<modelVersion>4.0.0</modelVersion>  
<groupId>org.myorg.myapp</groupId>  
<artifactId>app-parent</artifactId>  
<packaging>pom</packaging>  
<version>1.0-SNAPSHOT</version>  
<modules>  
    <module>app-util</module>  
    <module>app-dao</module>  
    <module>app-service</module>  
    <module>app-web</module>  
</modules>  

特殊的地方在于,这里的packaging为pom。所有带有子模块的项目的packaging都为pom。packaging如果不进行配置,它的默认值是jar,代表Maven会将项目打成一个jar包。
该配置重要的地方在于modules,例子中包含的子模块有app-util, app-dao, app-service, app-war。在Maven build app-parent的时候,它会根据子模块的相互依赖关系整理一个build顺序,然后依次build

子模块符合配置继承父模块 
app-util
<modelVersion>4.0.0</modelVersion>  
<artifactId>app-util</artifactId>  
<parent>  
    <artifactId>app-parent</artifactId>  
    <groupId>org.myorg.myapp</groupId>  
    <version>1.0-SNAPSHOT</version>
    <relativePath></relativePath>
</parent>  
<dependencies>  
    <dependency>  
        <groupId>commons-lang</groupId>  
        <artifactId>commons-lang</artifactId>  
        <version>2.4</version>  
    </dependency>  
</dependencies>
relativePath 父项目的pom.xml 文件的相对路径。默认值为../pom.xml。maven首先从当前构建项目开始查找父项目的pom文件,然后从本地仓库,最有从远程仓库。 RelativePath允许你选择一个不同的位置。

app-dao,它也是继承于app-parent,同时依赖于app-util
<modelVersion>4.0.0</modelVersion>  
<artifactId>app-dao</artifactId>  
<parent>  
    <artifactId>app-parent</artifactId>  
    <groupId>org.myorg.myapp</groupId>  
    <version>1.0-SNAPSHOT</version>
    <relativePath></relativePath>
</parent>  
<dependencies>  
    <dependency>  
        <groupId>org.myorg.myapp</groupId>  
        <artifactId>app-util</artifactId>  
        <version>${project.version}</version>  
    </dependency>  
</dependencies>

这里要注意的是version的值为${project.version},这个值是一个属性引用,指向了POM的project/version的值,也就是这个POM对应的version。由于app-dao的version继承于app-parent,因此它的值就是1.0-SNAPSHOT。而 app-util也继承了这个值,因此在所有这些项目中,我们做到了保持版本一致。

我们最后看一下app-web:
<modelVersion>4.0.0</modelVersion>  
<artifactId>app-web</artifactId>  
<packaging>war</packaging>
<parent>  
    <artifactId>app-parent</artifactId>  
    <groupId>org.myorg.myapp</groupId>  
    <version>1.0-SNAPSHOT</version>
    <relativePath></relativePath>
</parent>  

<dependencies>  
    <dependency>  
        <groupId>org.myorg.myapp</groupId>  
        <artifactId>app-service</artifactId>  
        <version>${project.version}</version>  
    </dependency>  
</dependencies>
由于app-web是我们最终要部署的应用,因此它的packaging是war


使用 assembly plugin实现自定义打包
建立java项目,文件结构如下:
    demo1
    |____src/main/java
    |____src/main/config
    |____src/main/bin
    |____src/main/resources
    |____src/main/assemble
    |____src/test/java
    |____src/test/resources
    |____target
    |____pom.xml

除开增加了src/main/assemble目录和没有ant的build文件外,其他内容完全一样:其中src/main/java下放java代码;src/main/resources下放一个*.properties文件,这个资源文件是打包到 jar中,内容打包之后不需要改变的。src/main/config下放一个标准的log4j.xml,这个是有在安装运行前临时修改的需要的。src /main/bin下放置可执行文件。
assembly plugin的使用方式比较简单,主要有:
1. 修改pom.xml
pom.xml中设置如下:
<build>
    <plugins>
        <plugin>
            <artifactId>maven-assembly-plugin</artifactId>
            <version>2.3</version>
            <executions>
                <execution>
                    <id>project</id>
                    <phase>package</phase>
                    <goals>
                        <goal>single</goal>
                    </goals>
                    <configuration>
                        <descriptors>
                            <descriptor>src/main/assembly/component.xml</descriptor>
                        </descriptors>
                        <finalName>lib</finalName>
                        <appendAssemblyId>false</appendAssemblyId>
                    </configuration>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>
appendAssemblyId属性控制是否在生成的打包文件的文件名中包含assembly id。
descriptor属性指定maven-assembly-plugin的配置文件,当然我设置的是src/main/assemble/component.xml.容许使用多个,功能强大当然用法也复杂,对于简单情况一个足矣。
execution的设置是为了将maven-assembly-plugin继承到标准的maven打包过程中,这样在运行maven-package 时就会执行maven-assembly-plugin的操作,从而实现我们需要的自定义打包。
2. assemble descriptor file
我的src/main/assemble/component.xml内容如下:
<assembly>
    <id>package</id>
    <formats>
        <format>zip</format>
    </formats>
    <includeBaseDirectory>true</includeBaseDirectory>
    <fileSets>
        <fileSet>
            <directory>src/main/bin</directory>
            <outputDirectory>/</outputDirectory>
        </fileSet>
        <fileSet>
            <directory>src/main/config</directory>
            <outputDirectory>config</outputDirectory>
        </fileSet>
    </fileSets>
    <dependencySets>
        <dependencySet>
            <outputDirectory>lib</outputDirectory>
            <scope>runtime</scope>
        </dependencySet>
    </dependencySets>
</assembly>

1) format
format=zip设置打包的最终文件格式为zip.
支持的其他格式还有gz,tar,tar.gz,tar.bz2。
2)  fileset
<fileSet>
   <directory>src/main/bin</directory>
   <outputDirectory>/</outputDirectory>
</fileSet>
将src/main/bin目录下的文件打包到根目录(/)下.
<fileSet>
    <directory>src/main/config</directory>
    <outputDirectory>config</outputDirectory>
</fileSet>
将src/main/config目录下的文件打包到config下.

3) dependencySets
<dependencySet>
   <outputDirectory>lib</outputDirectory>
   <scope>runtime</scope>
</dependencySet>
将scope为runtime的依赖包打包到lib目录下。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值