Maven简介
什么是Maven
Maven
的本质是一个项目管理工具,将项目开发和管理过程抽象成一个项目对象模型 (POM
)
如图蓝色部分为 Maven
,其不包括外部其他部分,上部分为核心,下部分为各种插件。Maven
的作用如下
- 项目构建: 提供标准的、跨平台的自动化项目构建方式
- 依赖管理: 方便快捷的管理项目依赖的资源包,避免资源之间的版本冲突问题
- 统一开发结构: 规定了
src
、resource
、target
等统一项目结构
Maven
是由Java
语言编写的,同样采用了面向对象的思想
Maven安装
- 点击进入
Maven
官网进行下载 maven.apache.org/ - 解压文件到没有空格、没有中文的目录下
- 【可选】打开
maven目录/conf/settings.xml
配置文件,配置阿里镜像地址(配置到<mirrors>
标签里)
xml
<mirror>
<id>alimaven</id>
<name>aliyun maven</name>
<url>https://maven.aliyun.com/repository/central/</url>
<mirrorOf>central</mirrorOf>
</mirror>
- 【可选】配置环境变量:新建
MAVEN_HOME:Maven根目录
,修改Path添加%MAVEN_HOME%\bin
(注意:Maven
依赖环境变量中有JAVA_HOME
),CMD输入mvn -v
验证 - 【可选】因为Java默认的最大可用内存往往不够满足Maven运行需要,比如较大的项目时,使用Maven生成项目站点需要占用大量内存,可选配置
MAVEN_OPTS:-Xms128m -Xmx512m
注意
Maven
是由Java
研发的,所以Maven
依赖Java
Maven概念
仓库概念
:仓库用于存储资源(各种 Jar
包),其分为本地仓库 、远程仓库 、中央仓库
- 本地仓库: 自己电脑上存储资源的仓库
- 远程仓库: 也叫作
Maven
私服,部门/公司范围内储存资源的仓库 - 中央仓库:
Maven
团队维护的,维护所有资源的仓库
坐标概念
:坐标用于描述仓库中资源的位置,其构成部分及说明如下:
gourpId
:组织名,定义该Maven
项目隶属组织,常是域名反写,如org.example.demo
artifactId
:项目名,定义该Maven
项目名称version
:版本号,定义该Maven
项目的版本号packaging
:定义项目的打包方式,如成果物类型war
或jar
,如组织项目的pom
类型
Jar
包的获取会逐级搜索,如本地仓存在则直接使用本地仓,如不存在则到远程仓获取。以此类推
Maven使用
生命周期命令
命令 | 说明 |
---|---|
mvn archetype:generate |
创建 Maven 项目,可通过参数指定坐标等 可以使用骨架:常用7号 quickstart 普通项目,10号 webappWEB 项目 |
mvn clean |
把已经编译好的项目的所有信息清除(target 文件夹) |
mvn compile |
自动导入 POM 中的依赖,并把核心代码部分编译后,放置在 target 目录下 |
mvn test |
通过此命令可以执行 test 文件夹下的测试用的内容,实现项目测试(同时执行了 compile ) |
mvn package |
将 Maven 项目进行打包,放置在 target 目录下(同时执行了 test ) |
mvn install |
将刚刚项目打完的包安装到本地仓库,由 maven 进行管理(同时执行了 package ) |
mvn deploy |
项目发布,将 maven 本地库中管理的资源发布到远程库中 |
POM文件结构
xml
<!--当前项目的maven资源坐标-->
<groupId>org.example</groupId>
<artifactId>MVNDemo01</artifactId>
<version>1.0-SNAPSHOT</version>
<!--此项目在mvn package的过程中,要打成什么样的包,通常是jar或war,也可能是pom-->
<packaging>jar</packaging>
<!-- 项目相关信息 -->
<name>MVNDemo01</name>
<description>xxx</description>
<url>http://maven.apache.org</url>
<!-- 参数配置 -->
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<!-- 依赖管理 -->
<dependencies>
<dependency>
</dependency>
</dependencies>
<!-- 依赖版本管理 -->
<dependencyManagement>
</dependencyManagement>
<!-- 项目构建 -->
<build>
<plugins>
<plugin>
</plugin>
</plugins>
</build>
依赖传递
依赖是可以传递的,很有可能会发生依赖传递冲突问题,其优先级如下:
- 路径优先: 当依赖中出现相同的资源时(可能版本号不同),层级越浅,优先级越高
- 声明优先: 当资源在相同层级被依赖时,配置顺序考前的覆盖配置顺序靠后的
- 特殊优先: 当在同
POM
文件中声明时,后配置的覆盖先配置的
处理依赖传递有如下两种标签:
- 可选依赖: 控制引用该资源的项目无法看到该依赖
- 排除依赖: 主动排除掉该资源中的指定依赖
xml
<dependency>
<groupId>org.springframework</groupId>
<artifactId>springboot</artifactId>
<version>1.1</version>
<!-- 可选依赖(默认false,可传递) -->
<optional>true</optional>
<!-- 排除依赖 -->
<exclusions>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>bbb</artifactId>
</exclusion>
</exclusions>
</dependency>
依赖范围
依赖范围: 可以通过 <scope>
标签指定其依赖范围,其作用如下:
scope | 编译 | 测试 | 打包 | 范例 |
---|---|---|---|---|
compile(默认) | Y | Y | Y | log4j |
test | Y | junit(仅测试使用) | ||
provided | Y | Y | 不传递 | servlet-api(Tomcat中包含) |
runtime | Y | jdbc(可防止编写时意外导入) | ||
system | Y | Y | 插件配置 includeSystemScope | 依赖来自本地系统,需要配合标签 systemPath 使用 |
import | 引入依赖项目,配合 <type>pom</type> 使用 |
依赖范围具有传递性,开发时根据实际情况使用
插件使用
插件的使用可以通过官网查询,不同插件有不同使用方式,根据文档说明进行操作。如下简单示例源码插件配置
xml
<build>
<plugins>
<!-- 使用具体插件 -->
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.3.RELEASE</version>
<!-- 配置执行条件/位置:具体使用参考插件文档 -->
<executions>
<execution>
<!-- 操作目标,如下为主代码及test代码 -->
<goals>
<goal>jar</goal>
<goal>test-jar</goal>
</goals>
<!-- 插件执行阶段(生命周期哪个阶段) -->
<phase>generate-resources</phase>
</execution>
</executions>
</plugin>
</plugins>
</build>
多模块管理
Model聚合
聚合 用于快速构建 Maven
工程,一次性构建多个项目/模块。如多个项目/模块依赖,执行命令时需要每一个工程都进行编译,打包,安装,测试,部署等生命周期的命令,一个一个去执行这些命令效率非常低
Maven
提供了聚合的配置,实现统一执行命令,实现方法:创建一个无代码聚合工程,并在 POM
中配置所有聚合的项目/模块
xml
<!-- 打包类型为聚合 -->
<packaging>pom</packaging>
<!-- 配置模块名称 -->
<modules>
<!-- 标签内部值为子模组pom.xml所在路径 -->
<!-- 表示与自己同级的child1项目目录 -->
<module>../child1</module>
<!-- 表示为自己目录下child2项目目录 -->
<module>child2</module>
</modules>
只是聚合项目关心有什么模块,模块不需要知道被谁聚合了
Maven继承
Maven
项目提供继承 的特性,可以利用继承实现所有项目资源版本统一的问题。其继承的父类资源包括:
继承项 | 说明 |
---|---|
groupId version |
项目相关的内容。可以重写,默认父类的值 |
properties |
父级工程在 properties 标签中定义的变量,子工程使用 ${} 使用 |
dependencies |
相当于强制继承,子工程中一定被导入父工程该标签内的 Jar 包 |
dependencyManagement |
常用的一种统一资源的继承方式,只会继承版本而不会强制让子工程依赖资源 子工程通过在 dependency 内添加 groupId 和 artifactId 即可,当然也可以重写 version 版本号 |
build pluginManagement |
如上的一种统一资源的继承方式,其使用如上,不仅继承版本号,还会继承声明的使用方式 |
继承 的实现需要子项目声明父项目,注意 Maven
是单继承,其声明方式如下:
xml
<!-- 定义工程的父工程 -->
<parent>
<groupId>org.example.parent</groupId>
<artifactId>demo-parent</artifactId>
<version>1.0.0.RELEASE</version>
<!-- 填写父工程的POM位置,省略不写视为在父工程内/父工程为远程项目,仓库获取 -->
<relativePath>../parent/pom.xml</relativePath>
</parent>
只是子项目声明了父项目是谁,父项目不需要知道被谁继承了
属性管理
Maven
提供属性管理,其管理方式属性类型有:自定义属性 、内置属性 、Setting属性 、Java系统属性 、环境变量属性
xml
<!-- 定义自定义属性 -->
<properties>
<mybatis-plus.version>3.1.2</mybatis-plus.version>
<druid.version>1.1.17</druid.version>
</properties>
<!-- 使用自定义属性 -->
<version>${druid.version}</version>
<!-- 内置属性:含 ${basedir} ${version} 等 -->
<!-- Setting属性:配置文件 setting.xml 中的标签属性,属于动态属性,如 ${settings.localRepository} 等 -->
<!-- Java系统属性、环境变量属性:通过命令 mvn help:system 可以获取到属性 -->
Maven
提供资源加载属性值功能,其为项目内的其他资源文件使用定义的自定义属性,调用方式相同 ${}
使用如下
xml
<!-- 定义哪个文件夹下文件开启POM属性过滤功能,检测到 ${} 就替换属性 -->
<build>
<resources>
<resource>
<directory>${project.basedir}/src/main/resources</directory>
<filtreing>true<filtering>
</resource>
</resources>
</build>
版本管理含
RELEASE
和SNAPSHOT
,正式版、快照版
Maven
可以进行多环境配置参数,通过打包命令添加参数完成,可了解一下
Maven私服
【Nexus
】为常用私服,安装及使用绕道参考
常用插件使用
JDK版本
更改编译 Java
源码的 jdk
版本
xml
<!-- 通过更改项目的 pom.xml,添加 java 编译插件 -->
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>utf-8</encoding>
</configuration>
</plugin>
</plugins>
</build>
<!-- 或者在 properties 设置 jdk 版本 -->
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
更改 Maven
默认 的 JDK
版本,更改 Maven
目录下的 conf/settings.xml
文件,以后建立的项目源码编译都是指定的 jdk
版本
xml
<profile>
<id>jdk-1.8</id>
<activation>
<activeByDefault>true</activeByDefault>
<jdk>1.8</jdk>
</activation>
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<maven.compiler.compilerVersion>1.8</maven.compiler.compilerVersion>
</properties>
</profile>
各种常用插件
xml
<!-- Spring项目打包插件:可能和 appassembler-maven-plugin 不兼容 -->
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<!-- 测试插件:不写进行默认测试,这里配置了该插件跳过测试 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<skipTests>true</skipTests>
</configuration>
</plugin>
<!-- 应用不部署到远程仓库中 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-deploy-plugin</artifactId>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
Appassembler打包
Appassembler
打包有三种核心打包方式,其中常用打包为可执行程序 和守护服务 方式。如下介绍最为常用的守护方式,该方式可生成资源后直接在服务器中运行为服务
Appassembler
打包方式的优点:
- 通过
wrapper
方式进行管理,直接运行bin/
下的可执行文件start | stop | console | restart
- 分包管理
lib
依赖,其打包方式不会将所有依赖打包到一个可执行文件中,分包管理,方便更改部分jar
包代码,进行部分更新 - 管理资源文件,可以通过设置,让程序首先使用
conf/
文件夹下的资源/配置文件,当找不到时才找jar
包内资源 - 当更新程序时,操作步骤更为简单:
- 把需要更新的
jar
包覆盖到lib/
下 - 保证是否需要更新配置文件
conf/
- 运行可执行文件
xxx restart
重启服务
xml
<!-- 使用说明: -->
<!-- 1. 修改对应的项目名称 -->
<!-- 2. 修改属性值,输出文件夹目录 -->
<!-- 3. 修改启动类,如下 mainClass 标签 -->
<!-- 配置项目名称及属性,后期配置使用 -->
<name>demo</name>
<properties>
<appassembler.out.name>appassembler-out</appassembler.out.name>
</properties>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>appassembler-maven-plugin</artifactId>
<version>2.1.0</version>
<!-- 配置插件启动时机 -->
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>generate-daemons</goal>
</goals>
</execution>
</executions>
<configuration>
<!-- 打包后生成的目录位置及各目录 -->
<target>${project.build.directory}/${appassembler.out.name}</target>
<binFolder>bin</binFolder>
<logsDirectory>logs</logsDirectory>
<repositoryName>lib</repositoryName>
<!-- 为系统配置文件指定一个目录 -->
<configurationDirectory>conf</configurationDirectory>
<!-- 源代码中对应的系统配置文件的位置 -->
<configurationSourceDirectory>src/main/resources</configurationSourceDirectory>
<!-- 是否将配置文件包含到classpath -->
<includeConfigurationDirectoryInClasspath>true</includeConfigurationDirectoryInClasspath>
<!-- 是否拷贝源代码中配置文件中的目录 -->
<copyConfigurationDirectory>true</copyConfigurationDirectory>
<!-- 依赖的lib包的目录格式,flat表示不分目录平铺到lib目录下 -->
<repositoryLayout>flat</repositoryLayout>
<daemons>
<daemon>
<!-- 基本信息配置:名称及启动类 -->
<id>${project.name}</id>
<mainClass>org.example.Starter</mainClass>
<!-- JVM配置设置 -->
<jvmSettings>
<maxStackSize>128</maxStackSize>
<extraArguments>
<extraArgument>-server</extraArgument>
<extraArgument>-XX:+AggressiveOpts</extraArgument>
<extraArgument>-Xmx1G</extraArgument>
<extraArgument>-XX:+HeapDumpOnOutOfMemoryError</extraArgument>
</extraArguments>
</jvmSettings>
<!-- 打包平台配置 -->
<platforms>
<platform>jsw</platform>
</platforms>
<generatorConfigurations>
<generatorConfiguration>
<generator>jsw</generator>
<includes>
<!-- include>linux-x86-32</include -->
<!-- include>linux-ppc-64</include -->
<include>linux-x86-64</include>
<include>windows-x86-64</include>
</includes>
<configuration>
<!-- 手动添加一个系统启动时依赖的第一个classpath,这里通常写为配置文件的目录名,如果不配置,配置文件无法找到 -->
<property>
<name>configuration.directory.in.classpath.first</name>
<value>conf</value>
</property>
<!-- 依赖jar包位置 -->
<property>
<name>set.default.REPO_DIR</name>
<value>lib</value>
</property>
<!-- 日志文件位置 -->
<property>
<name>wrapper.logfile</name>
<value>logs/wrapper-${project.name}.log</value>
</property>
<!-- 日志文件格式:MB兆的方式格式 -->
<property>
<name>wrapper.logfile.format</name>
<value>M</value>
</property>
<!-- 日志文件最大值:10MB -->
<property>
<name>wrapper.logfile.maxsize</name>
<value>10m</value>
</property>
<!-- 日志文件最大分割值:5 -->
<property>
<name>wrapper.logfile.maxfiles</name>
<value>5</value>
</property>
<!-- 配置Windows服务:效果未检测 -->
<property>
<name>wrapper.ntservice.interactive</name>
<value>true</value>
</property>
</configuration>
</generatorConfiguration>
</generatorConfigurations>
</daemon>
</daemons>
</configuration>
</plugin>
该插件可能与
Spring Boot
打包插件冲突,如出现找不到主类清单错误,可选择注释掉Spring Boot
打包插件(spring-boot-maven-plugin
)
Assembly打包
Assembly
打包是 Maven
提供的一种打包方式,可以输出自定义的包类型。如上输出守护服务 的资源后,可以再通过该插件进行打包输出
xml
<!-- 集合打包插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<executions>
<execution>
<phase>package</phase>
<goals>
<!-- 只执行一次 -->
<goal>single</goal>
</goals>
</execution>
</executions>
<configuration>
<!-- 描述文件所在位置 -->
<descriptors>
<descriptor>src/main/assembly/assembly-linux.xml</descriptor>
<descriptor>src/main/assembly/assembly-win.xml</descriptor>
</descriptors>
</configuration>
</plugin>
描述文件用于描述输出文件,如下输出两个压缩文件(文件内容来自上个插件的输出结果)
xml
<!-- src/main/assembly/assembly-linux.xml -->
<assembly
xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2 http://maven.apache.org/xsd/assembly-1.1.2.xsd">
<id>linux</id>
<includeBaseDirectory>false</includeBaseDirectory>
<formats>
<format>tar.gz</format>
</formats>
<fileSets>
<fileSet>
<directory>${project.build.directory}/${appassembler.out.name}/jsw/${project.name}/bin</directory>
<outputDirectory>${project.name}/bin</outputDirectory>
<fileMode>0755</fileMode>
<includes>
<include>${project.name}</include>
<include>wrapper-linux*</include>
</includes>
</fileSet>
<fileSet>
<directory>${project.build.directory}/${appassembler.out.name}/jsw/${project.name}/lib</directory>
<outputDirectory>${project.name}/lib</outputDirectory>
<includes>
<include>*.jar</include>
<include>libwrapper-linux*</include>
</includes>
</fileSet>
<fileSet>
<directory>${project.build.directory}/${appassembler.out.name}/jsw/${project.name}/conf</directory>
<outputDirectory>${project.name}/conf</outputDirectory>
<includes>
<include>*.yml</include>
<include>banner.txt</include>
<include>wrapper.conf</include>
</includes>
</fileSet>
<fileSet>
<directory>${project.build.directory}/${appassembler.out.name}/jsw/${project.name}/logs</directory>
<outputDirectory>${project.name}/logs</outputDirectory>
<excludes>
<exclude>**/*</exclude>
</excludes>
</fileSet>
</fileSets>
</assembly>
xml
<!-- src/main/assembly/assembly-win.xml -->
<assembly
xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2 http://maven.apache.org/xsd/assembly-1.1.2.xsd">
<id>win</id>
<includeBaseDirectory>false</includeBaseDirectory>
<formats>
<format>zip</format>
</formats>
<fileSets>
<fileSet>
<directory>${project.build.directory}/${appassembler.out.name}/jsw/${project.name}/bin</directory>
<outputDirectory>${project.name}/bin</outputDirectory>
<fileMode>0755</fileMode>
<includes>
<include>${project.name}</include>
<include>wrapper-windows*</include>
</includes>
</fileSet>
<fileSet>
<directory>${project.build.directory}/${appassembler.out.name}/jsw/${project.name}/lib</directory>
<outputDirectory>${project.name}/lib</outputDirectory>
<includes>
<include>*.jar</include>
<include>libwrapper-windows*</include>
</includes>
</fileSet>
<fileSet>
<directory>${project.build.directory}/${appassembler.out.name}/jsw/${project.name}/conf</directory>
<outputDirectory>${project.name}/conf</outputDirectory>
<includes>
<include>*.yml</include>
<include>banner.txt</include>
<include>wrapper.conf</include>
</includes>
</fileSet>
<fileSet>
<directory>${project.build.directory}/${appassembler.out.name}/jsw/${project.name}/logs</directory>
<outputDirectory>${project.name}/logs</outputDirectory>
<excludes>
<exclude>**/*</exclude>
</excludes>
</fileSet>
</fileSets>
</assembly>
资源打包插件
Maven
项目默认资源在 src/main/resources
目录下,如果资源不在此目录下,需要添加 maven-resources-plugin
插件,并在 resource
中配置资源路径
xml
<!-- 资源打包插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
</plugin>
<!-- 配合 resources 插件添加资源目录 -->
<resources>
<resource>
<directory>src/main/resources</directory>
<!-- 打开变量替换声明 -->
<!-- filtering>true</filtering -->
</resource>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.xml</include>
</includes>
</resource>
</resources>
Tomcat插件
下面介绍的是 tomcat7
插件在 pom.xml
文件中的配置,端口默认是 8080
,path
默认是项目名称(可以在 configuration
标签内进行修改)。执行命令 mvn tomact7:run
运行
xml
<!-- 构建 -->
<build>
<plugins>
<!-- 添加tomcat服务器插件 -->
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.1</version>
<configuration>
<!-- 配置tomcat端口 -->
<port>8080</port>
<!-- Web应用的访问路径
<path>HelloWorld</path>
-->
<!-- 配置tomcat编码,解决GET乱码 -->
<uriEncoding>UTF-8</uriEncoding>
</configuration>
</plugin>
</build>
</plugins>
使用技巧
清理小工具
Maven
本地仓库同步的时候会产生很多不存在的 Jar
包下载准备文件,可以通过该命令行脚本进行清理,保存到 .bat
文件中,在 windows
双击使用
bash
set REPOSITORY_PATH=E:\MavenRepo
rem 正在搜索...
for /f "delims=" %%i in ('dir /b /s "%REPOSITORY_PATH%\*lastUpdated*"') do (
del /s /q %%i
)
rem 搜索完毕
pause