maven实战学习笔记一(坐标和依赖)

maven3.0.4学习笔记
一、 安装
1.Maven安装比较简单,下载完后进行解压。配置环境变量M2_HOME (maven安装目录),将bin目录添加到path路径中。
下载地址:http://maven.apache.org/download.html
检查安装是否成功:在命令窗口中输入mvn –v 控制台能显示maven相关信息表示安装成功。

2.设置HTTP代理

<settings>
......
<proxies>
    <proxy>
         <id>my-proxy</id>
         <active>true</active>
         <protocol>http</protocol>
         <host>192.168.1.1></host>
         <port>3128</port>
         <!--
         <username>***</username>
         <password>***</password>
         <nonProxyHosts>repository.mycom.com|*.google.com</nonProxyHosts>
         -->
    </proxy>
</proxies>
....
</settings>

二、 目录结构
bin目录:
    该目录包含了mvn运行的脚本,其中mvn、mvnDebug是基于UNIX平台的shell脚本,mvn.bat、mvnDebug.bat是基于windows平台的bat脚本。该目录还包含m2.conf文件,这是classworlds的配置文件。
boot目录:
 该目录只包含一个文件,plexus-classworlds是一个类加载器框架,相对于默认的java类加载器,它提供了更丰富的语法以方便配置,maven使用该框架加载自己的类库
conf目录:
 settings.xml。直接修改该文件,就能在机器上全局地定制maven的行为,
 一般情况下,我们更偏向于复制该文件至用户目录。然后修改该文件,在用户范围定制maven的行为。
lib目录:
 该目录包含了所有maven运行时需要的java类库
src目录:
 maven源文档目录

三、 安装maven m2eclipse插件
 m2eclipse插件在线安装地址: http://m2eclipse.sonatype.org/sites/m2e
 插件安装完成后,打开 window-->preference-->Maven-->Installations ,点击Add...,选择我们自己安装的Maven目录。
 preference-->Maven-->Installations-->user settings,点击browse,选择自己的maven本地仓库。
 preference-->Java-->Installed JREs,点击Add..., 选择我们自己安装的JDK

 安装m2eclipse需要提醒的一点是,你可能会在使用 m2eclipse 时遇到类似这样的错误:Eclipse is running in a JRE, but a JDK is required
 这是因为 Eclipse 默认是运行在 JRE 上的,而 m2eclipse 的一些功能要求使用 JDK,解决方法是配置 Eclipse安装目录的eclipse.ini 文件,在-vmargs参数之前分2行添加vm配置指向 JDK,如:  
 -vm
 D:\java\jdk1.6.0_07\bin\javaw.exe

配置用户范围的setting.xml

复制%M2_HOME%/conf/setting.xml到用户目录下



四、 Maven入门
 1、maven项目结构
 /src/main/java  工程java源代码目录
 /src/main/resources 工程的资源目录
 /src/test/java  单元测试java源代码目录
 /src/test/resources 单元测试资源目录
 /target  输出目录,所有的输出物都存放在这个目录下
 /target/classes  编译之后的class文件
 
 2、pom.xml文件
 Maven项目的核心是pom.xml。POM(Project Object Model项目对象模型)定义了项目的基本信息,用于描述项目如何构建,声明项目依赖。pom.xml文件结构类似于:
 <modelVersion>4.0.0</modelVersion>
 <groupId>com.juvenxu.mvnbook</groupId>
 <artifactId>hello-world</artifactId>
 <version>1.0-SNAPSHOT</version>
 <name>Maven Hello World Project</name>
 <packaging>jar</packaging>
 <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>4.10</version>
   <scope>test</scope>
  </dependency>
 </dependencies>
 modelVersion:指定了当前POM模型的版本,对于Maven2及Maven 3来说,它只能是4.0.0。
 groupId:定义了项目属于哪个组,这个组往往和项目所在的组织或公司存在关联。通常为公司名称.项目名称。
 artifactId:定义了当前Maven项目在组中唯一的ID。通常为项目名称-模块名称
 version:指定了该项目当前的版本——1.0-SNAPSHOT,SNAPSHOT意为快照,说明该项目还处于开发中,是不稳定的版本
 name:元素声明了一个对于用户更为友好的项目名称,不是必须的。
 packaging:定义maven项目的打包方式,默认为jar
 properties:声明常量信息。通过${变量名}引用
 dependencies:指定了当前项目的所有依赖。所有的依赖都是通过坐标来进行存储的(GAV)。该元素下可以包含多个dependency元素以声明项目的依赖。groupId、artifactId、version是maven项目的基本坐标。有了这段声明后,maven会自动到中央仓库下载junit jar包。

