一:为什么要使用Maven

1.1:大量的jar包

JavaEE开发领域,需要使用大量的第三方框架和工具jar包,如果每次都进行复制到WEB-INF目录下的lib目录中会导致每次创建一个新的工程就需要将jar包再次复制到lib目录下,从而造成工作区中存在大量重复的文件。

另外,大量的jar包避免不了版本的冲突。

Maven拥有一套完全统一规范的jar包管理体系。可以将每个jar包在本地仓库中保存一份,项目只需要需要维护一个文本形式的jar包的引用(规范,完整,准确)——我们称之为“坐标”,不仅极大的节约了存储空间,更避免了重复文件太多而造成的混乱

1.2:jar包之间的依赖关系

jar包往往不是孤立存在的,很多jar包都需要在其他jar包的支持下才能够正常工作;

Maven就可以替我们自动的将当前jar包所依赖的其他所有jar包全部导入进来,无需人工参与。

1.3:Jar包之间的冲突

当一个工程A直接和间接的引用的工程B和C的jar包,但是B和C所用的jar包的版本不一致,此时对于A来说就存在jar依赖冲突。

maven帮我们完美的解决了:

原则:最短路径者优先和声明者优先

1.4:将项目拆分成多个工程模块

Maven可以实现管理多个工程模块

1.5:实现项目的分布式部署

项目规模增加到一定程度后,可能每个模块都需要运行在独立的服务器上,此时需要maven进行分布式部署

 1.6:小结

  • 大量jar包管理
  • jar版本依赖冲突
  • 管理工程的模块化
  • 分布式部署

二:Maven是什么

2.1:自动化构建工具

Maven是一款自动化构建工具,专注服务于Java平台的项目构建和依赖管理。

构建工具的演变:Make→Ant→Maven→Gradle→其他……

2.2:构建概念

构建并不是创建,创建一个工程(只是创建出来了)并不等于构建一个项目。

编写任何Java代码想要执行的话就必须经过编译得到对应的.class文件,才能运行;

当我们需要通过浏览器访问Java程序时就必须将包含Java程序的Web工程编译的结果“拿”到服务器上的指定目录下,并启动服务器才行。这个“拿”的过程我们叫部署

构建就是以我们编写的Java代码、框架配置文件、国际化等其他资源文件、JSP页面和图片等静态资源作为“原材料”,去生产出一个可以运行的项目的过程。

2.3:构建的过程

清理:删除以前的编译结果,为重新编译做好准备。

编译:将Java源程序编译为字节码文件。

测试:针对项目中的关键点进行测试,确保项目在迭代开发过程中关键点的正确性。

报告:在每一次测试后以标准的格式记录和展示测试结果。

打包:将一个包含诸多文件的工程封装为一个压缩文件用于安装或部署。Java工程对应jar包,Web工程对应war包。

安装:在Maven环境下特指将打包的结果——jar包或war包安装到本地仓库中。

部署:将打包的结果部署到远程仓库或将war包部署到服务器上运行。

 三: Maven的使用

3.1:Maven的仓库位置

仓库
        本地库:本地电脑上的某个目录

        远程库:
            1、私服:统一公司、部门、项目组内部人员的jar包
            2、中央仓库       (位于国外,全世界公用,但是高并发会造成阻塞) 
            3、中央仓库镜像   (位于某个地区,一般配置阿里镜像)

注意: 

本地仓库地址默认在C:\Users\Administrator\.m2\repository,但是并不利于开发,因此需要配置本地仓库的路径。

补充:

Java中的VM options for importer:可以设置导入的VM参数。一般这个都不需要主动改,除非项目真的导入太慢了我们再增大此参数。

Xmx代表程序最大可以从操作系统中获取的内存数量,Xms代表程序启动的时候从操作系统中获取的内存数量。

memory max(Xmx)           memory start (Xms)

3.2:Maven项目

pom文件pom(Project Object Modle):项目对象模型

 3.3:Maven项目的目录结构

 四:Maven的核心概念

