什么是Maven仓库

在不用Maven的时候,比如说以前我们用Ant构建项目,在项目目录下,往往会看到一个名为/lib的子目录,那里存放着各类第三方依赖jar文件,如log4j.jar,junit.jar等等。每建立一个项目,你都需要建立这样的一个/lib目录,然后复制一对jar文件,这是很明显的重复。重复永远是噩梦的起点,多个项目不共用相同的jar文件,不仅会造成磁盘资源的浪费,也使得版本的一致性管理变得困难。此外,如果你使用版本管理工具,如SVN(你没有使用版本管理工具?马上试试SVN吧,它能帮你解决很多头疼的问题),你需要将大量的jar文件提交到代码库里,可是版本管理工具在处理二进制文件方面并不出色。

Maven仓库就是放置所有JAR文件(WAR,ZIP,POM等等)的地方,所有Maven项目可以从同一个Maven仓库中获取自己所需要的依赖JAR,这节省了磁盘资源。此外,由于Maven仓库中所有的JAR都有其自己的坐标,该坐标告诉Maven它的组ID,构件ID,版本,打包方式等等,因此Maven项目可以方便的进行依赖版本管理。你也不在需要提交JAR文件到SCM仓库中,你可以建立一个组织层次的Maven仓库,供所有成员使用。

简言之,Maven仓库能帮助我们管理构件(主要是JAR)。

环境准备

官方下载地址: http://maven.apache.org/download.cgi

Windows安装

下载安装包apache-maven-3.5.4-bin.zip

解压到指定目录例如 C:\Program Files\Java\maven

添加环境变量

# 添加HOME和PATH
MAVEN_HOME=C:\maven3.6.1
PATH=C:\maven3.6.1\bin

Linux安装

# 上传到节点指定目录,添加环境变量:
export MAVEN_HOME=/opt/apache-maven-3.5.4
export PATH=${PATH}:${MAVEN_HOME}/bin

其他内容

M2_HOME = C:\Program Files\Java\apache-maven-3.5.0\bin
MAVEN_OPTS = -Xms128m -Xmx512m

自动下载的jar包一般存放在:位于 C:\Users\用户名.m2 目录。

使用中国源

编译maven项目时,会下载很多maven的插件,如果什么都没做的话,就会从默认的官网仓库地址下载。
为了加快访问速度,我们要把官网仓库地址替换为国内访问速度较快的镜像地址。
http://maven.aliyun.com/nexus/content/groups/public/

方法一

在settings.xml中找到,如下内容,将中央仓库(central)的默认地址设置为阿里云的地址。

  <mirrors>
 
    <!-- mirror
 
    | Specifies a repository mirror site to use instead of a given repository. The repository that
 
    | this mirror serves has an ID that matches the mirrorOf element of this mirror. IDs are used
 
    | for inheritance and direct lookup purposes, and must be unique across the set of mirrors.
 
    |
 
    <mirror>
 
      <id>mirrorId</id>
 
      <mirrorOf>repositoryId</mirrorOf>
 
      <name>Human Readable Name for this Mirror.</name>
 
      <url>http://my.repository.com/repo/path</url>
 
    </mirror>
 
    -->
 
    <mirror>
 
        <id>mirrorId</id>
 
        <mirrorOf>central</mirrorOf>
 
        <name>Human Readable Name for this Mirror.</name>
 
        <url>http://maven.aliyun.com/nexus/content/groups/public/</url>
 
    </mirror>
 
  </mirrors>

方法二:直接在项目的pom.xml上改

<repositories>
 
    <repository>
 
        <id>aliyun</id>
 
        <name>aliyun</name>
 
        <url>http://maven.aliyun.com/nexus/content/groups/public/</url>
 
        <layout>default</layout>
 
        <releases>
 
            <enabled>true</enabled>
 
            <updatePolicy>never</updatePolicy>
 
        </releases>
 
        <snapshots>
 
            <enabled>true</enabled>
 
            <updatePolicy>never</updatePolicy>
 
        </snapshots>
 
    </repository>
 
</repositories>
 
<pluginRepositories>
 
    <pluginRepository>
 
        <id>aliyun</id>
 
        <name>aliyun</name>
 
        <url>http://maven.aliyun.com/nexus/content/groups/public/</url>
 
        <releases>
 
            <enabled>true</enabled>
 
        </releases>
 
        <snapshots>
 
            <enabled>false</enabled>
 
        </snapshots>
 
    </pluginRepository>
 