maven最主要的命令
mvn clean compile:是清理target的内容并编译,
mvn clean test:是执行测试,
mvn clean package:是打包,
mvn clean install:是将项目输出的jar安装到maven的本地仓库中

执行maven clean compile,控制台输出
[INFO] Scanning for projects...
[INFO]                                                                         
[INFO] ------------------------------------------------------------------------
[INFO] Building tsp-user 0.0.1-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] --- maven-clean-plugin:2.4.1:clean (default-clean) @ tsp-user ---
[INFO] Deleting D:\workspace\tsp-user\target
[INFO]
[INFO] --- maven-resources-plugin:2.5:resources (default-resources) @ tsp-user ---
[debug] execute contextualize
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] skip non existing resourceDirectory D:\workspace\tsp-user\src\main\resources
[INFO]
[INFO] --- maven-compiler-plugin:2.3.2:compile (default-compile) @ tsp-user ---
[INFO] Compiling 1 source file to D:\workspace\tsp-user\target\classes
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 0.813s
[INFO] Finished at: Mon Oct 29 10:09:27 CST 2012
[INFO] Final Memory: 6M/15M
[INFO] ------------------------------------------------------------------------
clean 告诉maven清楚输出目录target/,compile告诉maven编译项目主代码,从输出中可以看到maven首先执行了clean:clean任务,删除target目录,接着执行resources:resources任务,最后执行compile:compile任务。将项目主代码编译到target/classes下。
clean:clean
resources:resources
compile:compile
对应一些maven插件及插件目标。clean:clean是clean插件的clean目标。
<scope>test</scope>,<scope>为依赖范围,如依赖范围为test,表示只对测试有效。如不声明依赖范围默认为compile.


maven compile插件默认只支持编译jdk1.3,配置插件支持jdk5
<build>
......
<plugins>
        <plugin>
          <groupId>org.apache.maven.plugins</groupId>
          <artifactId>maven-compiler-plugin</artifactId>
          <configuration>
            <source>1.5</source>
            <target>1.5</target>
          </configuration>
</plugin>
......
</plugins>
</build>


为了生成可执行的jar文件,需要借助maven-shade-plugin,配置该插件如下:
<plugin>
   <groupId>org.apache.maven.plugins</groupId>
   <artifactId>maven-shade-plugin</artifactId>
   <version>1.2.1</version>
   <executions><execution>
       <phase>package</phase>
       <goals>
             <goal>shade</goal>
       </goals>
       <configuration>
             <transformers>
                  <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransFormer">
                           <mainClass>com.juvenxu.mvnbook.helloworld.HelloWorld</mainClass>
                  </transformer>
             </transformers>
       </configuration>
   </execution></executions>
</plugin>

使用Archetype生成项目骨架:如果是maven3,简单地运行mvn archetype:generate。如果是maven2,最好运行命令mvn org.apache.maven.plugin.plugins:maven-archetype-plugin:2.0-alpha-5:generate

坐标和依赖
1.JAVA构件,MAVEN就必须将它们唯一标识,这就是依赖管理的底层基础--坐标。
2.maven定义了这样一组规则:世界上任何一个构件都可以使用maven坐标唯一标识,maven坐标的元素包括groupId,artifactId,version,packaging,classifier.
3.maven坐标是通过一些元素定义的,它们是groupId,artifactId,version,packaging,classifier.
这5个元素中只packaging是可选的(默认为jar),而classifier是不能直接定义的。
(1).groupId,定义当前maven项目隶属的实际项目。
(2).artifactId,定义实际项目中的一个maven项目(模块),推荐的做法是使用实际的项目名称作为artifactId的前缀。
(3).version,定义maven当前所处的版本。
(4).packaging,定义maven项目的打包方式。默认为jar
(5).classifier,该元素用来帮助定义构建输出的一些附属构件。
如nexus-index-2.0.0-javadoc.jar中,javadoc即为classifier,附属构建不是项目直接生成的,而是由附加插件帮助生成的。

