Maven学习与理解(彻底理解Maven)

文章目录

Maven学习与理解

Maven 安装

官网下载

官网下载地址,在Files下选择自己要下载的,一般选择Binary zip archive

Mac上下载

Mac 上通过homebrew安装即可

brew update
brew search maven
# 选择想要安装的版本
brew install maven

安装

安装文档详见官方文档,Windows和Mac下的安装步骤都有.就是为当前机器配置下环境变量

验证是否安装成功

mvn -v

如果打印出Maven版本,Maven安装路径,以及Java版本信息,则代码安装成功。

这也说明Maven运行是依赖于Java的。关于这一点还有其他佐证,首先Maven是用Java写的,如果不清Maven使用Java写的,官方文档Configuring Apache Maven里曾经提到过这么一句话也可以证明

This variable contains parameters used to start up the JVM running Maven

如何为Maven设置要使用的Java版本?

修改JAVA_HOME环境变量即可

如何为Maven设置JVM参数?

使用MAVEN_OPTS环境变量

在IDE上配置Maven

eclipse和idea配置文档详见这里

快速创建Maven项目及了解Maven项目标准结构

  1. 快速创建一个Maven项目的脚手架

    mvn -B archetype:generate -DgroupId=com.mycompany.app -DartifactId=my-app -DarchetypeArtifactId=maven-archetype-quickstart -DarchetypeVersion=1.4
    

    执行完此命令,会生成一个Maven项目。文件夹的名字是my-app

  2. 一个Maven项目的标准结构为
    在这里插入图片描述

    官方文档关于maven项目标准结构的说明,上图所示的文件夹不一定都有,但是起码要保证主要的一部分有,如src/main/java、src/main/resources、src/test/java、src/test/resources、pom.xml

    普通的maven项目,一般pom文件和src文件夹平级

Maven生命周期

上面使用了一长串的命令,生成了一个Maven基本项目.具体命令的每一项都什么意思呢?首先要了解Maven的整体构成。

场景

在刚刚使用Maven或者平时工作中仅仅是添加一些所需依赖这些操作,有的时候需要我们为项目配置单独的插件、又或者打包Maven项目时进行一些额外的操作。如果不理解Maven的整体构成,那么一般的操作是

  • 打开百度
  • maven如何XXX命令?
  • 找到一堆博客文章、开始复制命令、执行
  • 执行报错、执行错误,接着继续找
  • 直到找到正确的命令

不仅浪费了大把时间,而且这种零散性的知识输入,不利于我们彻底解决问题。下次碰到类似的场景只有接着百度,并不会举一反三

Lifecycle-生命周期划分

对于Maven来说,其最大层次是Lifecycle-生命周期。

官方关于Lifecycle完整文档地址

Maven有三种生命周期,default、clean、site.其中我们平时项目中用到的生命周期大多数是default.最后一种site生命周期基本用不上.我们只需要记住Maven是以生命周期作为最大层次的

Phrase-阶段划分

一个生命周期由许多Phrase组成.

例如default生命周期一般由7个主要阶段组成

  • validate 验证项目是否正确
  • compile 编辑项目源代码
  • test 运行单元测试
  • package 打包
  • verify 继承测试
  • install 将验证过得包放入我们机器的本地仓库
  • deploy 将打好的包发布到远程仓库

这几个阶段是线性执行的,也就是说,即使只执行install,那么在真正执行install之前,必须经过前面几个步骤
在这里插入图片描述

注意:为什么说是7个主要阶段?因为对于default生命周期来说,完整的阶段远不止7个,但是这几个阶段是比较具有代表性的。完整的阶段详见官方Deault Lifecycle列表

执行某个阶段

上面说到,Maven的结构是lifecycle-phrase,所以,执行Maven命令时也是按照这个顺序执行

执行格式为:

mvn phrase(mvn+要执行到的具体阶段)

