Mevan
完成一个java项目,需要做很多工作,如:
-
分析项目要做什么,直到项目有哪些组成成分
-
设计项目,通过哪些步骤,使用哪些技术,需要多少人,多长时间
-
组建团队,招人,购置设备,服务器,软件,笔记本
-
开发人员写代码,开发人员需要测试自己的代码重复多次工作
-
测试人员,测试项目功能是否符合要求
测试开发人员提交的代码-如果测试有问题–需要开发人员修改–在提交代码给测试–测试人员在测试代码-如果还有问题-在交给开发人员-开发人员在提交-在测试—直到,测试代码通过
传统开发项目的问题,没有使用maven[meivn]管理的项目
-
很多模块,模块之间有关系,手动管理关系,比较繁琐
-
需要很多第三方功能,也就是很多jar文件,需要手工从网络中获取各个jar包
-
需要管理jar包的版本,你需要的是mysql.5.1.5jar,那就不能给一个mysql.4.0jar
-
管理jar文件之间的依赖,你的项目要使用a.jar需要使用b.jar里面的类,首先就需要获取到b.jar才可以,然后才能使用a.jar
a.jar需要b.jar这个关系叫做依赖,或者你的项目要是用mysql的驱动,也可以叫做项目依赖mysql驱动
这样的需求就导致,我们需要改进项目的开发和管理,也就是需要maven
- maven可以管理jar文件
- 自动下载jar和他的文档,源代码
- 管理jar直接的依赖,a.jar需要b.jar,maven会自动下载b.jar
- 还可以管理需要的jar版本
- 帮助编译程序,把java编译为class
- 帮助测试代码是否正确
- 帮助打包文件,形成jar,或war文件
- 帮助部署项目
项目的构建
构建是面向过程的,就是一些步骤,完成项目代码的编译,测试,运行,打包,部署等等,maven支持的构建包括有:
- 清理,把之前项目编译的东西删除掉,为新编译的代码做准备。
- 编译,把程序源码编译为执行代码,java-class文件批量的,maven可以同时把成千上百的文件编译为class,javac不一样,javac一次编译一个文件
- 测试,maven可以执行测试程序代码,验证你的功能是否正确,批量的,maven同时执行多个测试代码,同时测试很多功能
- 报告,生成测试结果的文件,测试通过没有
- 打包,把你的项目中所有的class文件,配置文件,等所有资源放到一个压缩文件中,这个压缩文件就是项目的结果文件,通常java程序,压缩文件就是jar扩展名的,对于web应用,压缩文件扩展名.war
- 安装,把5中生成的文件jar,war安装到本机仓库
- 部署,把程序安装好可以执行
maven核心概念:
- POM:一个文件,名称POM.xml,POM翻译过来叫做项目对象模型,maven把一个项目当做一个模型使用控制maven构建项目的过程,管理jar依赖
- 约定的目录结构:maven项目的目录和文件的位置都是规定的
- 坐标:是一个唯一的字符串,用来表示资源的
- 依赖管理:管理你的项目可以使用jar文件
- 仓库管理(了解):资源存放的位置
- 生命周期(了解):maven工具构建项目的过程,就是生命周期
- 插件和目标(了解):执行maven构建的时候用的工具是插件
- 继承:
- 聚合:
讲maven的使用,先难后易的,难是说使用maven的命令,完成maven使用,在idea中直接使用maven,代替命令
maven工具的安装和配置:
-
需要从maven官网下载maven的安装包
-
解压安装包,解压到一个目录,非中文目录
子目录bin:执行程序,主要mvn.cmd
comf:maven工具本身的配置文件setting.xml
-
配置环境变量
在系统的环境变量中,指定一个M2_HOME的名称,指定它的值是maven工具安装目录,bin之前的目录
M2_HOME=x:\xx\maven_work\apache-maven-3.3.9
再把M2_HOME加入到path之中,在所有路径之前加入%M2_HOME%\bin;
-
验证,新的命令行,执行mvn -v
注意:需要配置JAVA_HOME,指定jdk路径
出现如下内容,maven安装,配置正确
Apache Maven 3.8.1 (05c21c65bdfed0f71a2f2ada8b84da59348c4c5d)
Maven home: F:\maven\apache-maven-3.8.1\bin…
Java version: 1.8.0_131, vendor: Oracle Corporation, runtime: F:\java-JDK\jre
Default locale: zh_CN, platform encoding: GBK
OS name: “windows 10”, version: “10.0”, arch: “amd64”, family: “windows”
Maven核心概念
Maven工程约定目录结构
maven中约定的目录结构:
Hello:
|—src
|—|---main
|—|---|—java
|—|---test
|—|---|—java
|—|---|—resources
|—pom.xml
说明:
Hello:根目录,就是工程名
src:源代码
main:主程序
java:主程序的java源码
maven约定的目录结构,约定是大家都遵守的一个原则
每一个maven项目
Hello/
—/src
------/main 放你主程序java代码和配置文件
----------/java 你的程序包和包中的java文件
----------/resources 你的java程序中要使用的配置文件
-----/test 放测试程序代码和文件的(可以没有)
----------/java 测试程序包和包中的java文件
----------/resources 测试java程序中要使用的配置文件
—/pom.xml maven的核心文件(maven项目必须有)
mvn compile命令编译main目录下,java中所有程序
编译过程会下载一些文件,从 https://repo.mven.apache.org(中央仓库)中下载
下载的东西是一些插件,maven工具执行操作是需要很多插件(java类—jar包)完成的
这些jar包,插件,是完成某些功能的
默认放在,默认仓库:C:\Users\Administrator\.m2\repository中
下载完成后显示BUILD SUSSESS
最后会在项目的根目录下生成target目录(结果目录),maven编译的java文件最后都放在target目录中
修改本机存放资源的目录位置:
- 修改maven的配置文件,maven安装目录/conf/settings.xml,要先备份setting.xml
- 修改指定目录(不要使用中文目录)
maven仓库
-
仓库是存放各种东西的,如,maven使用的jar包插件,还有项目使用的各种jar包
-
仓库的分类:
-
本地仓库,个人计算机上的文件夹,存放各种jar
-
远程仓库,在互联网上的,使用网络才能使用的仓库
中央仓库,最权威的,所有的开发人员都共享使用的一个集中的仓库,
https://repo.mven.apache.org:中央仓库的地址中央仓库的景象:就是中央仓库的备份,在各大洲,重要的城市都是镜像
私服:在公司内部,局域网范围内使用,不对外使用
-
-
仓库的使用:
maven仓库的使用不需要人为参与
如:开发人员需要使用mysql驱动----->maven首先查本地仓库–>私服—>镜像—>中央仓库
在以上几个层级没有找到就会继续往下寻找
坐标
pom:项目对象模型,是一个pom.xml文件
样例:
<groupId>公司域名的道谢</groupId>
<artifactId>自定义项目名称</artifactId>
<version>自定义版本号</version>
https://mvnrepository.com:搜索使用的中央仓库,使用groupId或者artifactId作为搜索条件
依赖
packaging:项目打包的类型,可以使用jar、war、rar、ear、pom,默认是jar,可以不写
dependencies和dependency:依赖,项目中要使用的各种资源说明
比如我的项目要是用mysql驱动
加入后,maven就会按照层级关系去寻找对应jar包
- Maven解析依赖信息时回到本地仓库中查找被依赖的jar包,对于我们自己开发的maven工程使用install命令安装后就可以进入仓库
maven依赖的范围
编译、测试、运行
Maven有以下几种依赖范围:
compile:编译依赖范围(默认),使用此依赖范围对于编译、测试、运行三种过程都有效,即在编译、测试和运行的时候都要使用该依赖jar包;
test:测试依赖范围,从字面意思就可以知道此依赖范围只能用于测试过程,而在编译和运行项目时无法使用此类依赖,典型的是JUnit,它只用于编译测试代码和运行测试代码的时候才需要;
provided:此依赖范围,对于编译和测试过程有效,而对运行时无效;
以下范围不常用:
runtime:运行时依赖范围,对于测试和运行classpath有效,但是在编译主代码时无效,典型的就是JDBC驱动实现;
system:系统依赖范围,使用system范围的依赖时必须通过systemPath元素显示地指定依赖文件的路径,不依赖Maven仓库解析,所以可能会造成建构的不可移植,谨慎使用。
maven依赖的传递性
如果A依赖于B,那么我们就可以说B是A的直接依赖
依赖的传递就基于这个概念。
直接依赖里配置的依赖信息,会默认往下级传递,也就是说,我的工程里添加了一些依赖信息,那么当其他工程依赖于我的工程时,就会默认拥有我工程中的其他依赖
好处:可以传递的依赖不必再各个模块重复声明,仅在最上级的直接依赖中依赖一次即可
注意:非compile范围的依赖不能传递,所以在各个模块中,有需要就重复声明
依赖的排除
<exclusions>
<exclusion>
<groupId></groupId>
<artifactId></artifactId>
</exclusion>
</exclusions>
当我们的项目因为配置依赖,而导入了不希望使用的依赖,那么就可以使用以上的标签,在pom.xml文件中排除掉该依赖,具体的值就是希望排除依赖的坐标信息
依赖的原则
作用:解决jar包冲突问题
在依赖传递时,有时会碰到这种情况,有三个工程,其中最顶级的工程,依赖于一个1.2版本的jar包,他下面的次级工程,依赖与它,但是它使用的jar包是1.0的版本,最下级的工程,此时因为传递性的原因被迫拥有了两个版本的依赖这就会造成冲突。
而maven因为自身的依赖原则,此时如果不指定版本 ,它会自动选择路径最短的,也就是使用离自己最近的依赖,即路径最短者优先
那如果路径相同呢?
这时的原则,就是先声明者优先,即在pom.xml先配置谁,就用谁
maven常用操作
-
maven的属性设置
设置maven的常用属性
-
maven的全局变量
自定义的属性,1.在通过自定义标签声明变量(标签名就是变量名)
2.在pom.xml文件中的其他位置,使用${标签名}使用变量的值
自定义全局变量一般是定义依赖的版本号,当你的项目中要使用多个相同的版本号,先试用全局变量定义,在使用${变量名}来使用
继承
现在有三个工程,最顶级的使用4.0的junit,它下面的工程也是用4.0的junit,最下面的使用4.9的junit,此时由于junit属于test范围的依赖,不能传递,那就很容易造成版本的不一致
解决的思路就是,将junit依赖统一提取到“父”工程中,在子工程中生命junit依赖是不指定版本,以负公差统一设定的为准
操作步骤:
- 创建一个Maven工程作为父工程,注意:打包方式为pom
- 在子工程中声明对父工程的引用
- 将子工程的坐标中与父工程坐标中重复的内容删除
- 在父工程统一管理junit的依赖
- 在子工程中删除junit依赖的版本号部分
- 配置继承后,要先安装父工程
<!--在子工程中声明父工程的标签-->
<parent>
<!--父工程的坐标信息-->
<groupId></groupId>
<artifactId></artifactId>
<version></version>
<!--以当前pom文件为基准的父工程pom.xml文件的相对路径-->
<relativePath></relativePath>
</parent>
<!--父工程配置依赖管理的标签-->
<dependencyManagement>
<dependencies>
<groupId></groupId>
<artifactId></artifactId>
<varsion></varsion>
<scope></scope>
</dependencies>
</dependencyManagement>
聚合
- 作用:意见安装各个模块
- 配置方式:在一个总的集合工程中配置各个参与聚合的模块,maven会自动识别依赖关系
- 右键总聚合的工程,安装
<!--配置聚合-->
<modules>
<!--指定各个子工程的相对路径-->
<module>子工程</module>
<module>子工程</module>
<module>子工程</module>
</modules>
继承与聚合,首先在继承中,一个父工程,并不知道自己子工程的准确信息,但子工程都必须清楚自己的父工程是谁,聚合中,被聚合的模块并不知道自己被聚合了,但总的聚合工程,需要明确知道自己要聚合的模块信息
Maven的生命周期
-
maven对象的构建是建立在生命周期模型上的,它明确定义项目生命周期各个阶段,并且对于每一个阶段提供对应的命令,对开发者而言,仅仅需要掌握一小堆的命令就可以完成项目各个阶段的构建工作
-
构建项目是按照生命周期顺序构建,每一个阶段都有特定的插件来完成,不论现在要执行生命周期中的哪个阶段,都是从这个生命周期的最初阶段开始的
-
对于我们程序员而言,无论我么要进行哪个阶段的构建,直接执行响应命令即可,无需担心它前边阶段是否构建,maven都会自动构建,这也就是maven这种自动化构建工具给我们带来的好处
-
maven的生命周期就是maven构建项目的过程,
清理,编译,测试,报告,打包,安装,部署,maven会按顺序执行这些步骤,就算运行后面步骤的命令,也会默认执行前面的步骤
- 清理:将以前编译得到的旧的class字节码文件删除,为下一次编译做准备
- 编译:将Java源程序编程成class字节码文件
- 测试:自动测试,自动调用Junit程序
- 报告:测试程序执行的结果
- 打包:动态Web工程打war包,Java工程打jar包
- 安装:maven特定的概念—将打包得到的本间复制到仓库中的指定位置
- 部署:将动态Web工程生成的war包赋值到Servlet容器的指定目录下,使其可以运行
maven有三套相互独立的生命周期,分别是:
- Clean Lifecycle在进行真正的构建之前进行一些清理工作
- Default Lifecycle构建的核心部分,编译,测试,打包,安装,部署等等
- Site Lifecycle生成项目报告,站点,发布站点
它们是相互独立的,你可以仅仅调用clean来清理工作目录,仅仅调用site赖声川站点,也可以直接运行 mvn clean install site 运行所有这三套生命周期
每套生命周期都有一组阶段(Phase)组成,我们平时在命令行输入的命令总会对于一个特定的阶段,比如
mvn clean,这个clean是Clean生命周期的一个阶段,有Clean生命周期,也有clean阶段
Clean的生命周期
- pre-clean 执行一些需要在clean之前完成的工作
- clean移除所有上一次构建生成的文件
- post-clean 执行一些需要在clean之后立刻完成的狗做
Site生命周期
- pre-site 执行一些需要在生成站点文档之前完成的工作
- site生成项目的站点文档
- post-site 这行一些需要在生成站点文档之后完成的公国,并且为部署做准备
- site-deploy 将生成的站点文档部署到特定的服务器上
Default生命周期
Default生命周期是Maven生命周期中最重要的一个,绝大部分工作都放在这个生命周期中,也就是正常执行的生命周期
这里经常用到的是site阶段和site-deploy阶段,用以生成和发布maven站点,这可是maven相当强大的功能,Manager比较喜欢,文档即统计数据自动生成,很好看
maven的命令:maven独立使用,通过命令,完成maven的生命周期的执行,maven可以使用命令,完成项目的清理,编译,测试等等
maven的插件:maven命令执行时,真正完成功能的是插件,生命周期仅仅定义了要执行什么任务,而插件就是一些jar文件,一些类
单元测试
maven用的是junit,junit是一个专门测试的框架
junit测试的内容:测试的是类中的方法,每一个方法都是独立测试的,方法是测试的基本单位(单元)
maven借助单元测试,批量的测试你类中的大量方法是否符合预期的
Maven的常用命令
mvn clean:清理(会删除原来编译和测试的目录,即target,但是已经install到仓库里的包不会删除)
mvn compile:编译主程序(会在当前目录下生成一个target,里边存放编译主程序之后生成的字节码文件)
mvn test-compile:编译测试程序(会在当前目录下生成一个target,里面存放编译主程序之后生成的字节码文件)
mvn test:测试(会生成一个目录surefire-reports,保存测试结果)
mvn package:打包主程序(会编译、编译测试、测试、并且按照pom.xml配置把主程序打包生成jar包或者war包)
mvn install:安装主程序(会把本工程打包,并且按照本工程的坐标保存到本地仓库中)
mvn deploy:部署主程序(会把本工程打包,按照本工程的坐标保存到本地库中,并且还会保存到私服仓库中,还会自动把项目部署到web容器中)。
mvn site:生成站点
注意:以上命令必须在命令行进入pom.xml所在目录!!!
插件
我们可以手动配置maven运行时调用的插件
<build>
<!-- 配置插件 -->
<plugins>
<!-- 配置具体的插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<!-- 插件的名称 -->
<artifactId>maven-compiler-plugin</artifactId>
<!-- 插件的版本 -->
<version>3.8.1</version>
<!-- 配置插件的信息 -->
<configuration>
<!-- 告诉maven 我们写的代码是在jdk1.8上编译的 -->
<source>1.8</source>
<!-- 我们的程序应该运行在1.8的jdk上 -->
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</bulid>
资源插件
<bulid>
<resources>
<resource>
<directory>src/main/java</directory><!--文件所在目录-->
<includes><!--包括目录下的.properties,.xml文件都会扫描到-->
<include>**/*.properties</include>
</includes>
<!--filtering选项false不启用过滤器,*.property已经起到了过滤的作用了-->
<filtering>false</filtering>
</resource>
</resources>
</bulid>
作用:
- 默认某使用resources的时候,maven执行编译代码时,会把src/main/resources目录中的文件拷贝到target/classes目录中,对于src/main/java目录下的非java文件不处理,不拷贝到target/classes目录中
- 我们的程序有需要把一些文件放在src/main/java目录中,当我们在执行java程序时,需要使用到src/main/java目录中的文件,需要告诉maven在mvn compile src/main/java目录下的程序时,需要把文件一同拷贝到target/classes目录中,此时就需要在build中加入resources
maven的标签
<!--当前项目的信息-->
<groupId>:企业网址反写+项目名
<artifactId>:项目名-模块名
<version>:版本号+类型(snapshot快照版本(简化版本)、alpha内测版、beta公测版、release稳定版、GA正式发布版)
<packaging>:打包类型,默认是jar,可以配置成war、zip、pom类型。
<name>:当前项目名
<url>:项目地址
<description>:项目描述信息
<developers>:开发者信息
<licenses>:项目许可证信息,用来发布时授予别人使用此项目的权利
<organization>:组织信息,企业信息
<properties>:属性值标签,也叫变量标签。
<!--依赖标签-->
<dependencies>
<!--一个依赖包-->
<dependency>
<!--通过坐标指定依赖包-->
<groupId> </groupId>
<artifactId> </artifactId>
<version> </version>
<!--可选项:依赖范围。有六个可选值:常用compile/provided/test/runtime等-->
<scope>一个范围</scope>
<!--可选项:排除依赖传递:即:当前项目依赖当前配置的依赖包A时,如果这个依赖包又依赖其他包B,这里可以选择排除依赖的传递性,不下载导入B-->
<exclusions>
<exclusion>
<!--被排除的依赖包坐标-->
<groupId> </groupId>
<artifactId> </artifactId>
<version> </version>
</exclusion>
</exclusions>
</dependency>
</dependencies>
依赖管理标签
<dependencyManagement>
<dependencies>
<dependency>
<!-- Import dependency management from Spring Boot -->
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${springboot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
build:项目支持标签,一般用来引入插件
<build>
<plugins>
<plugin>
<!--插件坐标-->
<groupId> </groupId>
<artifactId> </artifactId>
<version> </version>
其他设置...
</plugin>
</plugins>
</build>
parent:继承标签,用于继承父项目。
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.6.RELEASE</version>
<relativePath/>
</parent>
moudules:聚合标签
<modules>
<module>a-demo</module>
<module>b-client</module>
<module>c-interface</module>
</modules>
<plugin>
<!--插件坐标-->
<groupId> </groupId>
<artifactId> </artifactId>
<version> </version>
其他设置...
</plugin>
</plugins>
</build>