4.项目构件的文件名是与坐标是相对应的,一般规则为"artifactId-version[-classifier].packaging",[-calssifier]表示可选。

5.scope是用来定义依赖范围。

6.依赖的配置
<project>
     ......
     <dependencies>
          <dependency>
                <groupId>....</groupId>
                <artifactId>......</artifactId>
                <version>........</version>
                <type>......</type>
                <scope>....</scope>
                <optional>...</optional>
                <exclusions>
                     ..........
                </exclusions>
          </dependency>
           ............
     </dependencies>
     ......
 </project>
(1).groupId,artifactId和version:依赖的基本坐标,对于任何一个依赖来说,基本坐标是最重要的,maven根据坐标才能找到需要的依赖。
(2).type:依赖的类型,对于项目坐标定义的packaging。大部分情况下,该元素不必声明,其默认值为jar。
(3).scope:依赖的范围。
(4).optional:标记依赖是否可选。
(5).exclusions:用来排除传递性依赖。

7.依赖范围:是用来控制依赖与这三种classpath(编译classpath,测试classpath,运行classpath)的关系,maven有下面几种依赖范围。
(1)compile:编译依赖范围。如果没有指定,就会默认使用该依赖范围。使用该依赖范围,对于编译,测试,运行三种classpath都有效。
(2)test:测试依赖范围。
(3)provided:已提供依赖范围。使用该依赖范围,对于编译和测试classpath有效,但运行时无效(servlet-api)。
(4)runtime:运行时依赖范围。使用该依赖范围,对于测试和运行classpath有效,但是编译时无效(jdbc驱动,编译时只需JDK提供的JDBC接口,运行时需要具体实现类)。
(5)system:系统依赖范围。该依赖与三种classpath的关系,和provided依赖范围完全一致。但是,使用system范围依赖时必须通过systemPath元素显式地指定依赖文件的路径。由于此依赖不是通过maven仓库解析的,而且往往与本机系统绑定,可能造成构建的不可移植,一次谨慎使用。systemPath可以引用环境变量。如下代码。
<dependency>
   <goupId>javax.sql</groupId>
   <artifactId>jdbc-stdext</artifactId>
   <version>2.0</version>
   <scope>system</scope>
   <systemPath>${java.home}/lib/rt.jar</systemPath>
</dependency>
(6)import:导入依赖范围。该依赖范围不会对三种classpath产生实际的影响。

8.传递性依赖:account-mail有一个compile范围的spring-core依赖,spring-core有一个compile范围的commons-logging依赖,那么commons-logging就会成为account-mail的compile范围依赖。
当第一直接依赖范围为test,第二直接依赖范围是compile的时候,依赖范围就是test
当第二直接依赖范围是compile,传递性依赖的范围与第一直接依赖相同。当第二直接依赖为test,依赖不会得以传递。
当第二直接依赖范围是provided,只传递第一直接依赖也为provided.且传递性依赖范围同样为provided.
当第二直接以来范围是runtime,传递性依赖的范围与第一直接依赖相同,当compile例外,此时传递性依赖的范围为runtime.


9.依赖调解:maven引入的传递性依赖机制,一方面大大简化和方便了依赖声明,另一方面大部分情况下我们只需要关心项目直接依赖的是什么,而不用考虑这些依赖会引入什么传递性依赖。但有时候,当传递依赖造成问题的时候,我们需要清楚地知道该传递性依赖是从哪条依赖路径引入的。

maven依赖调解的两个原则。(1)第一原则是:路径最近者优先。(2)第二原则是:第一声明者优先。在依赖路径长度相等的前提下,在pom依赖声明的顺序决定了谁会解析使用
,顺序最靠前的那个依赖优胜。
A->B->C->X(1.0)、A->D->X(2.0)
X(1.0)的路径为3,而X(2.0)的路径为2,因此X(2.0)会被解析。

