ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Maven插件

2022-04-18 02:01:11  阅读:340  来源: 互联网

标签:maven 插件 plugin jar Maven 编译 pom


目录

一、maven-compiler-plugin 插件详解

1.maven插件介绍

maven是个项目管理工具,如果我们不告诉它代码要使用什么样的jdk版本编译的话,它就会用maven-compiler-plugin默认的jdk版本来进行编译处理,这样就容易出现编译版本与源代码不匹配,以至于可能导致编译不通过的问题。例如代码中要是使用上了Java 8的新特性,比如函数式编程,但是maven在编译的时候使用的是Java 7,那这一段代码是完全不可能编译成.class文件的,但如果相反maven编译时使用的是java11则可以编译通过,java高版本的jdk可以运行低版本的java语法的,也既是向下兼容的。为了避免出现mvne使用低版本jdk编译高版本java语法这种情况,在构建maven项目的时候,推荐第一步就是配置maven-compiler-plugin插件,指定项目源码的 jdk 版本,编译后的 jdk 版本,以及编码方式。

从 maven-compiler-plugin 3.8.0 之后,默认JDK 版本就由 1.5 改为 1.6 了。但是这仍然跟不上 JDK 的更新速度,目前大多数系统都在使用 JDK 1.8。Apache Maven Project 对 maven-compiler-plugin中compiler:compile有如下关于jdk版本变更的描述:

img

<plugin>
    <!-- 指定maven编译的jdk版本,如果不指定,maven3默认用jdk 1.5 maven2默认用jdk1.3 -->                 
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-compiler-plugin</artifactId>
    <version>3.8.1</version>
    <configuration>                       
        <!-- 一般而言,target与source是保持一致的,但是,有时候为了让程序能在其他版本的jdk中运行
(比如:源代码使用的是1.5的语法,但是想在1.8的jdk环境运行,由低刀高是允许的)
(对于低版本目标jdk,源代码中不能使用低版本jdk中不支持的语法),会存在target不同于source的情况 -->
        <!-- 源代码使用的JDK版本 -->
        <source>1.8</source>
        <!-- 需要生成的目标class文件的编译版本 -->
        <target>1.8</target>
        <!-- 字符集编码 -->
        <encoding>UTF-8</encoding>
        <!-- 跳过测试 -->
        <skipTests>true</skipTests>
        <verbose>true</verbose>
        <showWarnings>true</showWarnings>
        <!-- 要使compilerVersion标签生效,还需要将fork设为true,用于明确表示编译版本配置的可用 -->
        <fork>true</fork>
        <!-- 使用指定的javac命令,例如:<executable>${JAVA_1_4_HOME}/bin/javac</executable> -->
        <executable><!-- path-to-javac --></executable>
        <!-- 指定插件将使用的编译器的版本 -->
        <compilerVersion>1.3</compilerVersion>
        <!-- 编译器使用的初始内存 -->
        <meminitial>128m</meminitial>
        <!-- 编译器使用的最大内存 -->
        <maxmem>512m</maxmem>
        <!-- 这个选项用来传递编译器自身不包含但是却支持的参数选项 -->
        <compilerArgument>-verbose -bootclasspath ${java.home}\lib\rt.jar</compilerArgument>
    </configuration>
</plugin>                             

参考:https://blog.csdn.net/liupeifeng3514/article/details/80236077

2.全局配置maven JDK编译版本

  • 在公司开发时一劳永逸的配置

此种设置方式将影响由maven创建的所有项目。找到maven安装目录的conf文件夹,修改其中的settings.xml文件,profiles标签加入如下配置:

<!-- ${MAVEN_HOME}/conf/settins.xml 文件添加如下profile配置,建立的java项目默认使用java 8/11/13 -->
<profiles>
    <profile>
        <id>jdk-8</id>
        <activation>
            <activeByDefault>true</activeByDefault>
            <jdk>8</jdk>
        </activation>
        <properties>
            <maven.compiler.source>8</maven.compiler.source>
            <maven.compiler.target>8</maven.compiler.target>
            <maven.compiler.compilerVersion>8</maven.compiler.compilerVersion>
        </properties>
    </profile>
</profiles>

这样全局设置后,项目编译时就会默认使用jdk 13。全局配置的好处就是省事、方便,从而避免对每个项目都去设置。

3.参考

https://www.cnblogs.com/east7/p/13363069.html?utm_source=tuicool

二、org.apache.maven.plugins系列插件简介

