目录

Maven入门

目录

一、Maven是什么?

  • Maven是一个跨平台的项目管理工具。其主要服务于基于Java平台的项目构建、依赖管理和项目信息管理。

  • Maven基本功能:

    • 构建
    • 编译
    • 打包
    • 测试
    • 依赖管理(各种jar包)
  • Maven的特点:

    • 项目设置遵循统一的规则。

    • 任意工程中共享。

    • 依赖管理包括自动更新。

    • 一个庞大且不断增长的库。

    • 可扩展,能够轻松编写 Java 或脚本语言的插件。

    • 只需很少或不需要额外配置即可即时访问新功能。

二、Maven安装和配置

  1. 确定已安装jdk

  2. 下载安装

    • 访问官网下载页面, 下载系统对应版本的maven安装包,并解压。
      (PS:因为笔者是Windows系统,所以下载的是 apache-maven-3.6.3-bin.zip。)
  3. 配置环境变量

    • 在环境变量中添加变量 MAVEN_HOME,变量值为 C:\Java\apache-maven-3.6.3,
    • 并在已有变量 Path 中追加值 %MAVEN_HOME%\bin。
      (PS:变量值请大家自行更改为自己之前解压的目录路径。)
  4. 检查是否安装成功

    • 运行 CMD 打开命令行,输入mvn --version,若输出版本信息则为安装成功。
  5. 配置本地仓库(可选)

    • 在D盘,新建文件夹 maven-repository
    • 然后在 C:\Java\apache-maven-3.6.3\conf\settings.xml 文件中,将 <localRepository> 节点取消注释。
    • 并更改为 <localRepository>D:\maven-repository</localRepository>。
      (PS: 配置了本地仓库后,当我们从maven中获取jar包的时候,maven首先会在本地仓库中查找,如果本地仓库有则返回;如果没有则从远程仓库中获取包,并在本地库中保存。 本地仓库其实起到了一个缓存的作用,它的默认地址是 C:\Users\用户名.m2。)
  6. 配置阿里云镜像(可选)

    • 在 C:\Java\apache-maven-3.6.3\conf\settings.xml 文件中,的 mirrors 节点下添加下方代码。
      (PS:将MAVEN镜像路径添加阿里镜像,是为了提高jar包下载速度,默认的远程仓库maven中心仓库在国外,下载速度较慢)
      <mirror> 
      <id>nexus-aliyun</id> 
      <mirrorOf>*</mirrorOf> 
      <name>Nexus aliyun</name> 
      <url>http://maven.aliyun.com/nexus/content/groups/public</url> 
      </mirror>
      
  7. IDEA中配置maven(可选)
    步骤如下:

    • File => Settings => 输入框里输入Maven => 定位Maven选项
    • 在右侧,Maven home directory选择为解压目录
    • User settings file 选择解压目录下,conf文件夹下的settings.xml文件
    • Local repository,应该会按照settings.xml自动填写

三、Maven构建项目(命令行交互方式)

(一)命令行交互方式

  1. 打开 CMD 命令行,输入 mvn archetype:generate

  2. 命令行将输出一个模板列表,需要我们选择一个模板(Choose archetype)为基础来构建工程

  3. 我们可以键入列表前面的序号或关键字,来缩小模板选择范围或者直接选中模板,这里输入 webapp,筛选出web应用的模板

  4. 键入需要的 模板序号,来选择构建web项目的模板 org.apache.maven.archetypes:maven-archetype-webapp

  5. 选择模板的版本,输入序号回车。若模板只有一个版本,则会跳过这一步

  6. 接着输入项目的坐标:groupId(项目组织ID) 、 artifactId(项目ID)、 version(版本)、 package(包)

    • groupId:项目组织唯一的标识符,默认会对应JAVA的包的结构,是main目录里java的目录结构。
    • artifactId:项目的唯一的标识符,实际对应项目的名称,就是项目根目录的名称。
    • version:项目的版本,“1.0-SNAPSHOT”表示快照1.0版本,“1.0-release”表示发行版1.0
  7. 接着是确认属性配置(Confirm properties configuration),若信息无误,直接回车即可

  8. 可以看到,当前目录下多了一个以输入的artifactId来命名的文件夹

  9. 到此基本项目构建完成

(二)命令行非交互方式

  1. 直接在命令行中键入一下命令
    注意:1. 下面命令后面的 ^,表示换行接着输入,不能漏。 2.换行输入,提示符会变成 More?。
    mvn archetype:generate -DgroupId=com.zcz.webdemo2^
    -DartifactId=webdemo2^
    -DarchetypeArtifactId=maven-archetype-webapp^
    -DinteractiveMode=false
    
    mvn archetype:generate \    
    -DarchetypeGroupId=org.apache.flink \          //原型组ID
    -DarchetypeArtifactId=flink-quickstart-java \  //原型ID
    -DarchetypeVersion=1.6.1 \                     //原型版本
    -DgroupId=my-flink-project \    
    -DartifactId=my-flink-project \    
    -Dversion=0.1 \    
    -Dpackage=myflink \    
    -DinteractiveMode=false
    
  • 参数解释:
    • -DgroupId:输入的groupId
    • -DartifactId:输入的artifactId
    • -DarchetypeArtifactId:模板名称
    • -DinteractiveMode=false:不以交互式命令行的形式构建项目

四、Maven编译项目、测试项目、打包项目

  1. 在项目约定位置写好java代码之后,就要进行项目的编译 (PS:约定位置见后面的“默认约定”一节。)

  2. 编译先进入Maven项目根目录下,然后执行

    mvn compile
    
  3. 若之前以写过测试代码,这里可执行命令来测试 (PS:测试类及代码约定见后面的“默认约定”一节。)

    mvn test
    
  4. 打包项目,就是把编译完成的class文件,打到一个jar或者war包内

    mvn versions:set -DnewVersion=1.0.0         #修改版本号,自动设置所有本项目有关的pom.xml version
    mvn versions:commit                         #确认版本号,删除修改前pom版本备份
    mvn versions:revert                         #回退版本号,使用备份恢复原版本号
    mvn package
    
  5. mvn package 、 mvn install 、 mvn deploy区别

    packageinstalldeploy
    打包到项目target目录打包拷贝到本地仓库,供其他项目引用打包上传到远程仓库,需配置pom文件

五、关于pom.xml文件

  1. 刚刚构建的项目文件夹下有一个pom.xml文件。
      它是项目的描述文件,描述了项目的maven坐标,依赖关系,开发者需要遵循的规则,缺陷管理系统,组织和licenses,以及其他所有的项目相关因素,是项目级别的配置文件。
    (PS:最基础的pom文件,可以看这里 http://maven.apache.org/pom.html#The_Basics )

  2. web项目的pom.xml结构

    • 特别说明一下依赖节点(<dependency>)下的<scope>
        配置provided相当于compile,但是在打包阶段做了exclude的动作,也就是当我们打包的时候就不会把这个依赖加进去。最常见的是j2ee规范相关的servlet-api和jsp-api等jar包,一般Tomcat会提供,无需在打包到war包中,如果不配置为provided,把这些包打包到工程war包中,在tomcat6以上版本会出现冲突无法正常运行程序(版本不符的情况)。
    <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.0http://maven.apache.org/xsd/maven-4.0.0.xsd">  
    
        <!-- 模型版本。maven2.0必须是这样写,现在是maven2唯一支持的版本 -->  
        <modelVersion>4.0.0</modelVersion>  
    
        <!-- 公司或者组织的唯一标志,并且配置时生成的路径也是由此生成, 如com.winner.trade,maven会将该项目打成的jar包放本地路径:/com/winner/trade -->  
        <groupId>com.winner.trade</groupId>  
    
        <!-- 本项目的唯一ID,一个groupId下面可能多个项目,就是靠artifactId来区分的 -->  
        <artifactId>trade-core</artifactId>  
    
        <!-- 本项目目前所处的版本号 -->  
        <version>1.0.0-SNAPSHOT</version>  
    
        <!-- 打包的机制,如pom,jar, maven-plugin, ejb, war, ear, rar, par,默认为jar -->  
        <packaging>jar</packaging>  
    
        <!-- 帮助定义构件输出的一些附属构件,附属构件与主构件对应,有时候需要加上classifier才能唯一的确定该构件 不能直接定义项目的classifer,因为附属构件不是项目直接默认生成的,而是由附加的插件帮助生成的 -->  
        <classifier>...</classifier>  
    
        <!-- 定义本项目的依赖关系 -->  
        <dependencies>  
    
            <!-- 每个dependency都对应这一个jar包 -->  
            <dependency>  
    
                <!--一般情况下,maven是通过groupId、artifactId、version这三个元素值(俗称坐标)来检索该构件, 然后引入你的工程。如果别人想引用你现在开发的这个项目(前提是已开发完毕并发布到了远程仓库),-->   
                <!--就需要在他的pom文件中新建一个dependency节点,将本项目的groupId、artifactId、version写入, maven就会把你上传的jar包下载到他的本地 -->  
                <groupId>com.winner.trade</groupId>  
                <artifactId>trade-test</artifactId>  
                <version>1.0.0-SNAPSHOT</version>  
    
                <!-- maven认为,程序对外部的依赖会随着程序的所处阶段和应用场景而变化,所以maven中的依赖关系有作用域(scope)的限制。 -->  
                <!--scope包含如下的取值:compile(编译范围)、provided(已提供范围)、runtime(运行时范围)、test(测试范围)、system(系统范围) -->  
                <scope>test</scope>  
    
                <!-- 设置指依赖是否可选,默认为false,即子项目默认都继承:为true,则子项目必需显示的引入,与dependencyManagement里定义的依赖类似  -->  
                <optional>false</optional>  
    
                <classifier>jdk15</classifier>
    
                <!-- 屏蔽依赖关系。 比如项目中使用的libA依赖某个库的1.0版,libB依赖某个库的2.0版,现在想统一使用2.0版,就应该屏蔽掉对1.0版的依赖 -->  
                <exclusions>  
                    <exclusion>  
                        <groupId>org.slf4j</groupId>  
                        <artifactId>slf4j-api</artifactId>  
                    </exclusion>  
                </exclusions>  
    
            </dependency>  
    
        </dependencies>  
    
        <!-- 为pom定义一些常量,在pom中的其它地方可以直接引用 使用方式 如下 :${file.encoding} -->  
        <properties>  
            <file.encoding>UTF-8</file.encoding>  
            <java.source.version>1.5</java.source.version>  
            <java.target.version>1.5</java.target.version>  
        </properties>  
    
        ...  
    </project> 
    
  3. 其他项目信息配置、构建配置、分发配置、仓库配置、profile配置、环境配置等,参见官方文档描述

六、默认约定

  • Maven 提倡使用一个共同的标准目录结构,Maven 使用约定优于配置的原则,大家尽可能的遵守这样的目录结构。
  • 约定优于配置的设定一个是为了简化了配置文件的配置,另外也是为了规范maven工程的目录结构
目录|目的
:-:|:-:
${basedir}|存放pom.xml和所有的子目录
${basedir}/src/main/java|项目的java源代码
${basedir}/src/main/resources|项目的资源,比如说property文件,springmvc.xml
${basedir}/src/test/java|项目的测试类,比如说Junit代码
${basedir}/src/test/resources|测试用的资源
${basedir}/src/main/webapp/WEB-INF|web应用文件目录,web项目的信息,比如存放web.xml、本地图片、jsp视图页面
${basedir}/target|打包输出目录
${basedir}/target/classes|编译输出目录
${basedir}/target/test-classes|测试编译输出目录
TestXXX.java|Maven只会自动运行符合该命名规则的测试类
testFunction()|Maven只会自动运行测试类中的符合该命名规则测试方法
~/.m2/repository|Maven默认的本地仓库目录位置
  • 企业 Maven 依赖管理层次结构设计:https://zhuanlan.zhihu.com/p/109323847

七、常用命令和配置

  1. 安装jar到本地仓库;下载jar包
mvn spring-javaformat:apply            # 格式化代码 “Spring” style
#安裝jar到本地仓库
mvn install:install-file -Dfile=D:\git\Spring-boot-MSMQ-Demo-master\libs\MsmqJava.jar -DgroupId=ionic.Msmq -DartifactId=MsmqJava -Dversion=1.0 -Dpackaging=jar
mvn deploy:deploy-file -Durl=http://172.20.52.101:8081/repository/maven-releases/ -DrepositoryId=maven-release -Dfile=D:\git\Spring-boot-MSMQ-Demo-master\libs\MsmqJava.jar -DgroupId=ktest.ionic.Msmq -DartifactId=MsmqJava -Dversion=1.0 -Dpackaging=jar
mvn dependency:copy-dependencies   #复制所有依赖到target
mvn dependency:tree                #查看依赖树
mvn dependency:tree -Dverbose      #查看依赖树详细
mvn dependency:tree -Dverbose -Dincludes=groupId:artifactId:version
E:\tool\apache-maven-3.9.4\bin\mvn dependency:tree  -Dverbose -Dincludes=org.bouncycastle   #查看依赖树详细
E:\tool\apache-maven-3.9.4\bin\mvn dependency:tree -Dverbose  -s C:\\users\root\.m2\settings.xml -Dincludes=com.ibm.mq:com.ibm.mq.allclient:9.3.1.0 -DsocksProxyHost=127.0.0.1 -DsocksProxyPort=7890

#下载指定jar到本地仓库 可指定远程仓库-DremoteRepositories=https://mvnrepository.com/artifact/com.alibaba.fastjson2/fastjson2
mvn dependency:get -DgroupId=org.jline -DartifactId=jline -Dversion=3.20.0 -Dpackaging=jar
mvn dependency:get -Dartifact=org.apache.maven:maven-core:2.2.1:jar:sources -DremoteRepositories=http://repo1.maven.apache.org/maven2 -Ddest=./something.jar
#按pom.xml获取指定依赖
mvn dependency:copy-dependencies -f pom.xml   #pom.xml内容如下
    <?xml version="1.0"?>
    <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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
        <groupId>temp.download</groupId>
        <artifactId>temp-download</artifactId>
        <version>1.0-SNAPSHOT</version> 
        <dependencies>
        <!-- 需要下载什么jar包 添加相应依赖 其余部分无需在意-->

        </dependencies>
    </project>
  1. 打包构建配置
  • 可执行jar,并且依赖及配置等都打入一个jar包
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.example</groupId>
    <artifactId>demo</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>
    <build>
        <finalName>${project.name}-unexecutable</finalName>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-assembly-plugin</artifactId>
                <version>2.5.5</version>
                <configuration>
                    <finalName>${project.name}</finalName>
                    <archive>
                        <manifest>
                            <mainClass>com.example.Main</mainClass>
                        </manifest>
                        <!-- <manifestEntries> 配置jar包中的MANIFEST.MF文件内容,用于javaagent打包
                            <Premain-Class>org.example.Main</Premain-Class>
                            <Can-Redefine-Classes>true</Can-Redefine-Classes>
                            <Can-Retransform-Classes>true</Can-Retransform-Classes>
                            <Can-Set-Native-Method-Prefix>true</Can-Set-Native-Method-Prefix>
                        </manifestEntries> -->
                    </archive>
                    <descriptorRefs>
                        <descriptorRef>jar-with-dependencies</descriptorRef>
                    </descriptorRefs>
                    <appendAssemblyId>false</appendAssemblyId>
                </configuration>
                <!-- 此配置效果 打包执行mvn package即可不必加上assembly:single -->
                <executions>
                    <execution>
                        <id>make-assembly</id>
                        <phase>package</phase>
                        <goals>
                            <goal>single</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</project>
  • 可执行jar,但依赖及配置不打入jar包
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.example</groupId>
    <artifactId>demo</artifactId>
    <version>${revision}.${buildTime}-SNAPSHOT</version>

    <properties>
        <!--程序版本-->
        <revision>1.0.10</revision>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    
    <dependencies>
        <dependency>
            <groupId>xxx</groupId>
            <artifactId>xxx</artifactId>
            <version>xxx</version>
        </dependency>
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
            <version>3.17.0</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.36</version>
            <optional>true</optional>
        </dependency>
    </dependencies>

    <build>
        <finalName>${project.name}</finalName>
        <sourceDirectory>src/main/java</sourceDirectory>
        <testSourceDirectory>src/test/java</testSourceDirectory>
        <outputDirectory>target</outputDirectory>
        <plugins>
            <plugin>
                <!-- 指定jdk编译级别为jdk1.8,默认包含此插件可省略 -->
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <!-- <source>8</source> 由properties中maven.compiler.source指定,此处省略-->
                    <!-- <target>8</target> 由properties中maven.compiler.target指定,此处省略-->
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-jar-plugin</artifactId>
                <version>3.1.0</version>
                <configuration>
                    <outputDirectory>${project.build.directory}/${project.name}</outputDirectory>
                    <archive>
                        <addMavenDescriptor>false</addMavenDescriptor>
                        <!-- 打包jar文件时,配置manifest文件,加入lib包的jar依赖 -->
                        <manifest>
                            <mainClass>com.example.Main</mainClass>
                            <addClasspath>true</addClasspath>
                            <classpathPrefix>lib/</classpathPrefix>
                            <useUniqueVersions>false</useUniqueVersions>
                        </manifest>
                        <!-- 把配置文件目录加入到MANIFEST.MF的Class-Path中 -->
                        <manifestEntries>
                            <Class-Path>.</Class-Path>
                        </manifestEntries>
                    </archive>
                    <!-- 指定需要把哪些文件打入到jar包中,  -->
                    <!-- ** 代表jar包根目录 -->
                    <!-- **/com/ 代表jar包根目录下仅包含com目录(我所有的程序都在com包下), 当然打好之后还会包含生成的manifest目录 -->
                    <!-- 注意com后面的/一定不要省去,不然maven会认为这是一个文件名 -->
                    <!-- includes或者excludes一定要指定,不然会把target下所有的文件都打进去 -->
                    <includes>
                        <include>**/com/</include>
                    </includes>
                    <excludes>
                        <exclude>**/mappings/</exclude>
                    </excludes>
                </configuration>
            </plugin>
            <!-- 拷贝依赖的jar包到lib目录 -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-dependency-plugin</artifactId>
                <version>3.1.0</version>
                <executions>
                    <execution>
                        <id>copy</id>
                        <phase>package</phase>
                        <goals>
                            <goal>copy-dependencies</goal>
                        </goals>
                        <configuration>
                            <!-- 拷贝依赖的jar包到lib目录 -->
                            <outputDirectory>
                                ${project.build.directory}/${project.name}/lib
                            </outputDirectory>
                            <!-- 功能未知待学习<overWriteReleases>false</overWriteReleases>
                            <overWriteSnapshots>false</overWriteSnapshots>
                            <overWriteIfNewer>true</overWriteIfNewer> -->
                        </configuration>
                    </execution>
                </executions>
            </plugin>
            <!-- 解决资源文件的编码问题 -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-resources-plugin</artifactId>
                <version>3.1.0</version>
                <configuration>
                    <encoding>UTF-8</encoding>
                </configuration>
                <executions>
                    <execution>
                        <id>copy-resources</id>
                        <phase>package</phase>
                        <goals>
                            <goal>copy-resources</goal>
                        </goals>
                        <configuration>
                            <encoding>UTF-8</encoding>
                            <outputDirectory>${project.build.directory}/${project.name}</outputDirectory>
                            <resources>
                                <resource>
                                    <directory>src/main/resources</directory>
                                    <filtering>true</filtering>
                                    <includes>
                                        <include>*</include>
                                    </includes>
                                </resource>
                            </resources>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
            <!-- 打包source文件为jar文件 -->
            <plugin>
                <artifactId>maven-source-plugin</artifactId>
                <version>3.1.0</version>
                <configuration>
                    <attach>true</attach>
                </configuration>
                <executions>
                    <execution>
                        <phase>compile</phase>
                        <goals>
                            <goal>jar</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
            
            <!-- maven-surefire-plugin 用于配置执行JUnit单元测试 -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-plugin</artifactId>
                <version>3.0.0-M1</version>
                <configuration>
                    <!-- 跳过单元测试-->
                    <skip>true</skip>
                </configuration>
            </plugin>
            
            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>buildnumber-maven-plugin</artifactId>
                <version>1.2</version>
                <executions>
                    <execution>
                        <id>generate-timestamp</id>
                        <phase>validate</phase>
                        <goals>
                            <goal>create-timestamp</goal>
                        </goals>
                        <configuration>
                            <timestampFormat>yyyyMMddHHmmss</timestampFormat>
                            <timestampPropertyName>buildTime</timestampPropertyName>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
            <!--            https://www.mojohaus.org/flatten-maven-plugin/plugin-info.html-->
            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>flatten-maven-plugin</artifactId>
                <version>1.5.0</version>
                <configuration>
                    <updatePomFile>true</updatePomFile>
                    <flattenMode>resolveCiFriendliesOnly</flattenMode>
                </configuration>
                <executions>
                    <execution>
                        <id>flatten</id>
                        <phase>process-resources</phase>
                        <goals>
                            <goal>flatten</goal>
                        </goals>
                    </execution>
                    <execution>
                        <id>flatten.clean</id>
                        <phase>clean</phase>
                        <goals>
                            <goal>clean</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</project>
  1. 基础Maven项目工程文件夹构建
mkdir -p src/main/java/com/example
mkdir -p src/main/resources
echo > src/main/java/com/example/Main.java
nano pom.xml   //写入构建的pom.xml

七、推荐书籍

← 返回技术