当前位置: 首页 > news >正文

Maven打包插件介绍

文章目录

  • 1. maven介绍
  • 2. 生命周期及插件
    • 2.1 总览生命周期
    • 2.2 打包插件
      • 2.2.1 maven-jar-plugin
      • 2.2.2 maven-assembly-plugin
      • 2.2.3 maven-shade-plugin
      • 2.2.4 maven-war-plugin
        • 2.2.4.1 jar和war
      • 2.2.5 maven-source-plugin
  • 3. springboot打包插件
  • 4.实际操作
    • 4.1 一个可用的打包插件配置, 插件外置且打出可发布的包
    • 4.2 引用可执行jar的方式
  • 5. maven和Nexus的关系

1. maven介绍

我们都知道Maven本质上是一个插件框架,具有打包和jar管理的功能.

对于打包来说,它的核心并不执行任何具体的构建任务,所有这些任务都交给插件来完成,例如编译源代码是由maven- compiler-plugin完成的。进一步说,每个任务对应了一个插件目标(goal),每个插件会有一个或者多个目标,例如maven- compiler-plugin的compile目标用来编译位于src/main/java/目录下的主源码,testCompile目标用来编译位于src/test/java/目录下的测试源码。

用户可以通过两种方式调用Maven插件目标:

第一种方式是将插件目标与生命周期阶段(lifecycle phase)绑定,这样用户在命令行只是输入生命周期阶段而已,例如Maven默认将maven-compiler-plugin的compile目标与 compile生命周期阶段绑定,因此命令mvn compile实际上是先定位到compile这一生命周期阶段,然后再根据绑定关系调用maven-compiler-plugin的compile目标。

第二种方式是直接在命令行指定要执行的插件目标,例如mvn archetype:generate 就表示调用maven-archetype-plugingenerate目标,这种带冒号的调用方式与生命周期无关。

2. 生命周期及插件

以下测试用的是maven默认的打包插件(打common包这种), 执行 mvn clean install  对应的输出

2.1 总览生命周期

生命周期(lifecycle)由各个阶段组成,每个阶段由maven的插件plugin来执行完成。生命周期(lifecycle)主要包括cleanresourcescomplieinstallpackagetestResourcestestCompile等,其中带test开头的都是用业编译测试代码或运行单元测试用例的。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yJts8CbI-1661939280978)(maven%E6%89%93%E5%8C%85%E6%8F%92%E4%BB%B6.assets/70.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ToTdCNvm-1661939280980)(maven%E6%89%93%E5%8C%85%E6%8F%92%E4%BB%B6.assets/70-16619168585413.png)]

由上图可知,各个插件的执行顺序一般是:1:clean、2:resources、3:compile、4:testResources、5:testCompile、6:test、7:jar、8:install。

在图中标记的地方每一行都是由冒号分隔的,前半部分是对应的插件,后半部分是插件的执行目标也就是插件执行产生的结果。

现在我们来看下上面的pom文件,我们如配置了maven-compiler-plugin这个插件,其它的插件没有配置,但最后项目构建成功,说明maven内置的各种插件,如果pom中没有配置就调用默认的内置插件,如果pom中配置了就调用配置的插件。

到此我们理解maven的构建过程或者有更多的人称是打包,就是由各种插件按照一定的顺序执行来完成项目的编译,单元测试、打包、布署的完成。各种插件的执行过程也就构成的maven的生命周期(lifecycle)。生命周期(lifecycle)各个阶段并不是独立的,可以单独执行如mvn clean,也可以一起执行如mvn clean install。而且有的mvn命令其是包括多个阶段的,如mvn compile其是包括了resources和compile两个阶段。下面分别来分析各个阶段需要的插件和输出的结果

也就是说,每个步骤的插件包都能指定特定版本和配置其下参数

2.2 打包插件

这个插件是把class文件、配置文件打成一个jar(war或其它格式)包。依赖包是不在jar里面的,需要建立lib目录,且jar和lib目录在同级目录。常用的打包插件有maven-jar-plugin、maven-assembly-plugin、maven-shade-plugin三种,下面分别介绍下各自己pom配置和使用特点。

2.2.1 maven-jar-plugin

可执行jar与依赖包是分开,需建立lib目录里来存放需要的j依赖包,且需要jar和lib目录在同级目录, 这也是默认打包方式,所以打common包不写插件也能打包

2.2.2 maven-assembly-plugin

