JAVA学习之maven的使用


场景 : 最近使用springboot写一些小demo,发现到处都要使用maven,更离不开其中的pom.xml文件,所以这里对maven的常规使用作出一个整理。

转载自 : 本文很多内容都是仿照 http://www.cnblogs.com/qbzf-Blog/p/6539161.html 来的。而且他还提供了一个慕课网的学习视频:http://www.imooc.com/learn/443


 

文章结构 : 

1. 安装配置maven环境

2. maven目录结构

3. HelloMaven

4. 常用构建命令

5. 使用archetype插件自动建立目录

6. 坐标&仓库

7. 生命周期&插件的使用

8. pom.xml常用标签介绍

9. maven依赖(范围、传递、冲突)

10. 聚合&继承

 

 


 

正文 : 

 1. 安装配置maven环境

首先,在官网中下载maven组件。进入官网后,在左边菜单找到Download选项,点击进入Download页面。   

  

 

  

 

当然,我们首先要保证JDK安装好。接下来,要在本地配置好maven的系统环境变量,

   

新建一个maven_home的变量,然后在系统变量的path后面追加这个maven_home;

   

接着,我们测试下maven安装成功没有(注意,一般我们都先安装好JDK,因为maven的命令应该是要借助jdk的):

  

如图所示,显示了maven的版本信息跟jdk的版本信息,当然,我们也可以使用echo 查看下 系统环境变量 :

  

 到这里,我们对maven的环境配置就完成了。其实这是第一种,我们下载jar包的形式,不过本人是使用第二种,直接安装eclipse(包含maven)的版本即可,

  

比如我安装的版本即是自带的maven;接下来只需要配置好本地的系统变量即可。

 诶,如果我们想要改变maven的版本呢,我们可以在eclipse当中的preferences当中改变:

  

 

2.  maven项目的目录结构 

       先在这里插入一点个人对maven的理解,我们之前每个项目都需要有自己的jar包,但是这么多jar包很多有相同的,而这些jar包又是基于项目存放的,如果我们跨越项目这一层,统一管理jar包呢, 这样不就可以节约很多空间和时间。所以,我们使用maven工具来支配之,那么我们maven存放jar包的地方就是我们说的仓库,

 当我们在第一步设置好maven的环境之后,默认就在c盘的user目录下的.m2文件夹充当仓库。  

   a

 

        maven在每台机器上创建一个本机仓库,把本机上所有maven项目依赖的jar包统一管理起来,而且这些jar包用“坐标”来唯一标识(注:坐标是另一个重要的概念,后面还会讲到,这里只要简单理解成“唯一识别某个jar包文件名、版本号”的标识即可),这样所有maven项目就不需要再象以前那样把jar包复制到lib目录中,整个maven项目看起来十分清爽。 

扯了很多,现在说下maven项目的目录结构是怎样的 : 

          

 诶,这些有些怎么标红呢? 是因为我们使用maven约定由于配置。src/main/java约定用于存放源代码,src/main/test用于存放单元测试代码,src/target用于存放编译、打包后的输出文件。这是全世界maven项目的通用约定,请记住这些固定的目录结构。

3. 构建一个HelloMaven项目

      上面介绍完了我们该使用怎样的约定来开发一个项目,接下来我们创建一个项目。

   

new一个maven项目,写好坐标(待会介绍)。这里说的坐标就是上面的groupid以及artifact id。创建好之后的结构如下图所示:

   

       接下来我们尝试编译下这个项目,命令行进入项目路径,使用mvn compile命令(当然,直接在eclipse上run as这个项目使用maven的几个选项都是可以的)。编译之后会生成target目录,里面存放的是class文件 : 

  

我们接下来编译下 : 

     

      

我们查看下项目目录 : 

    

 我们这里在maven项目的测试类中写个syso输出 : 

 

 OK,我们再在控制台输入mvn clean ,清理下class文件,再输入mvn compile 再次编译一下,接着输入mvn test执行AppTest.class文件:

  

 

我们可以看到已经输出成功了。

4. 常用构建命令  

      从第3步骤可以看出,这些命令的使用了,其实很像使用java命令编译对不对。那么我们来介绍下maven的这些构建命令 : 其形式一般都是在命令行 mvn xxx的这种格式 : 

mvn    {

                     -v 查看maven版本以及其他相关信息

      compile 编译maven项目,并生成target文件夹

      test 运行test目录下的测试文件,即测试

      package 将项目打包,默认打包为jar格式,也可以打包成war格式用于服务器运行

                     install 将打包的jar文件安装到maven本地仓库

                     clean 删除target,相当于清除缓存

           }

 这些命令在集成了maven的eclipse当中也有对应选项可以操作 : 

  

 我们可以右键一个项目,然后run as 就会出现这些选项,在下面的maven当中 还有update选项;

    那这么多命令,我们怎么知道怎么合理使用呢,其实我们只需要理解到整个项目的构建过程就可以明白这一点了:

项目构建过程包括【清理项目】→【编译项目】→【测试项目】→【生成测试报告】→【打包项目】→【部署项目】这几个步骤,这六个步骤就是一个项目的完整构建过程。(mvn clean  -> mvn compile  -> mvn test -> mvn package)

    而上面所说的maven update是针对我们在项目中的pom.xml当中引入了新的jar包之后,需要重新update一下,此处的应用场景就是 :

比如我们A项目在pom.xml引入了一个新包,这个时候我们需要把A项目重新update一下才能使用新jar包当中的东西(不过很多时候我们项目有自动重构);如果这个时候我们B项目引用了A,也想使用这个新jar包,我们也应当update一下,避免发生引用错误,还有一个常见的使用场景就是我们import一个新的maven聚合项目的时候,需要clean install :

     

然后我们还要update把jar包下下来,这个时候如果依赖包过多,其下载是相当大的,所以我们可以指定maven仓库的位置为阿里的(更改setting文件后面作出介绍。)

下面我列举一下常用的maven 命令(注意我上面在eclipse当中不是maven clean 而是clean,原因吗我也不知道啦):

  • 创建一个简单的Java工程:mvn archetype:create -DgroupId=com.mycompany.example -DartifactId=Example
  • 创 建一个java的web工程:mvn archetype:create -DarchetypeGroupId=org.apache.maven.archetypes -DarchetypeArtifactId=maven-archetype-webapp -DgroupId=com.mycompany.app -DartifactId=my-webapp
  • 打包:mvn package
  • 编译:mvn compile
  • 编译测试程序:mvn test-compile
  • 清空:mvn clean
  • 运行测试:mvn test
  • 生成站点目录: mvn site
  • 生成站点目录并发布:mvn site-deploy
  • 安装当前工程的输出文件到本地仓库: mvn install
  • 安 装指定文件到本地仓库:mvn install:install-file -DgroupId=<groupId> -DartifactId=<artifactId> -Dversion=1.0.0 -Dpackaging=jar -Dfile=<myfile.jar>
  • 查看实际pom信息: mvn help:effective-pom
  • 分析项目的依赖信息:mvn dependency:analyze 或 mvn dependency:tree
  • 跳过测试运行maven任务:    mvn -Dmaven.test.skip=true XXX
  • 生成eclipse项目文件: mvn eclipse:eclipse (将maven项目转换成eclipse项目)
  • 查看帮助信息:mvn help:help 或 mvn help:help -Ddetail=true
  • 查看插件的帮助信息:mvn <plug-in>:help,比如:mvn dependency:help 或 mvn ant:help 等等。

      这里我还想多说一点,其实maven的功能不仅仅是这样,如下我列举一些maven的常用基本功能 :

      (转载自 https://www.cnblogs.com/adolfmc/archive/2012/07/31/2616908.html)

  • 构建:比如生成class、jar、war或者ear文件
  • 生成文档:比如生成javadoc、网站文档
  • 生成报告:比如junit测试报告
  • 生成依赖类库:生成文档,说明项目多其他软件的依赖
  • 有关SCM:SCM(Software Configuration Management),软件配置管理,比如版本控制,比如bug管理等等
  • 发布:生成供发布的分发包,比如生成Struts2的分发包,供提交给用户使用
  • 部署:比如,web应用程序,自动部署到指定的服务器上
  • Maven资源

     

 5.使用archetype插件自动建立目录

      这个本人不作出介绍了,哈哈,没用过。

6. 坐标和仓库

  坐标 :

   maven使用groupId、artifactId、version表示坐标,每个坐标都唯一的指向一个maven项目,简单介绍一下这几个标签

      groupId:项目组织唯一的标识符,一般为反写的公司网址+项目名
      artifactId:项目的唯一的标识符,一般为项目名+模块名
      version:版本号 x.x.x+版本类型
        第一个x表示大版本号
        第二个x表示分支版本号
        第三个x表示小版本号(可省略)
        常见版本类型:
          snapshot快照
          alpha内部测试
          beta公测
          release稳定
          GA正式发布

      注:包名应与groupId+artifactId相吻合。

       仓库 : maven的依赖管理是靠着仓库来支撑的,仓库分为中央仓库和本地仓库。在编译项目时,maven会根据配置的依赖,现在本地仓库中进行搜索,若是没有则再去仓库进行搜索,而搜索便是采用坐标进行查找。仓库默认为本地的c盘users文件夹下面的.m2的repository。如果不想放在C盘的话,可以对maven进行配置:

   

         如图,可以自己重写localRepository;

7. 生命周期 & 插件的使用

      多个生命周期之间相互独立。每个生命周期含有多个阶段,阶段按顺序执行,运行后阶段时,前阶段会自动执行。比如,直接运行mvn test命令,那么执行该命令时,会自动的附带mvn compile命令,因为test阶段在compile阶段之后。

       上面我们就说过,一个完整的项目的构建过程包括 : 

        清理、编译、测试、打包、集成测试、验证、部署;

         clean 清理项目,包括以下阶段:
      pre-clean 执行清理前
      clean 清理上一次构建生成的所有文件
      post-clean 执行清理后的文件
    default 构建项目(核心:常用),包括以下阶段
      compile 编译
      test 测试
      packeage 打包
      install 安装
    site 生成项目站点,根据pom中信息生成项目站点,包括以下阶段
      pre-site 在生成项目站点前要完成的工作
      site生成项目的站点文档
      post-site在生成项目站点后要完成的工作
      site-deploy发布生成的站点到服务器上

插件:

    maven中提供了许多功能强大的插件,让我们更好的管理项目。一个插件通常提供了一组目标,可使用以下语法来执行:

      mvn [plugin-name]:[goal-name]
   例如我们之前使用mvn archetype:generate,插件名为archetype,而目标为generate。我们可以在官网的Plugins标签下,查找到插件的坐标及插件目标的详细描述。
   Maven 提供以下两种类型插件:
类型 描述
构建插件 在生成过程中执行,并在 pom.xml 中的<build/> 元素进行配置
报告插件 在网站生成期间执行,在 pom.xml 中的 <reporting/> 元素进行配置

     

以下是一些常见的插件列表:

插件 描述
clean 编译后的清理目标,删除目标目录
compiler 编译 Java 源文件
surefile 运行JUnit单元测试,创建测试报告
jar 从当前项目构建 JAR 文件
war 从当前项目构建 WAR 文件
javadoc 产生用于该项目的 Javadoc
antrun 从构建所述的任何阶段运行一组 Ant 任务
source 从当前项目构建带源码的JAR文件

比如我们拿source来测试:

<build>
<!-- 配置插件集 -->
<plugins>
<plugin>
<!--使用插件的坐标进行引用 -->
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>3.0.0</version>

<executions>
<execution>
<!-- 绑定在哪个过程时一同执行,这里我们让它在使用package打包时一同执行 -->
<phase>package</phase>
<!--执行的目标类型,关于目标的详细介绍可以在maven官网中查到-->
<goals>
<goal>jar-no-fork</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>

我们接下来先编译一下 :

 

然后,我们在来看使用打包命令之后会不会生成源jar包。

 

 我们可以看到在下载很多东西了 ,接下来看下文件夹生成了源jar包没 : 

从这里我们可看成,这里有几个关键点,在pom.xml当中使用plugin来申明要使用的插件,然后还可以绑定到某个过程中执行,我们这里就绑定到了package当中执行。

8. 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">
<!-- 当前pom的版本-->
<modelVersion>4.0.0</modelVersion>

<!--坐标-->
<groupId>cn.edu</groupId>
<artifactId>maven04</artifactId>
<version>0.0.1-SNAPSHOT</version>
<!-- 默认是jar,其他war zip pom等 -->
<packaging>jar</packaging>

<!--项目描述名 -->
<name>maven04</name>
<!-- 项目地址 -->
<url>http://maven.apache.org</url>

<!-- 配置参数 -->
<properties>
<!-- 这里配置项目编译编码为UTF-8-->
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>

<!-- 开发人员信息 -->
<developers></developers>
<!-- 项目描述 -->
<description></description>
<!-- 许可信息 -->
<licenses></licenses>
<!-- 组织信息 -->
<organization></organization>
<!-- 依赖集,用于配置依赖 -->
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>

<!-- 依赖范围:这个jar包只在范围内生效,范围外引用会报错,这里让junit只在test时被依赖。
其他一些情况,如:servlet-api.jar,在编译阶段需要引用,而在服务器运行阶段则不需要引用,就可以使用scope-->
<scope>test</scope>

<!-- 默认为false,子项目将会继承,true时子项目并需显式引用 -->
<optional>false</optional>

<!-- 排除依赖列表:用于去除传递依赖等,在后面会详细介绍-->
<exclusions>
<exclusion></exclusion>
</exclusions>

</dependency>
</dependencies>

<!-- 依赖管理
为依赖进行统一管理,如果在父项目中声明此标签时,在子项目中不需声明,确保父子项目依赖版本一致;
如子项目需要不同版本的依赖,只需在子项目中进行声明即可,将会覆盖父项目中的声明。
-->
<!--
<dependencyManagement>
<dependencies>
<dependency></dependency>
</dependencies>
</dependencyManagement>
-->

<!--配置构建时的属性-->
<build>
<plugins></plugins>
</build>

<!-- 指定父模块 -->
<!-- <parent></parent> -->

<!-- 用于聚合编译多个maven模块 -->
<modules></modules>
</project>

9. maven依赖 (范围、传递、冲突)

范围:   

    首先要知道,maven中提供了三种classpath:编译、测试、运行
    scope标签
      -compile 默认,编译测试运行均有效,会传递
      -provided 在编译和测试时有效,如servletAPI可以加入,不传递
      -runtime 在测试和运行时有效,如JDBCAPI可以加入
      -test 在测试时有效,如junit可以加入
      -system 在编译和测试时有效,与本机系统相关联,移植性差,在系统中以外部jar包的形式引入,不会在仓库中查找
      -import 导入,只能用在dependecyManagement中,表示从其他pom中导入dependecy的配置

  传递:

    先来看看什么是传递依赖,比如现在有这么个情况:

    C依赖B、B依赖A——C→B→A,那么此时C也会依赖A且会包含A中的依赖,这就是传递依赖。接下来我们通过一个例子来详细了解依赖及如何消除传递依赖:

    现有ABC三个项目:

    

  A中额外依赖了一个commons-io的jar包:

  

  B中对A进行依赖:

  

  C中对B进行依赖:

  

  保存之后可以看到,C中不但包含B,还包含A和A依赖的common-io:

  

  那么如何消除传递依赖呢,这里就使用到<exclusion>标签了,在C中配置依赖B的地方加入以下内容:

  

  保存后就可以看到,C中关于A的依赖消失了,传递依赖的问题就解决了。

   

冲突:

    假设现在有这么个情况:A依赖common-io的2.4版本,B依赖common-io的2.5版本,C依赖A、B,那么此时C中的common-io是哪个版本的?

    这就是依赖冲突,在maven中应对依赖冲突有两种解决方式:短路优先,先声明优先

      先声明优先:顾名思义,在pom中,写在配置文件上面的优先,比如此时A的依赖配置在B之上,那C中就为2.4版本的common-io。

      短路优先:优先选择依赖路径较短的一端。假设现在多出一个D,依赖情况改为D依赖B,C依赖A、D——C→A、C→D→B,那么这里就是A的依赖路径比较短,所以为2.4版本。

10. 聚合&继承

     

聚合:

    试想一下这样的情况,在一个项目中,分模块使用了maven,那么可能在这个项目中会有五六个,或者更多的maven项目存在。如果此时需要编译或测试要怎么办呢,进入每个maven项目中进行mvn compile么,那就要执行五六次的compile命令,十分繁琐,这里就可以用maven的聚合来解决这个问题。

    现有ABC三个工程,那么我们使用一个新的工程D,来聚合他们,以后只要对D进行编译即可对三个工程同时进行编译。使用module标签进行聚合:

     

  <modules>
    <!--这里的路径是基于D项目的pom.xml路径,module标签内为指向其他项目的pom文件的路径
        这里我的ABCD项目在同一个文件夹内,那么从D内的pom中,通过../项目名,来找到其他项目的pom.xml-->
      <module>../A</module>
      <module>../B</module>
      <module>../C</module>
  </modules>

继承:

    另一种情形,如果多个maven项目具有相同的依赖时或配置时,那么应该如何处理呢?这里就用到继承的概念,在maven中使用<parent>标签来进行继承,下面通过一个例子来看一下:

    首先建立一个项目,命名为parent,在parent的pom文件声明一个common-io的依赖,不过这里用到了dependencyManagement:

 

<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>cn.edu</groupId>
    <artifactId>parent</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>pom</packaging>

    <name>parent</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>4.12</version>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <dependencyManagement>
        <!-- 在这里声明的依赖可以被子项目继承引用 -->
        <dependencies>
            <dependency>
                <groupId>commons-io</groupId>
                <artifactId>commons-io</artifactId>
                <version>2.4</version>
            </dependency>
        </dependencies>
    </dependencyManagement>
</project>
可以看到,虽然我们在父项目中配置了依赖,但是却不会在父项目中被引用:

 

  在子项目B中,配置继承parent并使用parent中的common-io版本:

<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>cn.edu</groupId>
    <artifactId>B</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>

    <name>B</name>
    <url>http://maven.apache.org</url>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <!-- 在parent标签中使用父项目的坐标进行配置 -->
     <parent>
          <groupId>cn.edu</groupId> 
          <artifactId>parent</artifactId> 
        <version>0.0.1-SNAPSHOT</version> 
    </parent>
    
    <dependencies>
        <!-- 此处使用依赖时,就不需声明版本 -->
        <dependency> 
            <groupId>commons-io</groupId> 
            <artifactId>commons-io</artifactId> 
        </dependency>
        
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
    </dependencies>
</project>

配置后保存即可看到,此处的依赖版本即为父项目中的版本:

  

 


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM