Maven核心概念和日常实践

java 4 2016-02-29 13:03
女装

一、Maven

1.1 为什么写Maven

工欲善其事,必先利其器。如今Java相关开发,基本离不开Maven、Gradle、MAT、Hudson之类的玩意,所以把本文当作工具篇吧,后续有空再整理其他工具。

1.2 概述

Maven是优秀的构建工具,但不仅仅是能构建,还有着强大的仓库管理、项目管理相关的功能。我这介绍这一句话,像详细了解它的所有描述或者构建工具的介绍,请自行百度谷歌或参考官网。

1.3 安装

依赖JDK:下载JDK的压缩包,解压,配置环境变量JAVA_HOME=安装目录、PATH=$JAVA_HOME/bin:$PATH 即完成。
安装Maven:同样下载Maven的压缩包,解压,配置MAVEN_HOME=安装目录、PATH=$MAVEN_HOME/bin:$PATH 即完成。
检查JDK : java -version 。 检查Maven: mvn -version。
安装后需要了解的是:Maven项目最核心就是pom.xml文件(创建项目后才有),需要在项目中配置的就是配置在pom文件中,还有少数全局配置是配置在maven安装目录中conf下的setting.xml中。

1.4 常用Maven网站

注:国内镜像也有好些,可以自己找。因为周边大多数人都用了开源中国的镜像,所以我这边也推荐它。

1.5 创建Maven项目

(1)了解创建符合maven规范的项目结构,即src/main/java、src/main/resources那套。
(2)创建pom.xml文件。
(3)命令行可以通过Archetype命令生成项目骨架。Eclipse等IDE集成Maven后也可以创建Maven项目(推荐!!! )。
(4)常用命令

1.6 Pom文件变量属性

maven定义了很多变量,常见的maven属性,了解下自己可用,阅读其他项目的时候可看懂。
${basedir} 项目根目录
${project.name}项目名
${project.version}项目版本号
${project.groupId}项目groupId
${project.build.directory} target目录
${project.build.finalName} 打包的名字

二、依赖管理

2.1 概述

通过在pom.xml配置依赖坐标,Maven会自动帮我们下载依赖的构件。
Maven的依赖主要是通过groupId、artifactId和version三者一起来确定一个构件的坐标。

2.2 例子

<dependencies>
    <dependency>
        <groupId>junit</groupId>         <!-- groupId 公司和组织的标识 -->
        <artifactId>junit</artifactId>   <!-- artifactId 项目或者模块ID,在该groupID下必须唯一 -->
        <version>4.10</version>          <!-- version 版本号,带SNAPSHOT为快照版本 -->
        <scope>test</scope>              <!-- scope 依赖范围,默认为compile -->
        <exclusions>                     <!-- exclusions 用来排除传递性依赖 -->
           <exclusion>                   <!-- exclusions指定排除的依赖的groupId和artifactId -->
           ....
           </exclusion>
        </exclusions>
    </dependency>
<dependencies>

2.3 关于dependencyManagement

这个标签主要起到依赖统一管理的作用。一般maven开发多个项目的时候,都会创建一个parent父模块来配置pom文件统一管理公用的东西,(下面聚合和继承就是讲这部分)。在dependencyManagement下也是通过在dependencies标签下配置依赖的,但它上面在dependencies标签配置不同。

不同之处是:在dependencyManagement中配置了,项目并不会直接下载依赖的构件,而是要在子模块或者当前模块的dependencies中进行配置,表明当前模块需要用到的依赖,但此时就不用再指定版本号了。dependencyManagement也是以此来确保各个模块对相同构件可以用同一版本,也就利于统一升级版本号等等。

<dependencyManagement> <!-- 可以把它看成构件的版本声明,并不会引发下载 -->
    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>3.2.5.RELEASE</version>
        </dependency>
    </dependencies>
</dependencyManagement>
<dependencies>    <!-- 必须配置它才会进行依赖下载 -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-core</artifactId>
    </dependency>
</dependencies>

三、仓库

3.1 本地仓库

本地仓库没啥好说的,在maven安装目录下的conf/setting.xml中配置localRepository就可以指定路径。默认路径则是在用户根目录下的.m2/repository。
作用:maven编译模块的时候,依赖的模块都会按照本地->远程(一般是私服)->中央的顺序依次查找构件。平常开发的模块也是通过mvn install安装到本地仓库,其他编译时才能使用;而如果跟其他人合作开发则要通过deploy发布到远程仓库。发布后,别人下载依赖也会将通过远程或者中央仓库下载来的构件保存到别人的本地仓库。

<localRepository>D:\repository</localRepository>

3.2 远程仓库

一般在项目中,会在<repositories>标签下配置远程仓库,可以配置多个,但id必须唯一。中央仓库默认的id为central,可以不用配置;但如果有其他仓库用这个id,则会覆盖中央仓库。(不过,像一般公司都会自己搭建私服,所以也可以把central覆盖成我们私服的仓库,我们也这样做)。
在pom.xml中配置远程仓库的例子如下:

<repositories>
     <repository>
         <id>repo.springsource.org</id>
         <name>repo.springsource.org-releases</name>
         <url>http://repo.springsource.org/libs-milestone-local</url>
         <snapshots>
             <enabled>false</enabled>
         </snapshots>
    </repository>
    <repository>
        <id>nexus</id>   <!-- 私服仓库 -->
        <name>TeamNexusRepository</name>
        <url>http://localhost:8081/nexus/content/groups/public</url>
        <releases>
            <enabled>true</enabled>
        </releases>
        <snapshots>
            <enabled>false</enabled>
        </snapshots>
        <layout>default</layout>
    </repository>
    ...
</repositories>

另外还可以指定插件的仓库:

<pluginRepositories> 
    <pluginRepository> 
        <id>nexus</id>
        <name>TeamNexusRepository</name>
        <url>http://localhost:8081/nexus/content/groups/public</url> 
        <snapshots>
            <enabled>false</enabled>
        </snapshots>
    </pluginRepository>
</pluginRepositories>

在pom.xml中配置的远程仓库,只会在pom文件对应的模块有效,即使配置在parent的pom中用来被继承,那也只是当前项目各个模块有效。如果多个项目实际上都想用一样的远程仓库(实际场景就是私服),那需要在setting.xml中利用profile来进行配置。
在setting.xml中配置远程仓库的例子如下:

<profiles>
    <profile>
      <id>nexus</id>
      <repositories>
        <repository>
          <id>central</id>
          <url>http://localhost:8081/nexus/content/groups/public/</url>
        </repository>
      </repositories>
      <pluginRepositories>
        <pluginRepository>
          <id>central</id>
          <url>http://localhost:8081/nexus/content/groups/public/</url>
        </pluginRepository>
      </pluginRepositories>
    </profile>
</profiles>

<activeProfiles> <!-- 激活profile -->
    <activeProfile>nexus</activeProfile>
</activeProfiles>

3.3 仓库镜像

除了以上配置之外,我们还可以在setting.xml里面配置仓库的镜像,一般用于当访问某个仓库的时候,可能由于网络不同或者其他原因需要转换到另外一个地址,这个时候就可以配置这个仓库的镜像。例如你想覆盖中央仓库的默认地址,可以在setting.xml里面这样配置:

<mirrors>     
     <mirror>     
       <id>maven-net-cn</id>     
       <name>MavenChinaMirror</name>     
       <url>http://maven.net.cn/content/groups/public/</url>     
       <mirrorOf>central</mirrorOf>     
     </mirror>     
</mirrors>     

这里通过<mirrorOf>标签指定为central仓库做镜像,就是访问central的url不再是国外那个地址,而会被转为我们配置的镜像地址http://maven.net.cn/content/groups/public/ (也可以配置为私服地址等等), 而如果想为所有的仓库做镜像那么可以改为 <mirrorOf>*</mirrorOf>。
在我的项目中,由于一般会把central设置为我们的私服仓库,所以大部分情况下也就不用配置镜像了。如果确实有多个仓库的话,那确实可以用<mirrorOf>*</mirrorOf>的方式指向私服。