这个插件可以把所有的依赖包打入到可执行jar包。需要在pom文件的plugin元素中引入才可以使用,功能非常强大,是maven中针对打包任务而提供的标准插件。它是Maven最强大的打包插件,它支持各种打包文件格式,包括zip、tar.gz、tar.bz2等等,通过一个打包描述文件设置(src/main/assembly.xml),它能够帮助用户选择具体打包哪些资源文件集合、依赖、模块,甚至本地仓库文件,每个项的具体打包路径用户也能自由控制。

但是该插件有个bug会缺失spring的xds文件,导致无法运行jar,同时如果同级目录还有其它可执行jar文件依赖可能会产生冲突。

2.2.3 maven-shade-plugin

需要在pom文件的plugin元素中引入才可以使用,它可以让用户配置Main-Class的值,然后在打包的时候将值填入/META-INF/MANIFEST.MF文件。关于项目的依赖,它很聪明地将依赖的JAR文件全部解压后,再将得到的.class文件连同当前项目的.class文件一起合并到最终的CLI包(可以直接运行的jar包)中,这样,在执行CLI JAR文件的时候,所有需要的类就都在Classpath中了。(springboot打包插件用的就是这个)

如何选用这几个插件

  • 如果在开发一个库,直接使用默认的maven-jar-plugin插件即可;

  • 如果是开发一个应用程序,可以考虑使用maven-shade-plugin进行打包生成Über jar(Über jar是将应用程序打包到单独的jar包中,该jar包包含了应用程序依赖的所有库和二进制包)

  • 如果打包生成了Über jar都不能满足你的需求的话,那么推荐使用maven-assembly-plugin插件来自定义打包内容。

2.2.4 maven-war-plugin

war项目默认的打包工具,默认情况下会打包项目编译生成的.class文件、资源文件以及项目依赖的所有jar包。

2.2.4.1 jar和war

1、war是一个web模块,其中需要包括WEB-INF,是可以直接运行的WEB模块;jar一般只是包括一些class文件,在声明了Main_class之后是可以用java命令运行的。

2、war包是做好一个web应用后,通常是网站,打成包部署到容器中;jar包通常是开发时要引用通用类,打成包便于存放管理。

3、war是Sun提出的一种Web应用程序格式,也是许多文件的一个压缩包。这个包中的文件按一定目录结构来组织;classes目录下则包含编译好的Servlet类和Jsp或Servlet所依赖的其它类(如JavaBean)可以打包成jar放到WEB-INF下的lib目录下。

1.我的一个springboot项目,用mvn install打包成jar,换一台有jdk的机器就直接可以用java -jar 项目名.jar的方式运行,没任何问题,为什么这里不需要tomcat也可以运行了?

答: 通过jar运行实际上是启动了内置的tomcat,所以用的是应用的配置文件中的端口

2.然后我打包成war放进tomcat运行,发现端口号变成tomcat默认的8080(我在server.port中设置端口8090)项目名称也必须加上了。
也就是说我在原来的机器的IDEA中运行,项目接口地址为 ip:8090/listall,打包放进另一台机器的tomcat就变成了ip:8080/项目名/listall。这又是为什么呢?

答: 直接部署到tomcat之后,内置的tomcat就不会启用,所以相关配置就以安装的tomcat为准,与应用的配置文件就没有关系了

2.2.5 maven-source-plugin

用来打源代码包的, 就像spring写的包,我们要下源代码来看注释,我们自己写的包有时也需要打出源码包给别人用,打完只有就会有一个-sources后缀的包

		<plugin>  
   			<groupId>org.apache.maven.plugins</groupId>  
              <artifactId>maven-source-plugin</artifactId>  
              <version>3.0.0</version>  
              <configuration>  
                  <attach>true</attach>  
              </configuration>  
              <executions>  
                  <execution>  
                      <phase>compile</phase>  
                      <goals>  
                          <goal>jar</goal>  
                      </goals>  
                  </execution>  
              </executions>  
          </plugin>  

3. springboot打包插件

spring-boot-maven-plugin插件在Maven中提供了对Spring Boot的支持,可以帮助我们打包出可执行的jar包或者war包。其实spring-boot-maven-plugin所做的工作是在默认的maven-jar-plugin插件打包结束后,将项目依赖的jar包中的.class文件重新进行打包。