phrase可以是多个,例如mvn clean package,这里要执行两个阶段,clean阶段,package阶段,clean是处于clean生命周期的,package是处于default生命周期的。Maven会根据具体的阶段判断其位于哪个生命周期内。所有生命周期的所有阶段见上述的Lifecycle列表链接·

# mvn后面跟具体要执行到的阶段
mvn package

Maven阶段(phrase)与目标(goal)

上面已经说了,Lifecycle是最高层,它的下一级就是Phrase-阶段。具体执行Maven命令都是以phrase-阶段为基本单位的,而在每个阶段-phrase都有其对应的目标goal,goal就是再明确一下在当前阶段要做的事情是哪些?

有个对应的目标-goal,那么实现goal是由谁来完成呢?不是由maven完成,而是由第三方插件来完成,所以Maven有丰富的三方插件库,用来执行在不同的阶段实现不同的目标

所以具体执行命令的基本单位从phrase变为了goal。

具体格式为:

mvn 插件名字:插件的目标

mvn Plugin:goal

疑问:为什么我们平时执行一些命令(如:mvn package、mvn install)不是这种形式的?

那是因为一些生命周期的一些阶段默认会绑定对应的插件和目标,所以不需要显示的写成这种形式。对应的官方文档

如mvn package 实际上是 mvn jar:jar

如mvn install 实际上是mvn install:install
在这里插入图片描述

Maven插件

前面说过,mvn在实际执行过程中,会根据对应的插件执行对应的目标.maven插件列表
在这里插入图片描述

可以看到,第一句话也印证了我们说的,mvn的实际工作都是由插件完成的.配置插件一般需要在pom.xml文件中的元素内配置,不会有的情况也需要在元素内配置。

在Maven的插件列表中根据自己实际需要,在Description找到符合自己需要的插件,点击Plugin对应的单元格内容,会跳转到具体插件的详情页面,一般会说明此插件会在那个阶段执行,根据文档配置即可.

插件使用举例

举例说明:在实际工作中,一般项目的jar包经过编译、构建、打包会自动发布到公司的Maven私有仓库。有的时候我们想要把自己本地打的jar包,发布到公司的Maven私有仓库中,如何操作呢?

现在的需求是:发布jar包到Maven仓库

在maven 插件列表找到符合我们需求的描述
在这里插入图片描述

点击deploy名字。跳转到插件详情的页面
在这里插入图片描述
可以看到,此插件作用于default生命周期的deploy阶段,发布到远程仓库,还可以把第三方jar包发布到远程仓库,然后用生成对应pom文件.

同时还可以看到,此插件有两个目标,deploy,deploy-file

在左侧的Usage的部分,可以查看如何使用。
在这里插入图片描述
可以看到,在使用页面,文档详细描述了,这两个goal分别应该使用的场景。大多数情况下我们直接使用mvn deploy默认的目标就是deploy:deploy,需要在pom.xml文件中配置仓库的信息、同时在全局setting.xml文件中配置server。配置完成之后即可直接使用mvn deploy命令将pom文件发布到远程仓库

而对于deploy-file,则是当项目不是由Maven构建的,或者说一种实际中最多的情况,项目中用到了一个三方jar包,可是这个三方jar包没有对应Maven的pom,而我们的项目又是Maven项目,这时就可以将三方jar下载下来,手动deploy到远程仓库,这样就会默认生成该jar包的pom文件,这样我们就可以在pom.xml中引用了。

mvn deploy:deploy-file -Durl=repositoryUrl -DrepositoryId=repositoryId -Dfile=my-app.jar -DgoupId=com.mycompany.app -DartifactId=my-app -Dversion=1.0
-Dpackaging=jar

url:Maven私服的地址

repositoryId:Maven私服服务器的ID

file: jar包位置

groupId、artifactId、version都是必输

packaging:打包格式

默认会生成该jar包的对应的pom文件
在这里插入图片描述

所以,在实际使用过程中,对于具体的场景,根据我们的需求,可以配置对应的插件。这么多插件我们当然记不住,最终也还是避免不了百度。但是我们只需要找到符合我们需求的插件名字即可,然后在Maven的插件列表搜索名字,根据文档进行配置即可。而不是从头到尾的流程,都依赖网上的一些文章。而且现实情况大多是是网上的文章不靠谱的很多,而且抄袭现象严重,特别浪费我们的时间

在pom文件中配置插件(pluginmanagent和plugins区别)

插件配置官方文档详细说明如何配置插件,包括在execution标签内为插件指定生效的阶段-phrase,还有插件执行的目标-goal

如果找到对应的插件文档,一般文档都会给出默认的如何配置,不过基本所有的maven插件配置都遵循一定的规则。

一般插件都配置在标签内pluginManagement下的,并且每个插件都要至少有groupId、artifactId、version

例如配置执行test单元测试的插件surefire

<build>
    <pluginManagement>
      <plugins>
        <plugin>
          <!--插件必须有groupId、artifactId、version-->
          <groupId>org.apache.maven.plugins</groupId>
          <artifactId>maven-surefire-plugin</artifactId>
          <version>2.22.2</version>
        </plugin>
      </plugins>
    </pluginManagement>
     <plugins>
        <plugin>
          <!--插件必须有groupId、artifactId、version-->
          <groupId>org.apache.maven.plugins</groupId>
          <artifactId>maven-surefire-plugin</artifactId>
          <version>2.22.2</version>
           <configuration>
            <skipTests>true</skipTests>
          </configuration>
        </plugin>
      </plugins>
  </build>

有的插件需要配置excutions标签内容,用来指明该插件在哪个阶段,执行哪个目标。·

这里要注意和的区别。pluginManagent一般声明在父pom文件中,当子pom要用到对应的插件时,在plugins标签中声明即可,不需要version,pluginManagent只做声明,具体要使用插件还是要在plugins标签中引入

如果是做了声明,没有引入,那么是找不到该插件的.

还有一种情况平时犯错误比较多的就是,用插件的时候,直接写在了pluginManagent标签里。那么此时是找不到插件的

在这里插入图片描述

如这里,assembly插件直接在pluginManagent标签中进行了使用,是无效的。还可以结合idea的面板来判断插件是否生效
在这里插入图片描述

可以看到,我们在pluginManagent中虽然进行了配置,但是idea的插件下没有我们配置的插件,说明配置未生效

把pluginManagent标签配置去掉或者在同级别下使用plugins进行配置
在这里插入图片描述

这次才是正确的配置

如何跳过单元测试?

要说明的是,一般情况下不要跳过单元测试,单元测试是非常重要的一项。

负责单元测试的插件就是上面的surefire插件。跳过单元测试的配置


<properties>
  <skipTests>false</skipTests>
</properties>

<build>
   <plugins>
     <plugin>
       <groupId>org.apache.maven.plugins</groupId>
       <artifactId>maven-surefire-plugin</artifactId>
       <version>2.22.2</version>
       <configuration>
         <skipTests>${skipTests}</skipTests>
       </configuration>
     </plugin>
   </plugins>
</build>

使用命令:

运行单元测试

mvn test

跳过单元测试

# 可以看到这里的-D后的属性就是在pom文件中properties标签中自定义的skipTests的标签,这里传进去是true
# 这个属性名字可以随便取,所以,以后要是被问到使用surefire跳过单元测试的命令怎么写,不一定是这种写法,要看属性里配的是什么
mvn -DskipTests=true

第二种写法

# 这种写法是直接跳过test的编译、运行,不建议使用这种方式。因为如果改了代码,有的test测试不一定能够启动,而且平时一般都是要求test单元测试要过的。这种直接跳过编译的方式不可取
mvn -Dmaven.test.skip=true

只执行一部分单元测试

<plugin>
   <groupId>org.apache.maven.plugins</groupId>
   <artifactId>maven-surefire-plugin</artifactId>
   <version>2.22.2</version>
    <configuration>
      <includes>
        <include>SimpleServletTest.java</include>
      </includes>
    </configuration>