</pluginRepositories>

配置pom.xml

<project>
 
    <groupId>com.oreilly.learningsparkexamples.mini</groupId>
 
    <artifactId>learning-spark-mini-example</artifactId>
 
    <modelVersion>4.0.0</modelVersion>   <!--pom模型版本,maven2和3只能为4.0.0-->
 
    <name>example</name>   <!--???-->
 
    <!-- 基本配置 -->
 
    <groupId>com.rexen.test</groupId>    <!--组ID,maven用于定位-->
 
    <artifactId>Test</artifactId>        <!--组中唯一ID,maven用于定位-->
 
    <version>1.0-SNAPSHOT</version>      <!--版本号-->
 
    <packaging>jar</packaging>           <!--打包方式 如:pom, jar, maven-plugin, ejb, war, ear, rar, par-->
 
    <!-- 用于定义pom常量 -->
 
    <properties>
 
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
 
        <spark.version>2.2.0</spark.version>   <!-- 这个常量可以在pom文件的任意地方通过${spark.version}来引用 -->
 
        <scala.version>2.10</scala.version>
 
        <hadoop.version>2.6.0</hadoop.version>
 
    </properties>
 
    <!-- 依赖配置 -->
 
    <repositories>
 
        <repository>
 
            <id>jboss</id>
 
            <name>Maven of jboss.org</name>
 
            <url>http://repository.jboss.org/nexus/content/groups/public/</url>
 
            <releases>
 
                <enabled>true</enabled>
 
            </releases>
 
            <snapshots>
 
                <enabled>true</enabled>
 
            </snapshots>
 
            <layout>default</layout>
 
        </repository>
 
    </repositories>
 
    <!-- 依赖配置 用于确定父项目的坐标 -->
 
    <parent>
 
        <groupId>com.rexen.learn</groupId>      <!--父项目的构件标识符-->
 
        <artifactId>test-parent</artifactId>    <!--父项目的唯一标识符-->
 
        <relativePath></relativePath>           <!--Maven首先在当前项目的找父项目的pom,在文件系统的这个位置(relativePath),后在本地仓库,最后在远程仓库找。-->
 
        <version>1.1-SNAPSHOT</version>         <!--父项目的版本-->
 
    </parent>
 
    <!-- 有些maven项目会做成多模块的,这个标签用于指定当前项目所包含的所有模块。之后对这个项目进行的maven操作,会让所有子模块也进行相同操作 -->
 
    <modules>
 
        <module>com-a</module>
 
        <module>com-b</module>
 
        <module>com-c</module>
 
    </modules>
 
    <!-- 项目相关依赖配置,如果在父项目写的依赖,会被子项目引用,一般父项目会将子项目公用的依赖引入,这边依赖和中央仓库中的一致,就可以引入对应的jar -->
 
    <dependencies>
 
        <dependency>
 
            <groupId>org.apache.spark</groupId>
 
            <artifactId>spark-core_2.10</artifactId>
 
            <version>1.6.3</version>
 
        </dependency>
 
    </dependencies>
 
    <!-- 配置写法同dependencies -->
 
    <dependencyManagement>...</dependencyManagement>
 
    <!-- 插入样例  在父模块中定义后,子模块不会直接使用对应依赖,但是在使用相同依赖的时候可以不加版本号,好处是,父项目统一了版本,而且子项目可以在需要的时候才引用对应的依赖 
 
    父项目:
 
    <dependencyManagement>
 
        <dependencies>
 
            <dependency>
 
                <groupId>junit</groupId>
 
                <artifactId>junit</artifactId>
 
                <version>4.12</version>
 
                <scope>test</scope>
 
            </dependency>
 
        </dependencies>
 
    </dependencyManagement>
 
    子项目:
 
    <dependency>
 
        <groupId>junit</groupId>
 
        <artifactId>junit</artifactId>
 
    </dependency>
 
    -->
 
    <!-- 构建配置 -->
 
    <build>
 
        <sourceDirectory>src/main</sourceDirectory>       <!--该元素设置了项目源码目录,当构建项目的时候,构建系统会编译目录里的源码。该路径是相对于pom.xml的相对路径。-->
 
        <scriptSourceDirectory/>                          <!--该元素设置了项目脚本源码目录,该目录和源码目录不同:绝大多数情况下,该目录下的内容 会被拷贝到输出目录(因为脚本是被解释的,而不是被编译的)。-->
 
        <testSourceDirectory/>                            <!--该元素设置了项目单元测试使用的源码目录,当测试项目的时候,构建系统会编译目录里的源码。该路径是相对于pom.xml的相对路径。-->
 
        <outputDirectory/>                                <!--被编译过的应用程序class文件存放的目录。-->
 
        <testOutputDirectory/>                            <!--被编译过的测试class文件存放的目录。-->
 
        <extensions>      <!--使用来自该项目的一系列构建扩展-->
 
            <extension>   <!--描述使用到的构建扩展。-->
 
                <groupId/>    <!--构建扩展的groupId-->
 
                <artifactId/> <!--构建扩展的artifactId-->
 
                <version/>    <!--构建扩展的版本-->
 
            </extension>
 
        </extensions>
 
        <defaultGoal/>    <!--当项目没有规定目标(Maven2 叫做阶段)时的默认值-->
 
        <resources>                                      <!--这个元素描述了项目相关的所有资源路径列表,例如和项目相关的属性文件,这些资源被包含在最终的打包文件里。-->
 
            <resource>                                   <!--这个元素描述了项目相关或测试相关的所有资源路径-->
 
                <targetPath/>                            <!-- 描述了资源的目标路径。该路径相对target/classes目录(例如${project.build.outputDirectory})。
 
                                                         举个例 子,如果你想资源在特定的包里(org.apache.maven.messages),你就必须该元素设置为org/apache/maven /messages。然而,如果你只是想把资源放到源码目录结构里,就不需要该配置。-->
 
                <filtering>true</filtering>              <!--是否使用参数值代替参数名。参数值取自properties元素或者文件里配置的属性,文件在filters元素里列出。-->
 
                <directory>src/main/java</directory>     <!--描述存放资源的目录,该路径相对POM路径-->
 
                <includes>                               <!--包含的模式列表,例如**/*.xml.-->
 
                    <include>*.*</include>
 
                </includes>
 
                <excludes/>                              <!--排除的模式列表,例如**/*.xml-->
 
            </resource>
 
        </resources>
 
        <testResources>                            <!--这个元素描述了单元测试相关的所有资源路径,例如和单元测试相关的属性文件。-->
 
            <testResource>
 
                <targetPath/>                      <!--这个元素描述了测试相关的所有资源路径,参见build/resources/resource元素的说明-->
 
                <filtering/>
 
                <directory/>
 
                <includes/>
 
                <excludes/>
 
            </testResource>
 
        </testResources>
 
        <directory/>    <!--构建产生的所有文件存放的目录-->
 
        <finalName/>    <!--产生的构件的文件名,默认值是${artifactId}-${version}。-->
 
        <filters/>        <!--当filtering开关打开时,使用到的过滤器属性文件列表-->
 
        <pluginManagement>        <!--子项目可以引用的默认插件信息。该插件配置项直到被引用时才会被解析或绑定到生命周期。给定插件的任何本地配置都会覆盖这里的配置-->
 
            <plugins>             <!--使用的插件列表 。-->
 
                <plugin>          <!--plugin元素包含描述插件所需要的信息。-->
 
                    <groupId/>    <!--插件在仓库里的group ID-->
 
                    <artifactId/><!--插件在仓库里的artifact ID-->
 
                    <version/><!--被使用的插件的版本(或版本范围)-->
 
                    <extensions/><!--是否从该插件下载Maven扩展(例如打包和类型处理器),由于性能原因,只有在真需要下载时,该元素才被设置成enabled。-->
 
                    <executions><!--在构建生命周期中执行一组目标的配置。每个目标可能有不同的配置。-->
 
                        <execution><!--execution元素包含了插件执行需要的信息-->
 
                            <id/><!--执行目标的标识符,用于标识构建过程中的目标,或者匹配继承过程中需要合并的执行目标-->
 
                            <phase/><!--绑定了目标的构建生命周期阶段,如果省略,目标会被绑定到源数据里配置的默认阶段-->
 
                            <goals/><!--配置的执行目标-->
 
                            <inherited/><!--配置是否被传播到子POM-->
 
                            <configuration/><!--作为DOM对象的配置-->
 
                        </execution>
 
                    </executions>
 
                    <dependencies><!--项目引入插件所需要的额外依赖-->
 
                        <dependency><!--参见dependencies/dependency元素-->
 
                        </dependency>
 
                    </dependencies>
 
                    <inherited/><!--任何配置是否被传播到子项目-->
 
                    <configuration/><!--作为DOM对象的配置-->
 
                </plugin>
 
            </plugins>
 
        </pluginManagement>
 
        <plugins> <!--使用的插件列表-->
 
            <plugin>
 
                <!-- 这是个编译java代码的 -->
 
                <groupId>org.apache.maven.plugins</groupId>
 
                <artifactId>maven-compiler-plugin</artifactId>
 
                <version>3.2</version>
 
                <configuration>
 
                    <source>1.7</source>
 
                    <target>1.7</target>
 
                    <encoding>UTF-8</encoding>
 
                </configuration>
 
                <executions>
 
                    <execution>
 
                        <phase>compile</phase>
 
                        <goals>
 
                            <goal>compile</goal>
 
                        </goals>
 
                    </execution>
 
                </executions>
 
            </plugin>
 
            <plugin>
 
                <!-- 这是个编译scala代码的 -->
 
                <groupId>net.alchim31.maven</groupId>
 
                <artifactId>scala-maven-plugin</artifactId>
 
                <version>3.2.1</version>
 
                <executions>
 
                    <execution>
 
                        <id>scala-compile-first</id>
 
                        <phase>process-resources</phase>
 
                        <goals>
 
                            <goal>add-source</goal>
 
                            <goal>compile</goal>
 
                        </goals>
 
                    </execution>
 
                </executions>
 
            </plugin>
 
            <plugin>
 
                <groupId>org.apache.maven.plugins</groupId>
 
                <artifactId>maven-shade-plugin</artifactId>
 
                <version>1.4</version>
 
                <executions>
 
                    <execution>
 
                        <phase>package</phase>
 
                        <goals>
 
                            <goal>shade</goal>
 
                        </goals>
 
                        <configuration>
 
                            <filters>
 
                                <filter>
 
                                    <artifact>*:*</artifact>
 
                                    <excludes>
 
                                        <exclude>META-INF/*.SF</exclude>
 
                                        <exclude>META-INF/*.DSA</exclude>
 
                                        <exclude>META-INF/*.RSA</exclude>
 
                                    </excludes>
 
                                </filter>
 
                            </filters>
 
                            <transformers>
 
                                <transformer
 
                                        implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
 
                                    <mainClass>com.oreilly.learningsparkexamples.mini.scala.WordCount</mainClass>
 
                                </transformer>
 
                            </transformers>
 
                        </configuration>
 
                    </execution>
 
                </executions>
 
            </plugin>
 
        </plugins>
 
    </build>
 
    <reporting>    <!--该元素描述使用报表插件产生报表的规范。当用户执行“mvn site”,这些报表就会运行。 在页面导航栏能看到所有报表的链接。-->
 
        <excludeDefaults/><!--true,则,网站不包括默认的报表。这包括“项目信息”菜单中的报表。-->
 
        <outputDirectory/><!--所有产生的报表存放到哪里。默认值是${project.build.directory}/site。-->
 
        <plugins><!--使用的报表插件和他们的配置。-->
 
            <plugin><!--plugin元素包含描述报表插件需要的信息-->
 
                <groupId/><!--报表插件在仓库里的group ID-->
 
                <artifactId/><!--报表插件在仓库里的artifact ID-->
 
                <version/><!--被使用的报表插件的版本(或版本范围)-->
 
                <inherited/><!--任何配置是否被传播到子项目-->
                <configuration/><!--报表插件的配置-->
                <reportSets><!--一组报表的多重规范,每个规范可能有不同的配置。一个规范(报表集)对应一个执行目标 。例如,有1,2,3,4,5,6,7,8,9个报表。1,2,5构成A报表集,对应一个执行目标。2,5,8构成B报表集,对应另一个执行目标-->
                    <reportSet><!--表示报表的一个集合,以及产生该集合的配置-->
                        <id/><!--报表集合的唯一标识符,POM继承时用到-->
                        <configuration/><!--产生报表集合时,被使用的报表的配置-->
                        <inherited/><!--配置是否被继承到子POMs-->
                        <reports/><!--这个集合里使用到哪些报表-->
                    </reportSet>
                </reportSets>
            </plugin>
        </plugins>
    </reporting>
</project>
 

参考文档

http://www.yiibai.com/maven/
http://mvnrepository.com/
http://maven.apache.org/pom.html