zoukankan      html  css  js  c++  java
  • Maven入门

      有用过Maven,但是一直都不知道是什么~被人一问,发现好像有点东西。随口一说是管理Jar包的,一般都是复制粘贴的。却被人说是啊是啊,但是复制粘贴是别人的又不是你的。说的好像jar包就是自己的一样(白眼.jpg)。——fzj

    一.Maven的作用:

      是一个项目管理工具。跨平台对外提供了一直的操作接口。统一开发规范与工具,统一管理jar包,还能自动下载构件。

    二.安装:

      链接放这里:https://www.cnblogs.com/zhaoyang/archive/2012/01/07/2315443.html(Maven的安装与配置)

    三.Maven 目录:

      bin目录:该目录包含了mvn运行的脚本,这些脚本用来配置Java命令,准备好classpath和相关的Java系统属性,然后执行Java命令。

      boot目录:该目录质保函一个文件,名字为plexus-classworlds-2.6.0.jar,是一个类加载器框架,相对于默认的Java类加载器,它提供了更加丰富的语法以及方便配置,Maven使用该框架加载自己的类库。

      conf目录:该目录包含了一个非常重要的配置文件叫settings.xml。直接修改该文件,就能在电脑上全局地定制Maven的行为。一般都是复制一份在桌面上,用记事本打开,然后修改,然后替换以前那一份。

      lib目录:该目录包含了所有Maven运行时需要的Java类库,需要用到的第三方依赖等。

    四.pom.xml

      这才是Maven最核心的东西,很有必要去解析一下。

    打开pom.xml,你可以看到原始的

     1 <project xmlns="http://maven.apache.org/POM/4.0.0" 
     2 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
     3 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
     4   <modelVersion>4.0.0</modelVersion>
     5   <groupId>com.baidu</groupId>
     6   <artifactId>MavenProject</artifactId>
     7   <version>0.0.1-SNAPSHOT</version>
     8   <packaging>war</packaging>
     9  <dependencies>
    10   <dependency>
    11       <groupId>ch.inftec.ju</groupId>
    12       <artifactId>ju-dbutil-test-mysql</artifactId>
    13       <version>4.1</version>
    14   </dependency>
    15  </dependencies>
    16 </project>

      第1~3行就是一些简单的声明,xml文件都有的

      第4行,modelVersion 是指定了当前的Maven模型的版本号,对于Maven2和Maven3来说,它只能是4.0.0

      第5行,groupId 这个应该是公司名或是组织名。一般来说groupId是由三个部分组成,每个部分之间以"."分隔,第一部分是项目用途,比如用于商业的就是"com",用于非营利性组织的就是"org";第二部分是公司名,比如"tengxun"、"baidu"、"alibaba";第三部分是你的项目名

      第6行,artifactId 可以认为是Maven构建的项目名,比如你的项目中有子项目,就可以使用"项目名-子项目名"的命名方式

      第7行,version 这个是版本号,SNAPSHOT意为快照,说明该项目还在开发中,是不稳定的版本。

    注意,在Maven中,groupId、artifactId、version三个元素生成了一个Maven项目的基本坐标。

      第8行,packing 项目打包的类型,可以使用jar、war、rar、ear、pom,默认是jar。

    dependencies和dependency:

      前者包含后者。前面说了,Maven的一个重要作用就是统一管理jar包,为了一个项目可以build或运行,项目中不可避免的,会依赖很多其他的jar包,在Maven中,这些依赖就被称为dependency。

      这里引入一个概念,就是本地仓库远程仓库

      官方下载的本地仓库的配置存放在"%MAVEN_HOME%confsettings.xml"里面,找一下"localRepository"就可以了;

      MyEclipse默认的本地仓库的地址在"{user.home}/.m2/repository"路径下,同样找一下"localRepository"就可以找到MyEclipse默认的本地仓库了。

      本地仓库和远程仓库是这样的,Maven工程首先会从本地仓库中获取jar包,当无法获取指定jar包时,本地仓库会从远程仓库(中央仓库)中下载jar包,并放入本地仓库以备将来使用

    properties

      properties是用来定义一些配置属性的,例如project.build.sourceEncoding(项目构建源码编码方式),可以设置为UTF-8,防止中文乱码,也可定义相关构建版本号,便于日后统一升级。

    build

      build表示与构建相关的配置,比如build下有finalName,表示的就是最终构建之后的名称。

    接着解释一下Maven的目录结构

    • main目录下是项目的主要代码,test目录下存放测试相关的代码
    • 编译输出后的代码会放在target目录下
    • src/main/java下存放Java代码,src/main/resources下存放配置文件
    • 这里没有webapp,Web项目会有webapp目录,webapp下存放Web应用相关代码
    • pom.xml是Maven项目的配置文件

    关于依赖的配置:这里引 嘟嘟独立 的一张图:

      我觉得这个图片可真直观~厉害厉害

    下面讲讲依赖范围(即<scope>)

      是什么?

       maven 项目在不同的阶段引入到classpath中的依赖是不同的,例如,编译时,maven 会将与编译相关的依赖引入classpath中,测试时,maven会将测试相关的的依赖引入到classpath中,运行时,maven会将与运行相关的依赖引入classpath中,而依赖范围就是用来控制依赖于这三种classpath的关系。总结起来就是三种:编译classpath,测试classpath、运行classpath。

      有什么?有好几种呢。

        compile(编译依赖范围)、test(测试依赖范围)、provided(已提供依赖范围)、

        runtime(运行时依赖范围)、system(系统依赖范围)、import(引入依赖范围)

      怎么用?

      1)编译依赖范围(compile),该范围就是默认依赖范围,此依赖范围对 于编译、测试、运行三种classpath都有效,举个简单的例子,假如项目中有spring-core的依赖,那么spring-core不管是在编译,测试,还是运行都会被用到,因此spring-core必须是编译范围(构件默认的是编译范围,所以依赖范围是编译范围的无须显示指定)

         <dependency>
         <groupId>org.springframework</groupId>
         <artifactId>spring-core</artifactId>
         <version>2.5</version>
         <scope>compile</scope> <!--默认为该依赖范围,无须显示指定--〉
        </dependency>

      2)测试依赖范围(test),顾名思义就是针对于测试的,使用此依赖范围的依赖,只对测试classpath有效,在编译主代码和项目运行时,都将无法使用该依赖,最典型的例子就是 Junit, 构件在测试时才需要,所以它的依赖范围是测试,因此它的依赖范围需要显示指定为<scope>test</scope> ,当然不显示指定依赖范围也不会报错,但是该依赖会被加入到编译和运行的classpath中,造成不必要的浪费 。

     <dependency>
         <groupId>junit</groupId>
         <artifactId>junit</artifactId>
         <version>4.7</version>
        <scope>test</scope>
        </dependency>

      3)已提供依赖范围(provided),使用该依赖范围的maven依赖,只对编译和测试的classpath有效,对运行的classpath无效,典型的例子就是servlet-api, 编译和测试该项目的时候需要该依赖,但是在运行时,web容器已经提供的该依赖,所以运行时就不再需要此依赖,如果不显示指定该依赖范围,并且容器依赖的版本和maven依赖的版本不一致的话,可能会引起版本冲突,造成不良影响。

     <dependency>
         <groupId>javax-servlet</groupId>
         <artifactId>servlet-api</artifactId>
         <version>2.0</version>
        <scope>provided</scope>
        </dependency>

      4)运行时依赖范围(runtime),使用该依赖范围的maven依赖,只对测试和运行的classpath有效,对编译的classpath无效,典型例子就是JDBC的驱动实现,项目主代码编译的时候只需要JDK提供的JDBC接口,只有在测试和运行的时候才需要实现上述接口的具体JDBC驱动。

      5)系统依赖范围(system),该依赖与classpath的关系与 provided依赖范围完全一致,但是系统依赖范围必须通过配置systemPath元素来显示指定依赖文件的路径,此类依赖不是由maven仓库解析的,而且往往与本机系统绑定,可能造成构件的不可移植,因此谨慎使用,systemPath元素可以引用环境变量:

        <dependency>
        <groupId>javax.sql</groupId>
        <artifactId>jdbc-stext</artifactId>
        <version>2.0</version>
        <scope>system</scope>
        <systemPath>${java.home}/lib/rt.jar</systemPath> 
        </dependency>

      6)导入依赖范围(import),该依赖范围不会对三种classpath产生影响,该依赖范围只能与dependencyManagement元素配合使用,其功能为将目标pom文件中dependencyManagement的配置导入合并到当前pom的dependencyManagement中。

    这里又引 嘟嘟独立 的一张图:(除import以外的各种依赖范围与三种classpath的关系如下:)

     Maven传递性依赖(Optional Dependencies):

      是什么?

        当一个项目A依赖另一个项目B时,项目A可能很少一部分功能用到了项目B,此时就可以在A中配置对B的可选依赖。举例来说,一个类似hibernate的项目,它支持对mysql、oracle等各种数据库的支持,但是在引用这个项目时,我们可能只用到其对mysql的支持,此时就可以在这个项目中配置可选依赖。

        简单来说就是:A-->B,B-->C   ==   A-->C。配置可选依赖的原因:1、节约磁盘、内存等空间;2、避免license许可问题;3、避免类路径问题,等等。

        有了传递性依赖机制,在使用Spring Framework的时候就不用去考虑它依赖了什么,也不用担心引入多余的依赖。Maven会解析各个直接依赖的POM,将那些必要的间接依赖,以传递性依赖的形式引入到当前的项目中。

        

    依赖范

      假设A依赖于B,B依赖于C,我们说A对于B是第一直接依赖,B对于C是第二直接依赖,A对于C是传递性依赖。第一直接依赖和第二直接依赖的范围决定了传递性依赖的范围,如下图所示,最左边一行表示第一直接依赖范围,最上面一行表示第二直接依赖范围,中间的交叉单元格则表示传递依赖范围。

    从上图中,我们可以发现这样的规律:

    • 当第二直接依赖的范围是compile的时候,传递性依赖的范围与第一直接依赖的范围一致;
    • 当第二直接依赖的范围是test的时候,依赖不会得以传递;
    • 当第二直接依赖的范围是provided的时候,只传递第一直接依赖范围也为provided的依赖,切传递依赖的范围同样为provided;
    • 当第二直接依赖的范围是runtime的时候,传递性依赖的范围与第一直接依赖的范围一致,但compile列外,此时传递性依赖范围为runtime

    依赖调解:

      是什么?

        当传递性依赖造成为问题的时候,就需要清楚地知道该传递性依赖是从哪条依赖路径引入的。这就是依赖调解的作用

      有什么?

       依赖调解有两大原则:

    1. 路径最近者优先
      比如项目有A有这样的依赖关系:A->B->C->X(1.0)、A->D->X(2.0),X是A的传递性依赖,但是两条依赖路径上有两个版本的X,所以根据第一原则,A->D->X(2.0)路径短,所以X(2.0)会被解析使用
    2. 第一声明者优先
      如果路径都一样长的话,第一原则就不行了,比如 A->B->Y(1.0)、A->C->Y(2.0),Y(1.0)和Y(2.0)的路径一样,所以这时候根据第二原则,先声明的被解析。

      

    可选依赖:

      如图,项目中A依赖B,B依赖于X和Y,如果所有这三个的范围都是compile的话,那么X和Y就是A的compile范围的传递性依赖,但是如果我想X,Y不作为A的传递性依赖,不给他用的话。就需要下面提到的配置可选依赖。

     1 <project>  
     2     <modelVersion>4.0.0</modelVersion>  
     3     <groupId>com.juvenxu.mvnbook</groupId>  
     4     <artifactId>project-b</artifactId>  
     5     <version>1.0.0</version>  
     6     <dependencies>  
     7         <dependency>  
     8             <groupId>mysql</groupId>  
     9             <artifactId>mysql-connector-java</artifactId>  
    10             <version>5.1.10</version>  
    11             <optional>true</optional>  
    12         </dependency>  
    13         <dependency>  
    14             <groupId>postgresql</groupId>  
    15             <artifactId>postgresql</groupId>  
    16             <version>8.4-701.jdbc3</version>  
    17             <optional>true</optional>  
    18         </dependency>  
    19     </dependencies>  
    20 </project>
    View Code

    配置也简单,在依赖里面添加

        <optional>true</optional> 

    就表示可选依赖了,这样A如果想用X,Y就要直接显示的添加依赖了。

    排除依赖:

      有时候你引入的依赖中包含你不想要的依赖包,你想引入自己想要的,这时候就要用到排除依赖了,比如下图中spring-boot-starter-web自带了logback这个日志包,我想引入log4j2的,所以我先排除掉logback的依赖包,再引入想要的包就行了

     

    排除依赖代码结构:

    1 <exclusions>
    2     <exclusion>
    3         <groupId>org.springframework.boot</groupId>
    4         <artifactId>spring-boot-starter-logging</artifactId>
    5     </exclusion>
    6 </exclusions>

     这里注意:声明exclustion的时候只需要groupId和artifactId,而不需要version元素,这是因为只需要groupId和artifactId就能唯一定位依赖图中的某个依赖。

    归类依赖:

      有时候我们引入的很多依赖包,他们都来自同一个项目的不同模块,所以他们的版本号都一样,这时候我们可以用属性来统一管理版本号

     1 <project>  
     2     <modelVersion>4.0.0</modelVersion>  
     3     <groupId>com.juven.mvnbook.account</groupId>  
     4     <artifactId>accout-email</artifactId>  
     5     <version>1.0.0-SNAPSHOT</version>  
     6     <properties>  
     7         <springframework.version>1.5.6</springframework.version>  
     8     </properties>  
     9     <dependencies>  
    10         <dependency>  
    11             <groupId>org.springframework</groupId>  
    12             <artifactId>spring-core</artifactId>  
    13             <version>${springframework.version}</version>  
    14         </dependency>   
    15         <dependency>  
    16             <groupId>org.springframework</groupId>  
    17             <artifactId>spring-beans</artifactId>  
    18             <version>${springframework.version}</version>  
    19         </dependency>         
    20     </dependencies>  
    21 </project>
    View Code

    如图所示,先通过

    </properties>
        这里定义你先要的版本
    </properties>
    

      来定义,然后在下面依赖使用${}来引入你的属性。

    本文有参考以下文章:http://tengj.top/2018/01/01/maven/ (嘟嘟MD)

              https://blog.csdn.net/chenlushun12/article/details/89261586

  • 相关阅读:
    CentOS6.5配置网络
    php curl 总结
    laravel-5-doctrine-2 教程
    DOS 总结
    Centos如何通过yum安装php7
    sql with 写法
    php 汉字转拼音函数
    MYSQL 升序排序但值为0的排最后
    zookeeper基础知识
    初识redis
  • 原文地址:https://www.cnblogs.com/fzzzjjj/p/11384886.html
Copyright © 2011-2022 走看看