1.插件知识简介

  compiler(maven-compiler-plugin)插件3.0之前,默认的Java编译器就的JDK自带的javac。但是从Compiler(maven-compiler-plugin)插件3.0开始(需要JDK1.6),默认的Java编译器 是javax.tools.JavaCompiler。如果仍然希望使用JDK自带的javac编译源代码,就需要为mvn命令配置forceJavacCompilerUse启动参数如:-Dmaven.compiler.forceJavacCompilerUse=true

  Compiler插件编译时和编译后运行的JVM版本目前默认的设置为1.5,默认用此版本,而不是根据你在IDEA项目结构中指定的工程JDK版本编译。如果想改变这些默认设置,应该设置编译源和目标中java编译器的目标,通过设置Java源代码兼容的JVM版本,标明Java源代码开发过程中使用的Java版本,通过设置编译后的类库拟运行的JVM版本,给出编译后的类库将要运行的Java环境(一般都会设置,因为很少有项目再用1.7以下的版本了):

  同时,命令mvn的运行需要依赖JDK,Compiler插件默认使用当前运行mvn命令的JDK去编译Java源代码。如果想使用其他版本的JDK(比如本地java环境的,而非maven自带的)编译Java源代码,则需要设置如下(重点fork 、executable、compilerVersion):

上述配置中,用以编译Java源代码的是JDK 1.8,运行mvn命令时指定maven所使用的是JDK为1.6

Compiler插件提供了如下2个goal,默认都已经绑定到Maven的生命周期阶段,无需单独指出。

compiler:compile,绑定到compile 阶段,用以编译main/路径下的源代码

compiler:testCompile,绑定到test-compile阶段,用以编译test/路径下的源代码

mvn compile:

2.官网也建议指定编译的jdk版本

如果是web项目,就需要打war包,那就需要这个插件:

强制字符集编码:${project.build.sourceEncoding}

platformwar包名字——platform.war

产生war前,用于存放构建war包的目录——target/platform。

${project.build.directory}/platform

使用maven工具链:

使用不同的JDK的最好方法是使用工具链方式。在建立一个项目,如编译java源文件,生成Javadoc,运行单元测试、打包,这些插件中的每一个都需要一个JDK工具来对应操作:Javac、JavaDoc、JaveNeR等。使用Maven工具链插件,您可以为所有相关的Maven插件配置1个默认JDK工具链也可以各自配置不同的jdk,用法略。

配置编译插件:

除工具链方式之外,也可以在编译过程中使用的特定JDK。这样的配置对这个插件是特定的,不会影响其他插件。compilerVersion参数可以用来指定插件使用的编译器版本,但是需要将fork设置为true才能工作,此为非常用配置不做详细了解。

针对不同的编译器设置source和target选项:

有时编译某个项目时需要使用的jdk与当前maven所使用的版本不同。Javac可以使用source和target参数来接受这样的命令。编译器插件也可以被配置为在编译期间提供这些选项。如刚才上述:官网也建议指定编译的jdk版本

传递编译参数:

有时需要传递其他编译器参数,这些编译器参数本身不是插件本身需要处理的,而是需要将编译器参数传递给Javac编译器,如下图

3.POM简介

所有的 POM 都继承自一个父 POM(无论是否显式定义了这个父 POM),父POM包含一些可以被继承的默认设置。Maven 使用 effective pom(Super pom 加上工程自己的配置)来执行相关,目的为了使开发者在pom.xml中做尽可能少的配置,且在子配置中可以被方便的覆盖:

比如不指定packaging时,即默认打jar包时打开effective.pom

再看另一种举例:当指定packaging为war,指定打war包时打开effective pom

所以我们只需要指定packaging打包类型,maven插件可以自动加载并继承父pom相关配置。

如果父pom中的默认配置不符合现有项目要求,而在我们的pom中有没有覆盖,则会报错,如删除pom中的maven-compiler-plugin,使其不覆盖父pom中的maven-compiler-plugin,这样就是使用的父pom中的配置:

上图删除了pom中的maven-compiler-plugin,再看下图effecrive pom中的:

看到这里就使用了默认父pom的maven-compiler-plugin2.3.2版本,此版本默认的jdk是1.5,maven编译时报:

然后修改自己的pom中的maven-compiler-plugin覆盖父pom中的maven-compiler-plugin,使用自定义覆盖默认配置:

上图pom中增加了maven-compiler-plugin,再看下图effecrive pom中的:

则使用jdk1.7编译成功了

4.打开Show Effective POM的两种方式

  • maven 命令行方式:
    mvn help:effective-pom -Doutput=EffectivePom.xml