[INFO] 
[INFO] --- maven-jar-plugin:2.6:jar (default-jar) @ helloworld ---
[INFO] Building jar: /Users/gaozengrong/IdeaProjects/helloworld/target/helloworld-1.0-SNAPSHOT.jar
[INFO] 
[INFO] --- spring-boot-maven-plugin:1.5.2.RELEASE:repackage (default) @ helloworld ---
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 26.357 s
[INFO] Finished at: 2017-03-19T17:51:33+08:00
[INFO] Final Memory: 33M/289M
[INFO] ------------------------------------------------------------------------

可以看出,在调用maven-jar-plugin的goal:jar任务打包之后,又调用了spring-boot-maven-plugin的goal:repackage任务,这样会产生两个jar包。在helloworld这个工程里分别对应helloworld-1.0-SNAPSHOT.jar.original(maven-jar-plugin打包生成的jar包),helloworld-1.0-SNAPSHOT.jar(spring-boot-maven-plugin重新打包生成的可执行jar包)。

它使用的打包插件是 maven-shade-plugin

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PdrgDkDt-1661939280980)(C:\Users\gree\AppData\Roaming\Typora\typora-user-images\image-20210402184511005.png)]

4.实际操作

4.1 一个可用的打包插件配置, 插件外置且打出可发布的包