</plugin>

关于只执行部分单元测试的文档

Maven pom文件结构

pom:Project Object Model

前面说了那么多,终究还是没有进行实际的pom文件的配置。这里,将对pom文件进行配置。一旦理解了前面的生命周期、阶段、插件、目标的关系、以及Maven的实际工作都是依赖插件和目标完成的,那么配置pom文件就是得心应手。

pom文件整体文档介绍

pom文件基本结构

pom文件的必备元素标签

<preject>
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.mycompany.app</groupId>
  <artifactId>my-app</artifactId>
  <version>1.0.0</version>
</preject>

完整的artifact名字是::,对应的就是com.mycompany.app:my-app:1

默认包类型是jar
在这里插入图片描述
version中如果带有SNAPSHOT则代表此版本为开发版本,不保证其可靠性。项目中应该减少此version的依赖的引用,应该使用正式版本

pom依赖version管理

官方文档

实际应用场景中,一个pom文件的依赖可能几十上百个,那么每个依赖都有对应的version,当要修改一个依赖的version时,要在Maven里全局搜索,再改,十分麻烦,而且不利于我们查看关于项目的整体依赖了哪些。所以一般经具体依赖的版本都放置在pom文件的上面,可以方便看到

使用如下:

<properties>
  <fast.json.version>3.1.0</fast.json.version>
  <mysql.version>8.0.0</mysql.version>
</properties>

<dependencies>
  <dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fast.json</artifactId>
    <version>${fast.json.version}</version>
  </dependency>
</dependencies>

将自定义的version标签放置在标签内。

注意:properties不仅可以做这个用途,还可以接收maven执行命令时的具体参数的属性

如:

mvn package -DskipTests=true

这里的-D后面的这个部分,肯定是要在peroperties中定义了标签的

规则是:

  • 定义<具体依赖+version>标签,在标签中指定我们使用的版本
  • 在具体依赖的标签中引用我们定义的标签,格式为${标签名字}

pom文件的依赖管理(dependencyManagent和dependencies的区别)

关于pom的依赖管理详情可参考maven官方关于依赖管理的文档

实际场景中,一家公司的项目可能有N个,但是这N个项目都使用到了部分相同的依赖,比如都用到了MySQL的驱动、都用到了的Druid数据源、都用到了springboot,为了统一的依赖管理。可以将这些公共的部分抽成一个上级pom,所有项目公共的部分都依赖于此pom,至于项目中用到的其他依赖,可以自行添加.

这里要说明,为什么要统一依赖管理?根据实际的经验教训,原因有几个,举例说明

  1. 如果每个项目使用到的springboot版本不一致,特别是现在微服务盛行的时代下,那么当后期需求产生变化,很可能两个不相干的项目就要彼此进行交互,那么由于springboot的版本不一致,很可能出现项目A提供给项目B的接口,项目B使用报错。那么此时,要统一springboot版本依赖,但是,更糟糕的事情发生了,一旦某个项目版本一改,可能引起此项目的其他部分出现大量的不可用。那么为了防止这种尴尬的局面,要从项目一开始创建的时候就要统一好依赖,特别是这种公共的,每个项目都在用的依赖
  2. 就算没有上面的问题,那么实际工作中,公司一般都有Maven私服,那么当同一个框架,N个不同项目使用N个不同的版本,那么此时Maven私服中必然会存在大量相同框架的pom,一是浪费Maven私服的服务器存储空间,二是,当要清理Maven私服时,面对这么多不同版本的pom,我如何确定该清理哪个?一旦项目多了之后,谁敢保证,清理了某一个版本的pom不会引起问题。如果统一依赖,则相同框架的pom只会存在一个,大大减少了存储空间,并且这种公共的pom升级时,必然是全平台统一升级,升级之后,直接清理原理的pom即可

使用示例:

定义一个公共的pom用来管理公共的依赖

parentPom.xml

<!--父pom的package类型为pom-->
<packaging>pom</packaging>

<properties>
  <fast.json.version>3.1.0</fast.json.version>
  <Druid.version>3.0.0</Druid.version>
  <!--...省略其他依赖版本配置-->
</properties>

<dependencyManagement>
  <dependencies>
     <groupId>com.alibaba</groupId>
     <artifactId>fast.json</artifactId>
     <version>${fast.json.version}</version>
  </dependencies>
  <!--...省略其他公共依赖-->
</dependencyManagement>

  <dependencies>
     <groupId>com.alibaba</groupId>
     <artifactId>Druid</artifactId>
     <version>${Druid.version}</version>
  </dependencies>

在项目A创建时中引用父pom中的依赖

<project>
  <modelVerson>4.0.0</modelVerson>
  
  <!--在子项目中声明父pom的信息-->
  <parent>
     <groupId>com.mycompany.myapp</groupId>
     <artifactId>my-parent</artifactId>
     <version>1.0.0</version>
  </parent>
  
  <!--具体子项目的配置信息-->
  <groupId>com.mycompany.app</groupId>
  <artifactId>my-app</artifactId>
  <version>1.0.0</version>
</project>

疑问:在父pom文件中,有两种依赖的声明方式,一种是dependency是在dependencyManagment标签内的,另外一种是直接在dependencies标签内的,那么这两种方式有什么不同呢?

答:区别如下

  • 在父pom文件中在<dependencyManagent>标签内的依赖,子module默认不会继承该依赖,当子module中引入了依赖、并且该依赖在父pom文件中存在、并且子module对于该依赖未声明version时,此时会继承父依赖的version

  • 在父pom文件中直接在<dependencies>标签下声明的依赖,子module默认会继承该依赖。当子module的pom文件显示声明该依赖时,必须指明版本(version),否则会报错
    在这里插入图片描述

如图,这是父pom的依赖,那么对应的子pom是如何的呢?
在这里插入图片描述

可以看到,虽然父pom中有两个依赖,但是fastJson的依赖时在dependencyManagent标签内的,所以子module默认不会继承,只会继承junit,并且父子版本一致

当我们在子module中依赖fastjson时,没有声明版本,默认会继承父pom
在这里插入图片描述
而当子module中显示声明了父pom中强制继承的依赖时,必须指定version,否则会报unknown的错误
在这里插入图片描述

引用不同依赖,都有不同的版本的某些依赖怎么处理?

什么意思呢?举个例子,当我们引用框架A的依赖后,发现A中有guava的依赖,而我们的项目中也有guava的依赖,并且两个版本不一致,那么此时在项目是使用guava时,具体使用哪一个呢?这里就用到了在dependency标签中的exclusions

当多个版本的依赖冲突时,使用exclusions进行排除,排除我们不想用的版本即可

dependency中的scope

官方关于scope的说明文档

一共有6中scope

  • compile 如果没有显示的声明,则当前依赖为compile。即在编译阶段就需要此依赖,否则可能出现编译不过的情况
  • provided 由具体容器提供
  • runtime 表示此依赖在编译时可以缺失,但是在项目运行时是必须的
  • test 表示这个依赖在正常项目运行时,没什么影响,仅仅是在test阶段是必须的
  • system 这个标签一般用来引入项目路径中的额外jar包,比如有些jar包时放在项目lib文件中的,运行时也需要这些jar包
  • import 这个标签一般不常用,必须是在<dependencyManagent>标签内使用,type必须是pom类型使用场景也不好举例。例如:我们现有的子pom文件依赖的父pom文件,是公司自己的。但是,此时呢,我们又需要spring-boot的依赖,而pom文件是单继承的,也就是说,只能有一个<parent>,那么此时使用spring-boot依赖按照正常思路,只能在<dependency>中一个一个声明,这样的坏处时,每一个声明,都需要写版本,能不能把spring-boot的dependencyManagent也加入进来呢,这样,我们具体依赖的时候,则不需要每个依赖都声明版本
    spring官方文档对于import的说明 以及这位博主更加简短的说明
<dependencyManagement>
    <dependencies>
      <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-dependencies</artifactId>
        <version>2.3.3.RELEASE</version>
        <type>pom</type>
        <scope>import</scope>
      </dependency>
    </dependencies>
  </dependencyManagement>
  <dependencies>
    <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.1.3</version>
        </dependency>
   </dependencies>

如上面这样,我们就可以使用父类中的dependencyManagent,也能使用spring-boot的dependencyManagent
关于spring-boot-dependencies和spring-boot-parent的区别可以自行查资料了解。其实二者没什么不同。只不过看开发者使用喜好以及实际公司maven组织情况(如果公共的父pom不是spring-boot-parent,可能会使用spring-boot-dependencies)。

继承和聚合

继承和聚合的官方文档

继承是指,有一些项目有一个公共的pom依赖

聚合是指,一个项目由多个模块组成

上面截图的工程,我们同时运用了继承和聚合。

Maven常见场景需求

mvnw是什么? / 如何指定项目使用特定版本的Maven?

使用mvnw

什么时候使用Optional?

Stackoverflow回答

如何使用Maven命令快速搭建一个Maven项目脚手架?

最前面创建Maven项目时,发了一大堆命令,除非天天背,如果偶尔要用一下,谁也想不起来具体命令是什么。那怎么办呢?

通过前面的了解,Maven都是由具体插件:目标完成工作的,我们只需要记住搭建Maven脚手架的插件即可

插件名字是archetype

具体声明Maven项目,只需要执行对应的目标generate即可

mvn archetype:generate

接下来会有交互的页面。

会提供多种Maven项目模式供我们选择(包括J2EE、springboot等),只需要输入模式前面的序号即可。默认模式是maven-archetype-quickstart模式
在这里插入图片描述

接下来要求填写groupId、artifactId、version
在这里插入图片描述

确认无误输入Y确认,此时项目已经生成了。可以看到相较于开篇的一大堆命令,我们这里只需要使用mvn archetype:generate接下来根据提示完成即可。简单好用

如何使用Maven命令快速搭建一个多模块-module的Maven项目脚手架?

上面说了,快速搭建一个Maven项目的命令,多模块的项目同理。执行多次命令即可

下面的步骤是紧接着上面创建好的Maven项目步骤的

  • cd pom文件所在的目录

  • rm -rf src

  • vim pom.xml

  • 打包格式修改位pom格式 pom

  • esc键,:wq

  • 接着执行上面快速创建Maven项目的命令

  • 在groupId时输入相同的groupId

  • artifactId输入自定义的名字

  • 最终生成项目完毕时,发现此时生成的项目的pom和父pom文件中发生了一点小变化
    在这里插入图片描述
    在这里插入图片描述

多module的项目如何根据不同的环境(Profile)使用不同的module?

假如Maven项目有多module,但是这些module并不都是必须的。比如有三个module A, B,C。其中A是必须的,本地开发时我们只需要B,在测试环境时需要B和C,如何实现这种需求呢?

使用Maven的Profile,在项目根路径下的pom文件中使用如下声明

   <modules>
		<module>message-common</module>
   </modules>
   <profiles>
        <profile>
            <id>dev</id>
            <activation>
                <activeByDefault>true</activeByDefault>
            </activation>
            <modules>
                <module>business-server</module>
            </modules>
        </profile>
        <profile>
            <id>test</id>
            <modules>
                <module>message-server</module>
                <module>business-server</module>
            </modules>
        </profile>
    </profiles>

在测试环境时,使用-P选项指定active为test

mvn clean install -Ptest

在IDEA中 > Maven tab下可以展开Profiles > 勾选要使用的Profile即可
在这里插入图片描述

如何过滤resource下的一些文件?/ 在打包时用pom文件里的属性替换指定文件里的${value}?

对于排除或者包含其他resource文件,见resouce plugin include-exclude一节

使用插件maven-resource-plugin并设置filtering为true,即可在打包时用pom文件里的属性替换指定文件里的${value}。具体使用示例详情见文档

要说明的是,官方建议将要过滤的文件放到其他目录
在这里插入图片描述

如何跳过单元测试?

使用单元测试插件surefire插件,在configuration标签配置好属性后,并在properties标签中自定义标签属性,执行命令时传入此属性即可

mvn install -DskipTests=true

Maven默认打包命令打出的jar包时可以通过java -jar执行的吗?

单纯的mvn package 绑定的插件目标打的jar包不能通过java -jar 执行,现在基本都是springboot,默认使用的都是springboot的打包插件(关于SpringBoot是如何处理可执行Jar包的细节,请移步官方文档executable-jar部分),但还是觉得有必要说一下

在刚才生成的maven项目中执行mvn package命令,使用java -jar执行时
在这里插入图片描述

提示此jar包没有主清单属性,什么是主清单属性

就是没有指定运行时MainClass

如何打出可执行的jar包?(或者java -jar执行jar包时出席那没有主清单属性如何处理)

使用assembly插件

配置插件

<build>
  <plugins>
     <plugin>
          <groupId>org.apache.maven.plugins</groupId>
          <artifactId>maven-assembly-plugin</artifactId>
            <configuration>
<!--            将项目依赖打入jar包-->
            <descriptorRefs>
              <descriptorRef>jar-with-dependencies</descriptorRef>
            </descriptorRefs>
            <archive>
<!--              指定主类-->
              <manifest>
                <mainClass>com.mycompany.app.App</mainClass>
              </manifest>
            </archive>
          </configuration>
<!--          设置插件执行阶段和目标-->
          <executions>
            <execution>
              <id>make-assembly</id>
              <phase>package</phase>
              <goals>
                <goal>single</goal>
              </goals>
            </execution>
          </executions>
        </plugin>
  </plugins>
</build>

配置完毕之后,执行

mvn package

此时会生成一个XXX-jar-with-dependencies的jar包

java -jar child-one-1.0-SNAPSHOT-jar-with-dependencies.jar

此时执行成功

可以看下jar包内的东西都有什么

在jar包内的META-INF下的MANIFEST.MF文件中
在这里插入图片描述
看到,这次指定了Main-class,这时项目运行成功

如何分析Maven项目的依赖关系?

可以使用Maven官方dependency插件

mvn dependency:tree -Dverbose

可以在命令行界面,很清楚的看到哪些依赖发生了冲突
如果执行只看某一个依赖是不是存在冲突,可以使用

mvn dependency:tree -Dincludes=org.apache.logging.log4j:log4j-api

dependency Filter详细文档

如果依赖太多,控制台可能不好查看,还可以将结果输出到文件中去,
例如将结果输出到D盘的tmp文件夹中去

mvn dependency:tree -Dverbose -Doutput=/d/tmp/file.txt -DoutputType=text

不过,一般平时开发过程中,都使用可视化的图形界面进行查看,如idea的Maven Helper插件.
也可以直接在idea中通过右侧的Maven下的Dependencies查看,具体方法在这里插入图片描述
感谢这位博主的分享

如何部署jar包到本地仓库?

mvn install

如何部署jar包到远程仓库?(Maven私服)

使用的是deploy插件

第一种方式

在pom文件中配置

<project>
  <distributionManagement>
        <repository>
            <id>reposity id</id>
            <name>reposity name</name>
            <url>reposity url</url>
        </repository>
    </distributionManagement>
</project>

在全局aven配置文件setting.xml文件中配置

   <server>
      <id>internal.repo</id>
      <username>maven</username>
      <password>foobar</password>
    </server>

最后运行下面命令即可

mvn deploy
第二种方式

这种方式用来将不存在的pom的jar包,发布到私服,可以在项目中直接通过pom引用

mvn deploy:deploy-file -Durl=reposityUrl -DrepositoryId=repositoryId -Dfile=jar包位置 -DgroupId=com.mycompany.ayy -DartifactId=child-one -Dversion=1.0.0 -Dpackaging=jar

如何让Maven使用 HTTPS 连接 Nexus私服?

参考文章

  1. 在Nexus上配置SSL
  2. 下载Nexus私服的https证书
  3. 将下载的证书通过keytool命令导入到本地JDK
    keytool -importcert -file /home/nexus-cert.cert.der -alias nexus-cert -keystore ${JAVA_HOME}/lib/security/cacerts -storepass changeit -nopromp
    

为什么要这么做呢?最上面说过,Maven运行时依赖于Java的,当Maven同私服建立连接时,使用的HttpClient,由于是https,那么需要证书,而JDK默认的证书中没有我们的私服证书,所以我们需要上述步骤。

官方文档提到的另外一种方式,这种我没测过。

如何在Maven项目构建时检查代码风格?

使用Maven官方checkStyle插件,加入此插件后,会在构建时检查代码风格是否符合规范。不符合则会构建失败.

关于checkStyle的资料可在checkStyle官网查看

如何构建多模块的Maven项目?

直接在最高级也就是父级文件下(此文件下放置的是父pom.xml文件),运行相关Maven命令即可

如:所有模块全部打包

mvn package

如何加快Maven的构建速度?/ mvn -T 4 clean install中-T什么意思?

详细解释见Maven Wiki > Proposals / Backlog > Complete > Parallel builds in Maven 3 一章解释

mvn -T 4 clean install # Builds with 4 threads
mvn -T 1C clean install # 1 thread per cpu core
mvn -T 1.5C clean install # 1.5 thread per cpu core

更多关于mvn [options]的含义可使用

mvn -h

即可查看

在传统Web项目中,如何在打war的时候动态替换web.xml中的值?

stackoverflow上关于此问题的回答
但是,现实情况有可能是,在不同的场景下去替换web.xml中的值。
所以可以和Maven的profile结合使用

第一种方式:
  • 为不同的场景定义不同的profile,将不同场景的properties文件通过全局自定义的properties设置进去。
  • 然后在war-plugin的filter那里配置全局自定义的properties即可
    具体示例如下面配置
<build>
<plugin>
<!--        打war时动态替换web.xml中的内容-->
        <artifactId>maven-war-plugin</artifactId>
        <configuration>
          <webResources>
            <resource>
              <filtering>true</filtering>
              <directory>src/main/webapp</directory>
              <includes>
                <include>**/*</include>
              </includes>
            </resource>
          </webResources>
          <filters>
            <filter>src/main/resources/${build.profile.name}.properties</filter>
          </filters>
        </configuration>
      </plugin>
      </build>
<profiles>
    <profile>
      <id>ticket</id>
      <activation>
        <activeByDefault>true</activeByDefault>
      </activation>
      <properties>
        <build.profile.name>displayTicket</build.profile.name>
      </properties>
    </profile>
    <profile>
      <id>kk</id>
      <properties>
        <build.profile.name>displayKk</build.profile.name>
      </properties>
    </profile>
  </profiles>

两个properties文件里配置的内容为,这里给出displayTicket.properties文件里的内容

display.name=ticket

web.xml中要替换的值为

<web-app>
  <display-name>${display.name}</display-name>
</web-app>
第二种方式:

还有其他人给出使用antrun插件的,也可以完成这个效果
文章链接

好用的资料

最好的资料就是官方文档,建议多多阅读官方文档,在官方文档中找答案,比什么都靠谱。有问题可以Google,比百度靠谱

  1. Maven新手常见问题
  2. Maven常见问题
  3. Spring Boot官方提供的的Maven打包文档

文章中使用的示例工程代码

下载地址,不需要C币

  • 3
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值