我们都知道maven是约定大于配置,也就是默认有很多约定好的配置,如果你不改变,那么就使用这些配置,比如java源代码放置在src/main/java下, 资源文件放置在src/main/resources下, 所以当我们把源代码,资源按约定的结构建立起来后,pom.xml配置很少就可以build jar/war/ear 包, 那么如果你想知道pom.xml的默认配置有哪些,分别设置了哪些值,那么你可以通过上面的goal来生成一个完整的EffectivePom.xml文件,这里面有完整的配置.

打开Show Effective POM(最终生效POM配置,包含了继承的内容)

  • IDEA方式:

5.常用插件

Maven官网插件地址:https://maven.apache.org/plugins/index.html

maven的属性值的占位符,类似EL,类似ant的属性,比如${X},可用于pom文件任何赋值的位置。有以下分类:

env.X:操作系统环境变量,比如${env.PATH}

project.x:pom文件中的属性,比如:1.0,引用方式:${project.version}

settings.xml文件中的属性,比如:false,引用方式:${settings.offline}

Java System Properties:java.lang.System.getProperties()中的属性,比如java.home,引用方式:${java.home}

自定义在pom文件中可以:c:/apps/cargo-installs定义属性及属性的值,而引用方式为:${installDir}

6.工作机制

  Maven强大的一个重要的原因是它有一个十分完善的生命周期模型(lifecycle),它有三套相互独立的生命周期,请注意这里说的是“三套”,请别将Maven的生命周期看成一个整体哦,三个生命周期是独立线性执行,分别是:

Clean Lifecycle 在进行真正的构建之前进行一些清理工作。

Default Lifecycle 构建的核心部分,编译,测试,打包,部署等等。

Site Lifecycle 生成项目报告,站点,发布站点。

  每个生命周期包含一些阶段(phase),这些阶段(phase)是有顺序的,每个阶段蕴含一个或多个目标(goal),并且后面的阶段依赖于前面的阶段,我们和Maven最直接的交互方式就是调用这些生命周期阶段。较之于生命周期阶段的前后依赖关系,三套生命周期本身是相互独立的,用户可以仅仅调用clean生命周期的某个阶段,或者仅仅调用default生命周期的某个阶段,而不会对其他生命周期产生任何影响。例如,当用户调用clean生命周期的clean阶段的时候,不会触发default生命周期的任何阶段。其中deault是最重要的生命周期,拥有validate 、compile 、test 、package、integration、verify、install、deploy等等阶段。

  看一下Maven的编译阶段,让maven进行编译代码,使用的是声明的方式来告知Maven如何做的。看似一个简单的命令,但其实它后面执行了一系列的工作。mvn compile如不指定compile阶段的goal,所以complie阶段所有goal,compile和test compile都会执行。

  Maven是如何知道从哪里找到要编译的源文件?并且Maven如何知道将编译好的类文件放到哪里?这里就是由Mave基础工作之一“通过配置进行约定”所解决的问题。一般情况下,源文件放在src/main/java路径下,这种默认设置(虽然在上面的POM文件中并没看到)是从父 POM继承来的,即使最简单的POM也知道源文件的默认位置:

当首次执行compile命令或其它命令时,maven会下载所有插件和相关的文件,而之后再执行同一个命令的时候会发现比第一次快很多,这就为什么首次执行命令时候会比较慢的原因。

7.自定义maven插件

大家有没有想过,如果maven自带的插件满足不了我们的需求时候,该怎么办呢?其实不难办,可以通过自己写插件来实现。下面给大家讲一下如何写插件。

1、首先需要创建一个maven项目tinaproject,然后把pom里的packaging改成maven-plugin

然后把版本改为你自己使用的版本,一般现在都是用maven2

接着添加依赖

2、pom修改完了之后就开始创建mojo类了,maven插件里每一个goal所对应的功能都是一个Mojo,比如说eclipse:clean和eclipse:eclipse就是两个Mojo

写完了一个最简单的mojo类之后就来测试下能否正确运行,把mvn install把它发布到本地maven仓库,然后在pom里再增加一个plugin(上面写的这个)

最后再运行mvn compile 就能看到输出了

8.参考

https://www.jianshu.com/p/3c75b3225724

三、springboot 打包插件spring-boot-maven-plugin打包机制及内部结构分析

1.前言

许多公司都会选择使用springboot作为服务应用开发框架,springboot框架提供了一套自己的打包机制,是通过spring-boot-maven-plugin插件来实现的。

1、spring-boot-maven-plugin引入pom

对于新建的一个springboot项目来说,pom中会加入插件:

img

通过idea可以看到maven中包含了spring-boot-maven-plugin插件:

img

功能说明:

  • build-info:生成项目的构建信息文件 build-info.properties
  • repackage:这个是默认goal,在 mvn package 执行之后,这个命令再次打包生成可执行的 jar,同时将 mvn package 生成的 jar 重命名为 *.origin
  • run:这个可以用来运行 Spring Boot 应用
  • start:这个在 mvn integration-test 阶段,进行 Spring Boot 应用生命周期的管理
  • stop:这个在 mvn integration-test 阶段,进行 Spring Boot 应用生命周期的管理

spring-boot-maven-plugin插件默认在父工程sprint-boot-starter-parent中被指定为repackage,可以点击sprint-boot-starter-parent进入父pom进行查看,如下图:

img

如果需要设置其他属性,需要在当前应用的pom中进行设置去覆盖父pom默认的值去改变行为。

2.执行打包命令

mvn clean package

或者通过开发工具如idea执行clean和package俩命令:

img

执行以上命令时会自动触发spring-boot-maven-plugin插件的repackage目标,完后可以在target目录下看到生成的jar,如下图:

img

这里可以看到生成了两个jar相关文件,其中common.jar是spring-boot-maven-plugin插件重新打包后生成的可执行jar,即可以通过java -jar common.jar命令启动。common.jar.original这个则是mvn package打包的原始jar,在spring-boot-maven-plugin插件repackage命令操作时重命名为xxx.original,这个是一个普通的jar,可以被引用在其他服务中。

3.jar内部结构

对这两个jar文件解压看看里面的结构差异:

3.1 common.jar目录结构如下:

img

其中BOOT-INF主要是一些启动信息,包含classes和lib文件,classes文件放的是项目里生成的字节文件class和配置文件,lib文件是项目所需要的jar依赖。

META-INF目录下主要是maven的一些元数据信息,MANIFEST.MF文件内容如下:

MANIFEST.MF:这个manifest文件定义了与扩展和包相关的数据。单词“manifest”的意思是“显示”。

Manifest-Version: 1.0
Implementation-Title: java-common-utils
Implementation-Version: 0.0.1-SNAPSHOT
Start-Class: com.common.util.CommonUtilsApplication
Spring-Boot-Classes: BOOT-INF/classes/
Spring-Boot-Lib: BOOT-INF/lib/
Build-Jdk-Spec: 1.8
Spring-Boot-Version: 2.1.9.RELEASE
Created-By: Maven Archiver 3.4.0
Main-Class: org.springframework.boot.loader.JarLauncher

其中Start-Class是项目的主程序入口,即main方法。Springboot-Boot-Classes和Spring-Boot-Lib指向的是生成的BOOT-INF下的对应位置。

Main-Class属性值为org.springframework.boot.loader.JarLauncher,这个值可以通过设置属性layout来控制,如下:

<plugin>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-maven-plugin</artifactId>
    <configuration>
<!--使用-Dloader.path需要在打包的时候增加<layout>ZIP</layout>,不指定的话-Dloader.path不生效-->
        <layout>ZIP</layout>
        <!-- 指定该jar包启动时的主类[建议] -->
        <mainClass>com.common.util.CommonUtilsApplication</mainClass>
    </configuration>
    <executions>
        <execution>
            <goals>
                <goal>repackage</goal>
            </goals>
        </execution>
    </executions>
</plugin>

设置<layout>ZIP</layout>时Main-Class为org.springframework.boot.loader.PropertiesLauncher,具体layout值对应Main-Class关系如下:

  • JAR,即通常的可执行jar
Main-Class: org.springframework.boot.loader.JarLauncher
  • WAR,即通常的可执行war,需要的servlet容器依赖位于WEB-INF/lib-provided
Main-Class: org.springframework.boot.loader.warLauncher
  • ZIP,即DIR,类似于JAR(打增量包时会使用到)
Main-Class: org.springframework.boot.loader.PropertiesLauncher
  • MODULE,将所有的依赖库打包(scope为provided的除外),但是不打包Spring Boot的任何Launcher
  • NONE,将所有的依赖库打包,但是不打包Spring Boot的任何Launcher

common.jar之所以可以使用java -jar运行,和MANIFEST.MF文件里的配置关系密切

3.2 common.jar.original目录结构

img

可以看到通过mvn package构建的jar是一个普通的jar,包含的都是项目的字节文件和一些配置文件,没有将项目依赖的第三方jar包含进来。再看下MANIFEST.MF文件:

Manifest-Version: 1.0
Implementation-Title: java-common-utils
Implementation-Version: 0.0.1-SNAPSHOT
Build-Jdk-Spec: 1.8
Created-By: Maven Archiver 3.4.0

其中没有包含Start-Class、Main-Class等信息,这个与可执行jar的该文件存在很多差异,而且目录结构也有很大差异。

一般对使用spring-boot-maven-plugin插件打出的可执行jar不建议作为jar给其他服务引用,因为可能出现访问可执行jar中的一些配置文件找不到的问题。如果想让构建出来的原始jar不被重新打包,可以对spring-boot-maven-plugin插件配置classifier属性,自定义一个可运行jar名称,这样该插件就不会对原始的jar重命名操作了。

例如:

<configuration>
    <!-- [建议]指定该jar包启动时的主类 -->
    <mainClass>com.common.util.CommonUtilsApplication</mainClass>
    <!--配置的 classifier 表示可执行 jar 的名字,配置了这个之后,在插件执行 repackage 命令时,
    就不会给 mvn package 所打成的 jar 重命名了,这样就可以被其他项目引用了,classifier命名的为可执行jar-->
    <classifier>myexec</classifier>
</configuration>

效果如下:

img

以上是对spring-boot-maven-plugin插件的打包机制和jar包结构的一些分析。

4.参考

https://blog.csdn.net/iss_jin/article/details/122463390

四、springboot增量打包更新--静态资源分离打包

1.前言

springboot部署打包为jar,一般都是全量打包,生成的jar包因包含大量三方库通常都是超过100M的,并且在进行一般的页面html微调、js修改、img替换、css样式修改时也需要重新打包进行部署;每次微小的调整都需要重新打包就太烦了,一般在项目开发稳定以后项目中引用的jar就不再改变

为了方便进行静态资源管理及增量部署,对项目引用jar包以及静态资源分离打包,提高打包的效率及部分前端微调项修改后及时进行无重启更新;

2.具体步骤

1、初次打包进行全量打包,对打包的jar进行解压,解压后的文件如下图展示:

jar包解压后的目录

2、分离引用的jar包:进入BOOT-INF中,copy文件夹lib到指定目录下,如jar包运行目录;

需要copy引用的jar包文件夹-lib

图-3,最终lib存放的目录

3分离静态文件:在lib同目录下创建resource文件夹,进入classes文件夹内copy文件夹statictemplates文件夹到resource文件下;如图:

copy到resource目录下的静态文件,包括HTML、JS、css、image等静态文件

4、删除jar包及解压文件,当前目录结构如下:

初次完成jar及静态文件分离

5、增量打包,打包不再将引用jar及static文件夹、templates文件夹打到jar包中:首先修改pom.xml文件中打包相关配置,如下图:
打包配置增加了如下代码:

<layout>ZIP</layout>
<includes>
        <include>
                <groupId>non-exists</groupId>
                <artifactId>non-exists</artifactId>
         </include>
</includes>

resource打包配置增加如下过滤:

<exclude>static/**/*</exclude>
<exclude>templates/**/*</exclude>

最终pom.xml中打包配置如下:

<build>
    <finalName>web</finalName>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
            <configuration>
                <includeSystemScope>true</includeSystemScope>
                <mainClass>com.XXX.Application</mainClass>
                <!--增量打包配置【start】-->
                <layout>ZIP</layout>
                <includes>
                    <include>
                        <groupId>non-exists</groupId>
                        <artifactId>non-exists</artifactId>
                    </include>
                </includes>
                <!--增量打包配置【end】-->
            </configuration>
            <executions>
                <execution>
                    <goals>
                        <goal>repackage</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
            <version>2.0.4.RELEASE</version>
            <configuration>
                <fork>false</fork>
            </configuration>
        </plugin>
    </plugins>
 
    <resources>
        <resource>
            <directory>src/main/resources</directory>
            <includes>
                <include>**/*</include>
            </includes>
            <excludes>
                <!--【增加静态文件过滤】-->
                <exclude>static/**/*</exclude>
                <exclude>templates/**/*</exclude>
            </excludes>
        </resource>
    </resources>
</build>

6、执行maven clean install,获得最终jar包,如下图所示,只有5M大小;

最终项目打包的目录结构

7、最终运行时,jar的执行命令中增加lib及resource的路径指向,否则项目无法正常运行;

java -Dloader.path=./lib,./resource -jar ./web.jar

8、如上进行增量打包后,如果前端有不涉及到后端的修改时都可以对resource中的文件进行替换进行实时更新,不再进行重启;后端有变动也不用上传100多M的jar到服务器,影响效率;

3.参考

转自:https://blog.csdn.net/qq_35611143/article/details/107083164

参考:https://www.jb51.net/article/186316.htm

标签:maven,插件,plugin,jar,Maven,编译,pom
来源: https://www.cnblogs.com/hhddd-1024/p/16158057.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有