<build>
    <plugins>
         <!--springboot自带的-->
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
        </plugin>
        <!-- 打包 -->
        <!-- 使用这个插件打包 -->
       <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-jar-plugin</artifactId>
            <configuration>
             <!-- 在1.8的环境下-->
            	<source>1.8</source>
            	<target>1.8</target>
            	<encoding>UTF-8</encoding>
            	<!--排除这些文件-->
            	<excludes>
            	    <exclude>*.properties</exclude>
            		<exclude>*.xml</exclude>
            	</excludes>
            </configuration>
        </plugin>
        <!-- 再使用这个插件打包 -->      <!-- 允许打多个包 -->
        <plugin>
            <artifactId>maven-assembly-plugin</artifactId>
            <executions>
            	<execution>
            		<id>make-zip</id>
            		<phase>package</phase>
            		<goals>
            			<goal>single</goal>
            		</goals>
            		<!-- 确定包名,输出路径,用assembly.xml文件 -->
            		<configuration>
            			<finalName>${project.artifactId}</finalName>
            			<outputDirectory>target</outputDirectory>
            			<descriptors>
            				<descriptor>src/assembly/assembly.xml</descriptor>
            			</descriptors>
            		</configuration>
            	</execution>
            </executions>
        </plugin>
        <!-- 再使用这个插件打包 -->  
         <plugin>
                 <artifactId>maven-resources-plugin</artifactId>
                  <executions>
                      <execution>
                          <id>copy-xmls</id>
                          <phase>process-sources</phase>
                          <goals>
                              <goal>copy-resources</goal>
                          </goals>
                          <configuration>
                              <outputDirectory>${basedir}/target/classes</outputDirectory>
                              <resources>
                                  <resource>
                                      <directory>${basedir}/src/main/java</directory>
                                      <includes>
                                          <include>**/*.xml</include>
                                      </includes>
                                  </resource>
                              </resources>
                          </configuration>
                      </execution>
                  </executions>
            </plugin>   
    </plugins>
</build>

4.2 引用可执行jar的方式

使用springboot插件打出来的包无法被其他应用程序引用,应该有多个可执行jar了(maven默认的可以被引用),要想被使用采用如下方式

<plugins>
  # 这是 springboot的打包插件,就是常说的服务包,它带了各种依赖和启动类,用这个插件打出来的包不能为其他服务包pom引用
    <plugin>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-maven-plugin</artifactId>
        <configuration>
            <executable>true</executable>
        </configuration>
    </plugin>
</plugins>

# 如果要使用,就再打一个普通包,用于引用,改写成如下:
    关键是<classifier>标签,这是新jar的后缀
<plugins>
    <plugin>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-maven-plugin</artifactId>
        <configuration>
            <!--  额外打包普通jar用于 activity-consumer服务-->
            <mainClass>com.gree.ecommerce.ActivityServiceApplication</mainClass>
            <classifier>OfConsumer</classifier>
            <executable>true</executable>
        </configuration>
    </plugin>
</plugins>

使用的时候正常用,这是找了"漏洞",打出来的包会发布到仓库中,平常部署运行时用的是target下的,这是可运行的,而引用时用的仓库里的jar,这又是被额外生成的 https://www.cnblogs.com/kingsonfu/p/11805455.html

5. maven和Nexus的关系

我们知道maven 具有打包和 jar管理功能 , 而jar包管理功能, 就是通过在Pom中指定坐标的形式将jar引入到项目中, 那这些jar包在哪呢?

这引出了仓库的概念,maven通过仓库来统一管理各种构件。Maven的仓库分为本地仓库和远程仓库。

在这里插入图片描述

当Maven根据坐标寻找构件时,它首先会查看本地仓库,如果本地仓库存在此构件,则直接使用;如果本地仓库不存在此构件,或者需要查看是否有更新的构件版本,Maven会再去远程仓库查找,发现需要的构件之后,下载到本地仓库再使用

Nexus是一种远程仓库。在远程仓库中,默认的是中央仓库,中央仓库是Maven核心自带的远程仓库

为了下载jar包的速度和包管理, 公司一般都会自己搭建Nexus系统, 所以在maven的setting.xml文件中会写自己公司的私服地址或者一些开源的私服地址, 例如阿里的私服: http://maven.aliyun.com/nexus/content/groups/public

参考链接

插件介绍

打包生命周期

maven-source-plugin使用

maven体系

springboot打包插件

Maven与nexus_超有韧性的猿媛的博客-CSDN博客_nexus和maven的区别

相关文章:

  • DataMaleon组件化开发实践 | StartDT Tech Lab 14
  • 记录一下Elasticsearch集群搭建的知识点
  • 自发荧光/阳离子纳米聚苯乙烯微球/功能化聚苯乙烯共聚荧光微球的研究
  • GBase 8s V8.8的锁机制和隔离级别
  • 浅谈MES管理系统对中国中小企业智能化生产的影响
  • 搜题接口创建 对接百万题库接口
  • SpringBoot自动配置原理入门
  • Linux 磁盘管理
  • 涂鸦电工产品开发包如何使用
  • 初识react笔记
  • Java中的串口编程是怎样的呢?
  • SI好文翻译:铜箔表面纹理对损耗的影响:一个有效的模型(二)
  • 数据结构学习笔记 4-2 哈希表与布隆过滤器 与 LeetCode真题(Java)
  • JAVA基础之动态代理
  • 轻量级神经网络算法系列文章-MobileNet v3
  • [iOS]Core Data浅析一 -- 启用Core Data
  • Android 架构优化~MVP 架构改造
  • Docker 笔记(1):介绍、镜像、容器及其基本操作
  • es6要点
  • ES6语法详解(一)
  • Git同步原始仓库到Fork仓库中
  • JavaScript HTML DOM
  • Netty 4.1 源代码学习:线程模型
  • nodejs:开发并发布一个nodejs包
  • 复杂数据处理
  • 湖南卫视:中国白领因网络偷菜成当代最寂寞的人?
  • 老板让我十分钟上手nx-admin
  • 类orAPI - 收藏集 - 掘金
  • 小程序测试方案初探
  • 用quicker-worker.js轻松跑一个大数据遍历
  • LevelDB 入门 —— 全面了解 LevelDB 的功能特性
  • SAP CRM里Lead通过工作流自动创建Opportunity的原理讲解 ...
  • ​​​​​​​sokit v1.3抓手机应用socket数据包: Socket是传输控制层协议,WebSocket是应用层协议。
  • # .NET Framework中使用命名管道进行进程间通信
  • #define、const、typedef的差别
  • (1) caustics\
  • (52)只出现一次的数字III
  • (done) 两个矩阵 “相似” 是什么意思?
  • (ZT)薛涌:谈贫说富
  • (安全基本功)磁盘MBR,分区表,活动分区,引导扇区。。。详解与区别
  • (附源码)springboot猪场管理系统 毕业设计 160901
  • (九)One-Wire总线-DS18B20
  • (论文阅读22/100)Learning a Deep Compact Image Representation for Visual Tracking
  • (四) Graphivz 颜色选择
  • (四)c52学习之旅-流水LED灯
  • (原創) 人會胖會瘦,都是自我要求的結果 (日記)
  • (转)Android学习笔记 --- android任务栈和启动模式
  • (转)拼包函数及网络封包的异常处理(含代码)
  • .chm格式文件如何阅读
  • .NET 5种线程安全集合
  • .NET Core MongoDB数据仓储和工作单元模式封装
  • .NET Core 成都线下面基会拉开序幕
  • .NET Core 通过 Ef Core 操作 Mysql
  • .NET/C# 推荐一个我设计的缓存类型(适合缓存反射等耗性能的操作,附用法)
  • .NET上SQLite的连接