Maven插件


一、maven-compiler-plugin 插件詳解

1.maven插件介紹

  maven是項目構建管理工具,如果不明確指定源代碼要使用什么版本的jdk的話,maven-compiler-plugin編譯插件就使用默認版本進行編譯,這就容易出現編譯版本與源代碼不匹配,甚至導致編譯不通過。

  例如:如果代碼中使用了Java 8 新特性,如函數式編程,但編譯時使用Java 7,那就完全不可能編譯通過,但如果編譯時使用java11則可以編譯通過,java高版本jdk的語法是向下兼容的。

  為了避免使用低版本jdk編譯高版本java語法的情況,在構建項目時就要配置maven-compiler-plugin插件,指定項目源碼的 jdk 版本,編譯后的 jdk 版本,以及編碼方式。

  從 maven-compiler-plugin-3.8.0 之后,默認 編譯 版本由 1.5 改為 1.6 。但這仍然跟不上 JDK 的更新速度,目前大多數系統都在使用 JDK 1.8。Apache Maven Project 對 maven-compiler-plugin中compiler:compile有如下關於jdk版本變更的描述:

img

<plugin>
    <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,源代碼中不能使用低版本jdk中不支持的語法,會存在target不同於source的情況 
        -->
        <source>1.8</source><!-- 源碼語法版本 -->
        <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>javac路徑</executable>
        <compilerVersion>1.3</compilerVersion><!-- 指定插件將使用的編譯器的版本 -->
        <meminitial>128m</meminitial><!-- 編譯器使用的初始內存 -->
        <maxmem>512m</maxmem><!-- 編譯器使用的最大內存 -->
        <!-- 這個選項用來傳遞編譯器自身不包含但是卻支持的參數選項 -->
        <compilerArgument>-verbose -bootclasspath ${java.home}\lib\rt.jar</compilerArgument>
    </configuration>
</plugin>                             

2.全局配置maven JDK編譯版本

   此種設置方式將影響由maven創建的所有項目。找到maven的settings.xml配置文件,加入如下配置片段:

<profiles>
    <profile>
        <id>default-jdk8-env</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>

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

1.插件知識簡介

  maven-compiler-plugin插件3.0之前,默認使用 JDK 自帶的 javac 進行編譯。但從3.0開始(需要JDK1.6),默認使用的 Java 編譯器 是javax.tools.JavaCompiler。如果仍然希望使用 JDK 自帶的 javac 編譯源代碼,需要為 mvn 指定啟動參數:-Dmaven.compiler.forceJavacCompilerUse=true

  maven-compiler-plugin插件編譯時和編譯后運行的JVM版本目前默認的設置為1.5,默認用此版本,而不是根據你在IDEA項目結構中指定的工程JDK版本編譯。如果想改變這些默認設置,應該設置編譯源和目標中java編譯器的目標,通過設置Java源代碼兼容的JVM版本,標明Java源代碼開發過程中使用的Java版本,通過設置編譯后的類庫擬運行的JVM版本,給出編譯后的類庫將要運行的Java環境(一般都會設置,因為很少有項目再用1.7以下的版本了):

  同時 mvn 的運行需要依賴 JDK ,maven-compiler-plugin 插件默認使用當前運行 mvn 命令的 JDK 去編譯Java源代碼。如果想使用其他版本的 JDK (比如本地 java 環境的,而非maven自帶的)編譯Java源代碼,則需要設置如下(重點fork 、executable、compilerVersion):

  上述配置中,用於編譯 Java 源代碼的是 JDK 1.8 ,運行mvn命令時指定maven所使用的是JDK1.6

2.官網也建議指定編譯的jdk版本

  如果是web項目,就需要打war包,那就需要這個插件:

  使用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中的:

  編譯成功

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 Propertiesjava.lang.System.getProperties()中的屬性,比如java.home,引用方式:${java.home}

6.工作機制

  Maven強大的一個重要的原因是它有一個十分完善的生命周期模型,它有三套相互獨立的生命周期,請注意這里說的是“三套”,請別將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插件

https://blog.csdn.net/qq_34272760/article/details/127148290

三、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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM