SpringBoot入門之spring-boot-maven-plugin

spring-boot-maven-plugin插件是將springboot的應(yīng)用程序打包成fat jar的插件极谊。首先我們說一下啥叫fat jar轻猖。fat jar 我們暫且叫他胖jar吧,實在是找不到官方叫法了咙边。我們一般的jar琉雳,里面放的是.class文件已經(jīng)resources目錄下的東西翠肘,但是fat jar 它可以把jar作為內(nèi)容包含進(jìn)去辫秧。也就是說盟戏,spring boot 借助spring-boot-maven-plugin將所有應(yīng)用啟動運行所需要的jar都包含進(jìn)來,從邏輯上將具備了獨立運行的條件邮旷。

我們將普通插件maven-jar-plugin生成的包和spring-boot-maven-plugin生成的包unzip,比較一下他們直接的區(qū)別婶肩,發(fā)現(xiàn)使用spring-boot-maven-plugin生成的jar中主要增加了兩部分律歼,第一部分是lib目錄险毁,這里存放的是應(yīng)用的Maven依賴的jar包文件,第二部分是spring boot loader相關(guān)的類畔况,這個我們下一節(jié)再說spring boot 的加載流程问窃。

在項目中需要先加入spring-boot-maven-plugin嵌戈。

           <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <version>1.3.2.RELEASE</version>
                <configuration>
                    <mainClass>test.ApplicationMain</mainClass>
                </configuration>
                <executions>
                    <execution>
                        <goals>
                            <goal>repackage</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>

默認(rèn)是在package階段執(zhí)行spring-boot-maven-plugin repackage這個目標(biāo)。我們看一下RepackageMojo的關(guān)鍵方法execute

    @Override
    public void execute() throws MojoExecutionException, MojoFailureException {
        if (this.project.getPackaging().equals("pom")) {
            getLog().debug("repackage goal could not be applied to pom project.");
            return;
        }
        if (this.skip) {
            getLog().debug("skipping repackaging as per configuration.");
            return;
        }
        //得到項目中的原始的jar听皿,就是使用maven-jar-plugin生成的jar
        File source = this.project.getArtifact().getFile();
        //要寫入的目標(biāo)文件熟呛,就是fat jar
        File target = getTargetFile();
        Repackager repackager = new Repackager(source) {
            //從source中尋找spring boot 應(yīng)用程序入口的main方法。
            @Override
            protected String findMainMethod(JarFile source) throws IOException {
                long startTime = System.currentTimeMillis();
                try {
                    return super.findMainMethod(source);
                }
                finally {
                    long duration = System.currentTimeMillis() - startTime;
                    if (duration > FIND_WARNING_TIMEOUT) {
                        getLog().warn("Searching for the main-class is taking some time, "
                                + "consider using the mainClass configuration "
                                + "parameter");
                    }
                }
            }
        };
        //如果插件中指定了mainClass就直接使用
        repackager.setMainClass(this.mainClass);
        if (this.layout != null) {
            getLog().info("Layout: " + this.layout);
            repackager.setLayout(this.layout.layout());
        }
        //尋找項目運行時依賴的jar尉姨,過濾后
        Set<Artifact> artifacts = filterDependencies(this.project.getArtifacts(),
                getFilters(getAdditionalFilters()));
        //將Artifact轉(zhuǎn)化成Libraries 
        Libraries libraries = new ArtifactsLibraries(artifacts, this.requiresUnpack,
                getLog());
        try {
            LaunchScript launchScript = getLaunchScript();
            //進(jìn)行repackage
            repackager.repackage(target, libraries, launchScript);
        }
        catch (IOException ex) {
            throw new MojoExecutionException(ex.getMessage(), ex);
        }
        if (this.classifier != null) {
            getLog().info("Attaching archive: " + target + ", with classifier: "
                    + this.classifier);
            this.projectHelper.attachArtifact(this.project, this.project.getPackaging(),
                    this.classifier, target);
        }
        else if (!source.equals(target)) {
            this.project.getArtifact().setFile(target);
            getLog().info("Replacing main artifact " + source + " to " + target);
        }
    }

基本上重要的步驟都有注釋庵朝,應(yīng)該不難理解的。再來看下面又厉,當(dāng)然也不是重點九府,看看就行。

public void repackage(File destination, Libraries libraries,
            LaunchScript launchScript) throws IOException {
        if (destination == null || destination.isDirectory()) {
            throw new IllegalArgumentException("Invalid destination");
        }
        if (libraries == null) {
            throw new IllegalArgumentException("Libraries must not be null");
        }
        if (alreadyRepackaged()) {
            return;
        }
        destination = destination.getAbsoluteFile();
        File workingSource = this.source;
        //如果源jar與目標(biāo)jar的文件路徑及名稱是一致的
        if (this.source.equals(destination)) {
            //將源jar重新命名為原名稱+.original,同時刪除原來的源jar
            workingSource = new File(this.source.getParentFile(),
                    this.source.getName() + ".original");
            workingSource.delete();
            renameFile(this.source, workingSource);
        }
        destination.delete();
        try {
            //將源jar變成JarFile 
            JarFile jarFileSource = new JarFile(workingSource);
            try {
                repackage(jarFileSource, destination, libraries, launchScript);
            }
            finally {
                jarFileSource.close();
            }
        }
        finally {
            if (!this.backupSource && !this.source.equals(workingSource)) {
                deleteFile(workingSource);
            }
        }
    }