3.4 发布到仓库

<distributionManagement>
    <repository>
        <id>nexus</id>
        <name>releases</name>
        <url>http://localhost:8081/nexus/content/groups/public/</url>
    </repository>
    <snapshotRepository>
        <id>nexus</id>
        <name>snapshots</name>
        <url>http://localhost:8081/nexus/content/groups/public/</url>
    </snapshotRepository>
</distributionManagement>

四、插件

4.1 概述

4.2 生命周期

4.3 常见插件

4.4 例子

4.5 关于pluginManagement

这个标签跟dependencyManagement标签一样,也是为了起到统一管理的作用,只是它统一管理了插件。跟依赖管理一样,一般也会在parent父模块来配置pom来配置pluginManagement,统一描述好插件之后,在子模块中就不用完整的配置插件已经绑定的生命周期和执行目标等等,只需要指定插件的groupId 和 artifactId就可以完成插件的引用。下面给出例子。
父模块(parent模块)的pom.xml中配置:

<build>
    <pluginManagement>
        <plugins>
           <plugin>
              <groupId>org.apache.maven.plugins</groupId>
              <artifactId>maven-source-plugin</artifactId>
              <version>2.4</version>
              <executions>
                <execution>
                    <phase>package</phase>
                    <goals>
                        <goal>jar-no-fork</goal>
                    </goals>
                </execution>
              </executions>
            </plugin>
          </plugins>
    </pluginManagement>
    <!-- 如果父模块这里配置的话,则所有子模块都会引用该插件!!所以一般只用于通用插件。
    <plugins>  
       <plugin>
          <groupId>org.apache.maven.plugins</groupId>
          <artifactId>maven-source-plugin</artifactId>
       </plugin>
    </plugins>
    -->
</build>

其他子模块需要单独引用插件的,可以在pom.xml中配置:

<build>
    <plugins>
       <plugin>
          <groupId>org.apache.maven.plugins</groupId>
          <artifactId>maven-source-plugin</artifactId>
       </plugin>
    </plugins>
</build>

五、聚合和继承

5.1 继承

先说继承吧,其实继承就是为了抽出相同的东西,然后给项目的其他模块一起共用,而不用每个模块的pom.xml文件都写很多重复的东西。如果光说重复的工作量也就算了,有个重点是类似spring-core这种多个模块都可能用到的依赖,如果每个模块都自己配置自己的依赖和版本好,那很容易就会犯错或者依赖的版本不一致导致错误等等。因此,在拆分多模块开发的时候,尽量考虑使用继承。

如何使用Maven继承呢?
(1)建立一个文件夹,只创建一个pom.xml文件即可。
(2)然后把各个模块通用的东西写到这个pom.xml中,如属性定义,工厂定义,依赖坐标定义等等。
(3)把这个pom.xml中的<packaging>的值设置为pom。
(4)在各个子模块中使用<parent>标签指明自己使用的父项目。

关于父模块的依赖配置注意两点:
(1)一般都是通过<dependencyManagement>来配置所有依赖及其版本号,然后子模块,在自己的pom文件中声明依赖即可,不用再指定版本,以确保统一。
(2)父项目中什么时候直接配置<dependencies>呢?就是确定每个子模块基本都会用的依赖,统一配置,不用每个子模块再单独去配的,比如junit、log4j这种。

5.2 聚合

聚合的作用在于可以把一个项目的多个模块一起配置,这样可以一次性编译、安装和发布多个模块。
一般项目都会把聚合和继承都会放到同一个pom.xml文件进行管理。

如何使用Maven聚合呢?
(1)建立一个文件夹,只创建一个pom.xml文件。
(2)然后在这个pom.xml文件中,把这个pom.xml中的<packaging>的值设置为pom和配置<modules>标签即可。

如果其他模块跟父pom.xml是同一层的话,如下图:

则模块的配置方式为:

<modules>
    <module>hello-world</module>
    <module>hello-spring</module>
</modules>

六、插件开发

待更新

女装
文章评论