Maven中常用的操作
一、Maven的目录结构:
Hello 项目名
├─src 源码
│ ├─main 主程序
│ │ ├─java 核心java代码
│ │ └─resources 配置文件
│ └─test 测试程序
│ ├─java 测试java代码
│ └─resources 测试的配置文件或资源文件
└─pom.xml
各个目录结构的详细介绍:
- src/main/java – 存放项目的.java文件即项目的源码。
- src/main/resources – 存放项目资源文件,如yaml、properties结尾等的配置文件。
- src/test/java – 存放所有单元测试.java文件,如junit测试类
- src/test/resources – 测试资源文件
- targe – 项目输出位置,编译后的class文件会输出到此目录
- pom.xml – maven项目核心配置文件 这里要注意看是maven的java项目还是maven的动态web项目,如动态web项目则会有webapp目录
二、Maven中的pom.xml
作用:以坐标的形式来引入所需要的jar包,对项目进行构建的的配置文件。
- 核心组成结构:
groupId:一般为公司域名的倒写
artifactId:一般为模块名即项目中的子模块名
version:项目的版本号
name:项目的名称
packaging:项目的打包类型,默认是jar包,web项目的是war包
dependencies|dependency:Maven 的一个重要作用就是管理jar包,为了一个项目可以构建或运行,项目中不可避免的,会依赖很多其他的jar包,在Maven中,这些 jar 就被称为依赖,使用标签dependency来配置。而这种依赖的配置正是通过坐标来定位的,由此我们也不难看出,maven 把所有的 jar包也都视为项目存在了。
properties:是用来定义一些配置shuxing 的,例如构建源码编码方式project.build.sourceEncoding,可以设置项目的编码方式反之中文乱码,以及可以管理项目中各个依赖的版本号(方便统一修改),例如一下配置:
<properties>
<!--源码编译jdk版本-->
<maven.compiler.source>1.8</maven.compiler.source>
<!--运行代码的jdk版本-->
<maven.compiler.target>1.8</maven.compiler.target>
<!--项目构建使用的编码,避免中文乱码-->
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<!--生成报告的编码-->
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
</properties>
build:表示与构建相关的配置,例如设置编译插件的jdk版本
parent:在Maven中,如果多个模块都需要声明相同的配置,例如:groupId、version、有相同的依赖、或者相同的组件配置等,也有类似java的继承机制,用parent声明要继承的父工程的pom配置
modules:在Maven的多模块开发中,为了统一构建整个项目的所有模块,可以提供一个额外的模块,该模块打包方式为pom,并且在其中使用modules聚合的其它模块,这样通过本模块就可以一键自动识别模块间的依赖关系来构建所有模块,叫Maven的聚合
description:描述信息
relativePath:父项目pom.xml文件的相对路径,以上标签使用的实例:
```java
<?xml version="1.0" encoding="UTF-8"?>
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<!--Maven模型的版本,对于Maven2和Maven3来说,它只能是4.0.0-->
<modelVersion>4.0.0</modelVersion>
<!--groupId、artifactId、version三个元素生成了一个Maven项目的基本坐标,
在众多的maven项目中可以唯一定位到某一个项目。
坐标也决定着将来项目在仓库中的路径及名称 -->
<groupId>com.atguigu.gulimall</groupId>
<artifactId>gulimall</artifactId>
<version>0.0.1-SNAPSHOT</version>
<!--名称-->
<name>gulimall</name>
<!--描述-->
<description>聚合</description>
<!--打包-->
<packaging>pom</packaging>
<!--模块-->
<modules>
<module>gulimall-member</module>
<module>gulimall-order</module>
<module>gulimall-coupon</module>
<module>gulimall-ware</module>
<module>gulimall-product</module>
<module>renren-fast</module>
<module>renren-generator</module>
<module>gulimall-common</module>
<module>gulimall-gateway</module>
</modules>
<!--插件-->
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<fork>true</fork>
<addResources>true</addResources>
</configuration>
</plugin>
</plugins>
</build>
</project>
```
```java
<?xml version="1.0" encoding="UTF-8"?>
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<!--Maven模型的版本,对于Maven2和Maven3来说,它只能是4.0.0-->
<modelVersion>4.0.0</modelVersion>
<!--父工程的坐标-->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.8.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<!--公司名或组织名的域名倒序-->
<groupId>com.atguigu.gulimall</groupId>
<!--模块名-->
<artifactId>gulimall-order</artifactId>
<!--版本号-->
<version>0.0.1-SNAPSHOT</version>
<!--名称-->
<name>gulimall-order</name>
<!--描述-->
<description>谷粒商城-订单服务</description>
<!--配置信息-->
<properties>
<java.version>1.8</java.version>
<spring-cloud.version>Greenwich.SR3</spring-cloud.version>
</properties>
<!--依赖-->
<dependencies>
<dependency>
<groupId>com.atguigu.gulimall</groupId>
<artifactId>gulimall-common</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>
三、Maven仓库
- 本地仓库:用来存储从远程仓库或中央仓库下载的插件和 jar 包,存储在本地硬盘上,本地仓库的位置设置:
<localRepository>G:\devSoft\apache-maven-3.6.3\maven_repository</localRepository>
- 远程仓库:
1.中央仓库:在maven中内置了一个远程仓库的地址:http://repo1.maven.org/maven2
2.私服:在局域网中部署的服务器、为当前局域网范围内使用的所有maven服务
3.中央仓库的镜像:架设在不同的位置,为中央仓库分担流量
执行流程如图所示:
四、Maven的生命周期
- Clean Lifecycle :在进行真正的构建之前进行一些清理工作
- Default Lifecycle:构建的核心部分,编译,测试,打包,部署等等
- Site Lifecycle : 生成项目报告、站点、发布站点
注意:对于我们而言,无论在进行那个阶段的构建,直接执行相应的命令即可,Maven都会帮祝我们进行自动化构建。
五、Maven常用命令
- mvn clean:将target目录删除,但是已经install到仓库里的包不会删除
- mvn compile:编译(执行的是主程序下的代码)
- mvn test:测试(不仅仅编译src/main/java下的代码,也编译了java/test/java下的代码)
- mvn package:打包(执行的时候会打成war包,编译了src/main/java下的代码,也编译了java/test/java下的代码)
- mvn install:安装(执行的时候会打成war包,编译了src/main/java下的代码,也编译了java/test/java下的代码,将这个包安装到了本地仓库中)
- mvn deploy:部署(需要配置才能执行)
注意:maven命令的运行一定要在pom.xml文件目录下运行
六、插件
定义:maven提供的功能,用来执行清理、编译、测试、报告、安装的程序
- clean插件:maven-clean-plugin:2.5
clean阶段是独立的一个阶段,功能就是清除工程目前下的target目录 - resources插件:maven-resources-plugin:2.6
resource插件的功能就是把项目需要的配置文件拷贝到指定的目当,默认是拷贝src\main\resources目录下的件 到classes目录下 - compile插件:maven-compiler-plugin
compile插件执行时先调用resouces插件,功能就是把src\mainjava源码编译成字节码生成class文件,并把编译好的class文件输出到target\classes目录下 - test测试插件:
单元测试所用的compile和resources插件和主代码是相同的,但执行的目标不行,目标testCompile和 testResources是把src\test\java下的代码编译成字节码输出到target\test-classes,同时把src\test\resources下的配置文件拷贝到target\test-classes - package打包插件:maven-jar-plugin
这个插件是把class文件、配置文件打成一个jar(war或其它格式)包 - deploy发布插件:maven-install-plugin
发布插件的功能就是把构建好的artifact部署到本地仓库,还有一个deploy插件是将构建好的artifact部署到远程仓库
七、坐标gav
- maven把任何一个插件都作为仓库中的一个项目进行管理,用一组三维坐标来表示,这样可以唯一定位一个maven项目
- groupId:组织名,通常是公司或组织域名倒序+项目名
- artifactId:模块名,通常是工程名
- version:版本号
八、依赖dependency
- 一个Maven项目正常运行需要其它项目的支持,Maven会根据坐标自动到本地仓库中进行查找。对于程序员自己的Maven项目需要进行安装,才能保存到仓库中
- 不用maven的时候所有的jar都不是你的,需要去各个地方下载拷贝,用了maven所有的jar包都是你的,想要谁,叫谁的名字就行。maven帮你下载
九、Maven的依赖范围
maven的依赖范围包括:compile、provide、runtime、test、system
- compile:编译范围的依赖会用在编译、测试、运行、由于运行时需要,所以编译范围的依赖会被打包
- test:test范围在编译和运行时都不需要,只在测试编译和测试运行时需要。由于运行时不需要,所以test范围依赖不会被打包
- provide:provide依赖只有jdk或者一个容器以提供该依赖之后使用,provide依赖在编译和测试时需要,在运行时不需要
- runtime:runtime依赖在运行和测试系统时需要,但在编译时不需要。
- system:system范围依赖与provide类似
实例:
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<!--runtime表示编译器不使用它,运行期使用它-->
<scope>runtime</scope>
<version>8.0.17</version>
</dependency>
<!--导入servlet相关依赖,request不报错-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
<!--provided的意思是编译时使用它,运行时不使用-->
<scope>provided</scope>
</dependency>
<--jsp-->
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.0</version>
<scope>provided</scope>
</dependency>
<!--system 编译测试有用、不会运行打成jar-->
<dependency>
<groupId>com.sun</groupId>
<artifactId>tools</artifactId>
<scope>system</scope>
<optional>true</optional>
<version>${java.version}</version>
<systemPath>${java.home}/../lib/tools.jar</systemPath>
</dependency>
十、Maven的常用设置
- 全局设置:在Maven的pom.xml文件中,properties用于定义全局变量,pom中通过${property_name}的形式引用变量的值。定义全局变量:
<properties>
<spring.version>4.3.10.RELEASE</spring.version>
</properties>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
- maven系统采用的变量
<properties>
<!--源码编译jdk版本-->
<maven.compiler.source>1.8</maven.compiler.source>
<!--运行代码的jdk版本-->
<maven.compiler.target>1.8</maven.compiler.target>
<!--项目构建使用的编码,避免中文乱码-->
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<!--生成报告的编码-->
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
</properties>
- 指定资源位置:src/main/java和src/test/java这两个目录中的所有*.java文件会分别在comile和test-comiple阶段被编译,编译结果分别放到了target/classes和targe/test-classes目录中,但是这两个目录中的其他文件都会被忽略掉,如果需要把src目录下的文件包放到target/classes目录,作为输出的jar一部分。需要指定资源文件位置。以下内容放到buid标签中,即不能将src/mian/java和src/test/java中除java文件以外的文件编译到target目录中,可以使用在pom.xm中加入标签build进行设置
<resources> <!--资源文件的路径,默认位于${basedir}/src/main/resources/目录下--> <directory>src/main/resources</directory> <!--一组文件名的匹配模式,被匹配的资源文件将被构建过程处理--> <includes> <include>**/*</include> <include>*</include> </includes> <!--filtering默认false,true表示通过参数对资源文件中的${key} 在编译时进行动态变更。替换源可紧-Dkey和pom中的<properties>值 或<filters>中指定的properties文件--> <filtering>true</filtering> </resource> </resources>
- Maven中默认的属性:
${basedir} 项目根目录
${version}表示项目版本;
p r o j e c t . b a s e d i r 同 {project.basedir}同 project.basedir同{basedir};
p r o j e c t . v e r s i o n 表 示 项 目 版 本 , 与 {project.version}表示项目版本,与 project.version表示项目版本,与{version}相同; ${project.build.directory}
构建目录,缺省为target ${project.build.sourceEncoding}表示主源码的编码格式;
${project.build.sourceDirectory}表示主源码路径;
${project.build.finalName}表示输出文件名称;
${project.build.outputDirectory} 构建过程输出目录,缺省为target/classes
十一、Maven项目依赖、依赖冲突
- 什么是依赖传递
在maven中,依赖是可以传递的,假设存在三个项目,分别是项目A,项目B以及项目C。假设C依赖B,B依赖A,那么我们可以根据maven项目依赖的特征不难推出项目C也依赖A
- 什么是依赖冲突:
由于spring-webmvc中依赖了spring-core,而spring-core中依赖了commons-logging(1.1.3),而我们又引入了commons-loging1.2,就造成了冲突
- 依赖冲突的解决方式:
3.1 依赖调节原则:第一声明者优先原则(在pom文件中定义依赖,以先声明的依赖为准)
3.2 根据路径近者优先
3.3 如果在同一个pom中引入两个相同的jar包,以引入的最后一个为准
3.4 使用optional进行依赖可选,optional=true,依赖不会传递,该项目依赖A之后依赖该项目的项目如果想要使用A,需要重新引入。
3.5 可以使用exclusions标签将传递过来的依赖排除出去
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<exclusions>
<exclusion>
<groupId>org.skyscreamer</groupId>
<artifactId>jsonassert</artifactId>
</exclusion>
</exclusions>
</dependency>
3.6 版本锁定:
3.6.1:采用直接锁定版本的方法确定依赖jar包的版本,版本锁定后则不考虑依赖的声明顺序或依赖的
3.6.2:版本锁定的方式:
1.在dependencyManagement标签中锁定依赖的版本
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.glory</groupId>
<artifactId>glory-auth-entity</artifactId>
<version>${project.version}</version>
</dependency>
<dependencyManagement>
2.在dependencies标签中声明需要导入的maven坐标
- 分模块构建maven工程
4.1 分模块构建maven工程分析
不管是下面那种拆分方式,通常都会提供一个父工程,将一些公共的代码和配置提取到父工程中进行统一管理和配置
4.2 maven工程的继承
4.2.1: 被继承的maven工程通常被称为父工程,父工程的打包方式必须为pom,所以我们区分某个maven工程是否为父工程就要看这个工程的打包方式是否为pom
4.2.2:继承其他maven父工程的通常称为子工程,在pom.xml文件中通过parent标签进行父工程的继承
4.3 maven工程的聚合:
4.3.1: 在maven工程的pom.xml文件中可以使用标签将其他maven工程聚合到一起,聚合的目的是为了进行统一操作
4.3.2:例如拆分后的maven工程有多个,如果要进行打包,就需要针对每个工程分别执行打包命令,操作起来非常繁琐。这时就可以使用modules标签将这些工程统一聚合到maven工程中,需要打包的时候,只需要在此工程中执行一次打包命令,其下被聚合的工程就都会被打包了