title: maven
date: 2020-09-27 23:29:57
tags:
maven的概述
- maven的作用是为了更快更好的进行开发,虽然我们目前已经掌握的技术已经可以搭建一个简易的网站,但是不能胜任大型项目的开发。
- 最基本开发的几个问题:
- 添加第三方jar包:简单项目可能只有几十个jar包,但是一旦多起来了呢,一个个手动添加十分麻烦,并且如果分模块构建的话,每个模块可能都要重新导入jar包,无疑会使项目十分臃肿。
- jar包之间的依赖关系:jar包非常有可能依赖与其他jar包,一旦jar包一多,记住每个jar包的依赖是不现实的。
- jar包的寻找和下载:由于是jar包的形式进行下载,非常难以寻找到自己想要的jar包和版本,并且也不能保证下载的jar包是安全的。
- maven是如何解决的:
- 对于大型项目,maven可以将项目拆分为多个模块,每个模块就是一个小工程,提高复用率。
- 添加第三方jar包:maven不再将jar包引入到项目中,而是建立一个maven仓库,将jar包存放在仓库中,再项目中使用仓库的坐标进行引用。
- 依赖:maven引入jar包时,会自动将jar包所依赖的jar包自动引入。
- 统一下载:maven是通过中央仓库进行下载的,保证安全行并且十分容易进行查找。
- 了解的maven的作用之后,我们给出maven的定义:maven是一款服务于java平台的自动化构建工具。历史发展是make-ant-maven-gradle。其中,构建是指以java源文件,框架配置文件,jsp,html,图片等资源为原材料去生产一个可以运行的项目的过程。大致可以分为三个阶段:编译,部署,搭建,编译是指将java的源文件编译为class文件之后,交给jvm去执行。部署是指一个BS项目最终运行的并不是web工程本身,而是编译之后的web工程。
- 下面让我们来直观的了解一下maven的结构
再来看一下web工程的目录,就能深刻的理解,项目运行的时编译之后的项目而不是项目本身
从图中可以看到,编译之后的项目中src目录(即源码目录)消失了,因为运行的是class文件,并且webconten(webapps)目录页消失了,取而代之的是以项目名命名的目录,lib是存放需要的jar包,这时还没有采用maven进行构建,classes就是通常说的类路径,至于web-inf和meta-inf的区别,详细情况看这里,简单来说就是,web-inf目录是存放项目所需资源,字节码文件的地方,meta-inf目录相当于是java的内部目录,一般是不会自己手动天加文件进去的,通常都是由构建工具自动生成。
构建的周期
- 各个环节
- 清理:将之前编译过的字节码文件删除
- 编译:将源文件编译问字节码
- 测试:自动测试,自动调用junit程序(就是自动调用写好的juint,*test.java程序)
- 报告:测试程序执行的成果
- 打包:web工程打的是war包,java工程打jar包
- 安装:maven特定概念-将打包得到的文件复制到仓库中的指定位置,就像其他第三方包一样,供后来的程序调用。
- 部署:将war包复制到servlet容器中的指定目录下。
- maven所有标签大全:这里
- 这里说的仅仅是maven的构建周期,maven有三个标准周期,是clean(清理),build(构建),site(项目站点文档),常用的就是clean和build,site不怎么用。
- maven和javac和java等命令一样,是可以再命令行中运行的,平常我们再ide中不过是ide帮我们调用的,需要注意的是,使用与构建过程相关的,命令要进入pom.xml文件所在的目录,而对maven本身的命令,可以再任何一个目录中执行。
生命周期和插件的关系
- maven的核心程序中只定义了抽象的生命周期,但是具体的执行任务还是要靠插件来完成。插件目标包扩插件的前缀和目标,每个插件能完成多个任务(任务的完成是通过目标来执行的),maven核心程序为我们将许多的插件目标和生命周期进行了绑定,这样再我们再命令行中输入的其实是生命周期,实际执行由绑定的插件目标进行。详细可以看这里
- 当执行maven的某个生命周期时,只会执行这个生命周期和生命周期之前的周期,之后的则不会执行,比如执行compile周期,则只会执行clean和compile周期。
- 大致的分类是这样:生命周期(clean,defaul,site)->阶段(包含在生命周期中,比如clean就有pre-clean,clean,post-clean,default有compile,test等周期)->插件(就是大致的任务方向,比如maven-clean-plugin和maven-jar-plugin)->目标(最小的单位,执行多种具体任务)
- 每个声明周期都有许多的阶段,阶段可以类比为接口,而插件就是这些接口的实现类。
仓库
- 仓库分类:
- 本地仓库:在本机上的maven仓库,默认是在C:/user/${用户名}/.m2/Repository,可以自己在maven配置文件中配置指定目录作为仓库,教程可以百度。
- 远程仓库:私服,一般是公司内部局域网,中央仓库,架设在互联网上,为全世界服务,中央仓库镜像,分设在各大洲,分散中央仓库的流量,并且更快响应,实际开发中,远程仓库一般就是私服和阿里镜像。
依赖管理
- 分为三个范围:compile,test,provided。
- 作用范围:compile对于主程序有效,对于测试程序有效,参与打包。test范围对主程序无效,对test程序有效,不参与打包。provided对主程序和测试程序都有效,但是不参与打包,这里和compile和test的比较角度不同,因为provided是从项目开发部署的角度比较的,provided参与开发(即compile和test阶段),但是不参与部署和打包,因为web项目是要部署到服务器上运行的,但是服务器也是一各java程序,本身就有jar包,provided的jar包就是服务器本身具有的jar包,不能重复添加,否则会有jar包冲突,因此只有开发时需要,其余并不需要。典型例子就是servlet-api.jar
- 统一依赖管理,将版本号写在properties中,在用到的地方进行${}引用,防止大范围手动改动
<properties>
<spring.version>2.3.0</spring.version>
</properties>
依赖的传递性
- 工程B依赖于工程A,那么A中声明的依赖会自动传递到B中,避免在工程中重复导入。
- 当有多个版本的依赖时,如果依赖在依赖结构树中的深度相同,就会以第一个声明的版本作为最终版本。
- 任何可传递的以来都可以用exclusion进行排除,比如A依赖B,B依赖C,在A中就可以用exclusion排除一些在C中声明的依赖。
- 非compile范围的依赖是不能传递的,需要手动引入。
依赖的继承
- 当工程分为多个模块时,模块之间的依赖就有可能不能进行传递,从而冲突,比如test范围的依赖就不能传递,那么在每个模块中都必须手动引入依赖。很容易产生冲突,这时就可以将依赖统一版本到maven父工程中,子工程继承,且不声明依赖版本。(统一依赖管理plus)
- 过程
<!--声明父工程-->
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>parent</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>pom</packaging><!--注意这里必须写pom方式打包,因为父工程是不放东西的,只是用来做依赖管理-->
<dependenciesManagement><!--管理依赖-->
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
</dependencies>
</dependenciesManagement>
<!--子工程中声明对父工程的引用-->
<parent>
<groupId>org.example</groupId>
<artifactId>parent</artifactId>
<version>1.0-SNAPSHOT</version>
<!--以当前文件为基准的父工程pom文件的相对位置-->
<relativePath>../pom.xml</relativePath>
</parent>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope><!--子工程中就不需要指定版本号,如果想单独使用,可以指定单独版本号-->
</dependency>
</dependencies>
聚合
- 使用了继承之后,如果要执行install,就要先install父工程,如果不先install父,就会构建失败,但是这样每个模块都要手动安装,为了解决这个问题,就用到了聚合
- 聚合就是在一个聚合工程中声明其他模块,这样只要安装聚合工程就会自动安装其他工程。聚合工程是随意哪个工程都可以,与继承无关,但是一般选择父工程作为聚合工程。
<modules>
<module>dao</module><!--各个子工程的相对路径-->
<module>service</module>
<module>controller</module>
<module>web</module>
</modules>
pom文件中各个标签的含义
踩雷
- 我憨了,怪不得每次下载依赖那么慢,原来是idea没有配置全局的maven,导致每次都是使用的idea的自带的默认的maven,仓库默认放在c盘,怪不得我修改本地的,maven配置也没有反应,因为idea根本没有使用我自己的maven,每次都从中央仓库下载,不慢就有鬼了,重新配置好之后
使用自己的maven配置的阿里云镜像,快的飞起。nice,但是好像还是每次新建项目都要重新配置,在设置中搜索maven就可以。将settings文件和maven仓库配置好就可以