A->B->Y(1.0)、A->C->Y(2.0)
对应路径长度相等的,在POM中依赖声明的顺序决定谁会被解析。


10.可选依赖:假设有这样一个依赖关系,项目A依赖于项目B,项目B依赖于项目X和Y,B对于X和Y的依赖都是可选依赖:A->B,B->X(可选),B->Y(可选)。根据传递性依赖的定义,如果所有这三个依赖的范围都是compile,那么X,Y 就是A的compile范围传递性依赖。然而,由于这里X,Y是可选依赖,依赖不会得以传递。换句话说,X,Y将不会对A有任何影响。项目B的依赖声明见代码清单。关于可选依赖需要说明的一点就是,在理想情况下,是不应该使用可选依赖的。
<project>
   <modelVerion>4.0</modelVersion>
   <groupId>com.juvenxu.mvnbook</groupId>
   <artifactId>project-B</artifactId>
   <version>1.0</version>
   <dependencies>
       <dependency>
           <groupId>mysql</groupId>
           <artifactId>mysql-connector-java</artifactId>
           <version>5.1.10</version>
           <optional>true</optional>
       </dependency>
       <dependency>
           <groupId>postgresql</groupId>
           <artifactId>postagresql</artifactId>
           <version>8.4-701.jdbc3</version>
           <optional>true</optional>
       </dependency>
   </dependencies>
</project>
因此当项目A依赖项目B的时候,如果实际使用基于Mysql数据库,那么在项目A中需要显示的声明mysql-connection-java依赖。

11.排除依赖。
传递性依赖给项目隐式地引入了很多依赖,这极大地简化了项目的依赖管理,但是有时候这种特性也会带来问题。比如,当前项目有一个第三方依赖,而这个第三方依赖由于某些原因依赖了另外一个类库的SNAPSHOT的版本,那么这个SNAPSHOT就会成为当前项目的传递性依赖,而SNAPSHOT的不稳定性会影响到当前项目。这时需要排除该SNAPSHOT,并且在当前项目中声明该类库某个正式发布版本。
<project>
   <modelVerion>4.0</modelVersion>
   <groupId>com.juvenxu.mvnbook</groupId>
   <artifactId>project-a</artifactId>
   <version>1.0.0</version>
   <dependencies>
       <dependency>
           <groupId>com.juvenxu.mvnbook</groupId>
           <artifactId>project-b</artifactId>
           <version>1.0.0</version>
           <exclusions>
             <exclusion>
                 <groupId>com.juvencu.mvnbook</groupId>
                 <artifactId>project-c</artifactId>
             </exclusion>
           </exclusions>
       </dependency>
       <dependency>
          <groupId>com.juvencu.mvnbook</groupId>
          <artifactId>project-c</artifactId>          
          <version>1.1.0</version>
       </dependency>
   </dependencies>
</project>
  代码中,项目A依赖于项目B,但是由于一些原因,不想引入传递性依赖C,而是自己显示地声明对于项目C1.1.0版本的依赖。代码中使用exclusions元素声明排除依赖,exclusions可以包含一个或者多个exclusion子元素。
需要注意的是,声明exclusion的时候只需要groupId,artifactId就能唯一定义某个依赖。


12.归类依赖。通过<properties>元素来定义。通过${变量名}来引用
声明一个常量信息,所有用到的地方都用这个常量
   <properties>
    <springversion>2.5.6</springversion>
    <junitversion>2.5.6</junitversion>
   </properties>

   <version>${springversion}</version>

13.优化依赖:maven会自动解析所有项目的直接依赖和传递性依赖,并且根据规则正确判断每个依赖的范围。对于一些依赖冲突,也能进行调节,以确保任何一个构件只有唯一的版本在依赖中存在。在这些工作之后,最后得到的那些依赖被称为解析依赖。运行下面两条命令分别可以查看当前项目的已解析依赖。
mvn dependency:list
mvn dependency:tree
使用mvn dependency:list和mvn dependency:tree可以帮助我们详细了解项目中所有依赖的具体信息。在此基础上,还有dependency:analyze工具可以帮助分析当前项目的依赖,但是该工具只会分析编译主代码和测试代码所需要用到的依赖,一些执行测试和运行时需要的依赖它就发现不了。

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值