這一步所做的是清理工作覆致,如果源jar同目標(biāo)文件路徑名稱等一致侄旬,將源jar重命名,原來的文件刪除。為目標(biāo)文件騰位置族操。下面的重點來了炕婶。

    private void repackage(JarFile sourceJar, File destination, Libraries libraries,
            LaunchScript launchScript) throws IOException {
        JarWriter writer = new JarWriter(destination, launchScript);
        try {
            final List<Library> unpackLibraries = new ArrayList<Library>();
            final List<Library> standardLibraries = new ArrayList<Library>();
            libraries.doWithLibraries(new LibraryCallback() {
                @Override
                public void library(Library library) throws IOException {
                    File file = library.getFile();
                    if (isZip(file)) {
                        if (library.isUnpackRequired()) {
                            unpackLibraries.add(library);
                        }
                        else {
                            standardLibraries.add(library);
                        }
                    }
                }
            });
            //按照規(guī)則寫入manifest文件
            writer.writeManifest(buildManifest(sourceJar));
            Set<String> seen = new HashSet<String>();
            writeNestedLibraries(unpackLibraries, seen, writer);
           //寫入源jar中的內(nèi)容
            writer.writeEntries(sourceJar);
           //寫入標(biāo)準(zhǔn)的jar,依賴的jar
            writeNestedLibraries(standardLibraries, seen, writer);
            if (this.layout.isExecutable()) {
               //寫入spring boot loader的類
                writer.writeLoaderClasses();
            }
        }
        finally {
            try {
                writer.close();
            }
            catch (Exception ex) {
                // Ignore
            }
        }
    }

上面就是一通寫危喉,將所需要的內(nèi)容全部寫入到目標(biāo)文件中。然后就有了我們的fat jar。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末钉寝,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌言沐,老刑警劉巖矿筝,帶你破解...
    沈念sama閱讀 221,406評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件鼻疮,死亡現(xiàn)場離奇詭異,居然都是意外死亡挪哄,警方通過查閱死者的電腦和手機颠毙,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,395評論 3 398
  • 文/潘曉璐 我一進(jìn)店門闹伪,熙熙樓的掌柜王于貴愁眉苦臉地迎上來椰憋,“玉大人,你說我怎么就攤上這事。” “怎么了残制?”我有些...
    開封第一講書人閱讀 167,815評論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我字支,道長栗菜,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,537評論 1 296
  • 正文 為了忘掉前任暴备,我火速辦了婚禮障癌,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己嗽冒,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 68,536評論 6 397
  • 文/花漫 我一把揭開白布氛堕。 她就那樣靜靜地躺著,像睡著了一般痛倚。 火紅的嫁衣襯著肌膚如雪蝉稳。 梳的紋絲不亂的頭發(fā)上操漠,一...
    開封第一講書人閱讀 52,184評論 1 308
  • 那天吻贿,我揣著相機與錄音,去河邊找鬼。 笑死横侦,一個胖子當(dāng)著我的面吹牛引瀑,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播榨馁,決...
    沈念sama閱讀 40,776評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼憨栽,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了翼虫?” 一聲冷哼從身側(cè)響起屑柔,我...
    開封第一講書人閱讀 39,668評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎珍剑,沒想到半個月后掸宛,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,212評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡招拙,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,299評論 3 340
  • 正文 我和宋清朗相戀三年唧瘾,在試婚紗的時候發(fā)現(xiàn)自己被綠了措译。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,438評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡饰序,死狀恐怖领虹,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情菌羽,我是刑警寧澤掠械,帶...
    沈念sama閱讀 36,128評論 5 349
  • 正文 年R本政府宣布由缆,位于F島的核電站注祖,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏均唉。R本人自食惡果不足惜是晨,卻給世界環(huán)境...
    茶點故事閱讀 41,807評論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望舔箭。 院中可真熱鬧罩缴,春花似錦、人聲如沸层扶。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,279評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽镜会。三九已至檬寂,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間戳表,已是汗流浹背桶至。 一陣腳步聲響...
    開封第一講書人閱讀 33,395評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留匾旭,地道東北人镣屹。 一個月前我還...
    沈念sama閱讀 48,827評論 3 376
  • 正文 我出身青樓,卻偏偏與公主長得像价涝,于是被迫代替她去往敵國和親女蜈。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,446評論 2 359

推薦閱讀更多精彩內(nèi)容