Maven的核心概念包括:POM、约定的目录结构、坐标、依赖、仓库、生命周期、插件和目标、继承、聚合。

4.1 POM

Project Object Model:项目对象模型。Java工程的相关信息封装为对象作为便于操作和管理的模型。

4.2 约定的目录结构

约定>配置>编码

4.3 Maven的坐标:

(1)groupId:公司或组织的域名倒序+当前项目名称

(2)artifactId:当前项目的模块名称

(3)version:当前模块的版本

4.4如何通过坐标到仓库中查找jar包?

 <groupId> </groupId><artifactId></artifactId><version></version>

将三个标签中的值连起来的字符串,找到对应的本地仓库

※注意:

我们自己的Maven工程必须执行安装操作才会进入仓库。安装的命令是:mvn install

任何一个Maven工程会根据坐标到本地仓库中去查找它所依赖的jar包。如果能够找到则可以正常工作,否则就不行。HelloFriend 回到本地仓库去找HelloWorld  jar包。

4.5 依赖管理

当A jar包需要用到B jar包中的类时,我们就说A对B有依赖。、

直接依赖和间接依赖

如果A依赖B,B依赖C,那么A→B和B→C都是直接依赖,而A→C是间接依赖。

4.5.1 依赖的范围

依赖的范围:类似于变量的作用域,jar包可以使用的范围
            <scope></scope>指明依赖范围
                compile:
                    默认值,可以使用在main目录与test目录下使用
                   部署到Tomcat服务器上运行时放在WEB-INF的lib目录下
                test:
                    只能在test目录下使用
                    部署时无需上传服务器,服务器上没有是没有问题的
                provided:
                    可以使用在main目录与test目录下使用  
                    部署时无需上传服务器,因为服务器上理论上时已经存在的了(假定)

4.5.2 依赖的传递性

当存在间接依赖的情况时,主工程对间接依赖的jar可以访问吗?这要看间接依赖的jar包引入时的依赖范围——只有依赖范围为compile时可以访问。

间接依赖是否可以用还需要看依赖的范围,只有是complie才可以间接依赖。

原则:最短路径者优先和声明者优先

 如果可以不去依赖某个工程的jar包可以使用<exclusion>标签

 <exclusions>
                <exclusion>
                    <groupId>junit</groupId>
                    <artifactId>junit</artifactId>
                </exclusion>
            </exclusions>

4.5.3 统一管理目标Jar包的版本 

以对Spring的jar包依赖为例:Spring的每一个版本中都包含spring-context,springmvc等jar包。我们应该导入版本一致的Spring jar包,而不是使用4.0.0的spring-context的同时使用4.1.1的springmvc。

问题是如果我们想要将这些jar包的版本统一升级为4.1.1,显然,我们有统一配置的方式:

 方式:

<properties>
    <spring.version>4.0.0.RELEASE</spring.version>
</properties>
${spring.version}

<properties>
        <spring.version>4.0.0.RELEASE</spring.version>
    </properties>




<dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-orm</artifactId>
            <version>${spring.version}</version>
        </dependency>

4.6:仓库:

(1)本地仓库:为当前本机电脑上的所有Maven工程服务。

(2)远程仓库

        a)私服:架设在当前局域网环境下,为当前局域网范围内的所有Maven工程服务。

        b)中央仓库:架设在Internet上,为全世界所有Maven工程服务。

        c)中央仓库的镜像:架设在各个大洲,为中央仓库分担流量。减轻中央仓库的压力,同时更快的响应用户请求。

 4.6.3:仓库中的文件

(1)Maven的插件

(2)我们自己开发的项目的模块

(3)第三方框架或工具的jar包

不管是什么样的jar包,在仓库中都是按照坐标生成目录结构,所以可以通过统一的方式查询或依赖。

4.7:maven生命周期

Maven生命周期定义了各个构建环节的执行顺序,有了这个清单,Maven就可以自动化的执行构建命令了。

  • Clean Lifecycle在进行真正的构建之前进行一些清理工作。
  • Default Lifecycle构建的核心部分,编译,测试,打包,安装,部署等等。(用的比较多,可以帮助我们自动化构建我们需要的内容)
  • Site Lifecycle生成项目报告,站点,发布站点。(在浏览器上查看项目的信息,是site阶段和site-deploy阶段,用以生成和发布Maven站点,这可是Maven相当强大的功能,文档及统计数据自动生成,但是一般我们用不上)

4.7.1:生命周期与自动化构建

运行任何一个阶段的时候,它前面的所有阶段都会被运行,例如我们运行mvn install 的时候,代码会被编译,测试,打包。这就是Maven为什么能够自动执行构建过程的各个环节的原因。此外,Maven的插件机制是完全依赖Maven的生命周期的。

4.8:插件和目标

(1)Maven的核心仅仅定义了抽象的生命周期,具体的任务都是交由插件完成的。

(2)每个插件都能实现多个功能每个功能就是一个插件目标

(3)Maven的生命周期与插件目标相互绑定,以完成某个具体的构建任务。

例如:compile就是插件maven-compiler-plugin的一个功能;pre-clean是插件maven-clean-plugin的一个目标。

五:继承与聚合

5.1:为什么需要继承机制?

由于非compile范围的依赖信息是不能在“依赖链”中传递的,所以有需要的工程只能单独配置。

父项目一般不做业务处理,所以无需打包,并且无需保留src目录

需要在父项目中声明标签<packaging></packaging> 可以传的值有:

        pom:不打包
        jar:默认值,打包时打成jar包
        war:打包时打成war包

子项目应该声明代码知道父项目是谁

<relativePath>../Parent/pom.xml</relativePath>

         <parent>
	        <groupId>com.atguigu.parent</groupId>
	        <artifactId>Parent</artifactId>
	        <version>1.0-SNAPSHOT</version>
	        <!-- 指定父项目pom.xml文件位置 -->
	            <relativePath>../Parent/pom.xml</relativePath>
	    </parent>

5.2:父项目的导包方式:

方式一:

 结果:子项目中直接拥有父项目中的所有jar包

<dependencies>
		        <dependency>
		            <groupId>junit</groupId>
		            <artifactId>junit</artifactId>
		            <version>4.12</version>
		            <scope>test</scope>
		        </dependency>
		    </dependencies>

方式二:

结果:父项目中实际上没有导包进入,只不过进行了声明,子项目需要再次导入声明,但是此时无需指定版本

<dependencyManagement>
		        <dependencies>
		            <dependency>
		                <groupId>junit</groupId>
		                <artifactId>junit</artifactId>
		                <version>4.10</version>
		                <scope>test</scope>
		            </dependency>
		        </dependencies>
		    </dependencyManagement>

原因:父项目作为整个项目的管理者,没有业务逻辑代码,所以本身不需要导包,父项目只不过作为jar包管理,这里可能有很多的jar包,子项目中可以根据需求进行声明。

5.3:聚合:

5.3.1:为什么要使用聚合?

将多个工程拆分为模块后,需要手动逐个安装到仓库后依赖才能够生效。修改源码后也需要逐个手动进行clean操作。而使用了聚合之后就可以批量进行Maven工程的安装、清理工作,方便管理。

5.3.2:配置:

(在父项目中进行配置,目的是父亲知道谁是它的儿子,这样的话才能统一管理子项目)

<modules>
	        <module>../BoyFriend</module>
	        <module>../GrilFriend</module>
	    </modules>

5.3.3:开发中的使用:

1、不拆分模块(项目比较小)
        没有工作空间的概念,项目分开管理
    2、拆分模块(项目比较大)    
        创建就指定了父子关系,代码自动完善

Logo

CSDN联合极客时间,共同打造面向开发者的精品内容学习社区,助力成长!

更多推荐