maven 打包时缺少文件_(三)Java资源文件和路径相关扫盲
本來打算接著上文直接寫登錄功能的,順便介紹下SpringSecurity,但是SpringSecurity和Spring以及SpirngBoot是如何銜接的又是個(gè)較為復(fù)雜的事情。看了下SpringBoot的啟動(dòng)過程之后,發(fā)現(xiàn)里面很多地方用到了類加載器以及Classpath等。其實(shí)如果沒用過Eclipse寫過傳統(tǒng)的java項(xiàng)目或者web項(xiàng)目,經(jīng)常會(huì)對ClassPath,根目錄,類加載器,jar包格式,war包格式等迷糊,所以一方面自己總結(jié)下,一方面也給大家掃下盲。
一、Jar包和War包
通常來說java可以分為普通項(xiàng)目和web項(xiàng)目。普通項(xiàng)目的運(yùn)行我們需要自己寫一個(gè)main函數(shù),然后以這個(gè)main函數(shù)作為入口啟動(dòng)項(xiàng)目。而web項(xiàng)目則需要交給servlet容器去啟動(dòng),通常是tomcat或者jetty。web項(xiàng)目的啟動(dòng)過程是一個(gè)十分復(fù)雜的事情,不過目前我們不用關(guān)心細(xì)節(jié),畢竟是一篇掃盲文章。
1、什么是打包
除了SDK以外,一個(gè)項(xiàng)目我們寫完之后都需要部署到linux服務(wù)器上運(yùn)行。但是并不是直接部署項(xiàng)目源碼到linux上,而是經(jīng)過編譯,打包后的"包"。整個(gè)過程我們稱之為構(gòu)建(build),后端常用的構(gòu)建工具也就那幾個(gè),當(dāng)然最簡單也最普遍的就是maven了。編譯和打包對應(yīng)到maven命令則分別是compile和package。
mvn compile可以將.java文件編譯成.class文件,也就是將源碼轉(zhuǎn)化為字節(jié)碼,即一次編譯到處運(yùn)行的編譯過程。
mvn package則將編譯后的.class文件和相關(guān)的資源配置如.properties配置文件.xml配置文件按照約定或者我們自己的配置整合到一個(gè)jar包或者war包中。至于如何整合,以及最終是jar包還是war包,要根據(jù)我們的配置來決定,maven的配置文件就是項(xiàng)目根目錄下的pom.xml文件。
所以打包可以有兩個(gè)概念,術(shù)語來說就是指mvn package這一步,如果是我們口頭上常說的打包其實(shí)就是整個(gè)構(gòu)建過程。
2、如何打包
目前市場上最常用的構(gòu)建工具要屬maven(其他的還有ant,gradle等就不介紹了)。
首先我們使用idea創(chuàng)建一個(gè)maven項(xiàng)目:File -> New -> Project,然后一路點(diǎn)next就行
創(chuàng)建Maven項(xiàng)目這樣我們就創(chuàng)建了一個(gè)最基本的maven項(xiàng)目,如下圖所示
創(chuàng)建完成的Maven項(xiàng)目目錄結(jié)構(gòu)可以看到,我們通過maven創(chuàng)建的項(xiàng)目,已經(jīng)有了自己默認(rèn)的目錄結(jié)構(gòu)。這里不得不提到這個(gè)目錄結(jié)構(gòu)的由來,即maven的核心思想:約定先行于配置。只要知道了這個(gè),maven的神秘面紗就基本揭開了。
maven為什么要提供這樣一個(gè)默認(rèn)的結(jié)構(gòu)?這個(gè)目錄結(jié)構(gòu)又有什么用呢?
maven給我們提供的這個(gè)默認(rèn)的結(jié)構(gòu)其實(shí)就是對我們的約定,即認(rèn)為我們的項(xiàng)目目錄結(jié)構(gòu)就是這個(gè)樣子,并沒有自己的改動(dòng)。如果我們遵守了這個(gè)約定,則我們在不需要自己額外配置的情況下,可以對項(xiàng)目進(jìn)行正確的構(gòu)建。
因?yàn)閖ar和war都是有著嚴(yán)格格式要求的,所以正確的構(gòu)建就是指打包后的項(xiàng)目目錄格式能夠滿足規(guī)定的格式要求。綜合起來就是如果我們的項(xiàng)目結(jié)構(gòu)和maven約定的結(jié)構(gòu)相同,則我們可以直接使用mvn package進(jìn)行打包,無需在pom.xml文件中進(jìn)行額外配置。當(dāng)然如果我們想應(yīng)用自己的目錄結(jié)構(gòu),也可以在pom.xml文件中配置相關(guān)內(nèi)容,讓項(xiàng)目正確構(gòu)建。pom.xml就是maven的相關(guān)配置文件。
JAR包:
用剛才創(chuàng)建的項(xiàng)目,我們先在java目錄下創(chuàng)建一個(gè)類,然后再運(yùn)行mvn package就可以進(jìn)行一次打包:
mvn packge之后的項(xiàng)目雖然我們只運(yùn)行了一個(gè)mvn package命令,但是從構(gòu)建日志上來看,似乎運(yùn)行了很多插件。沒錯(cuò),mvn package并不只是運(yùn)行package插件,而且根據(jù)maven的插件生命周期運(yùn)行package和它之前的所有插件。
package之前最重要的一步就是compile,打包的也是編譯后的文件夾。圖上有個(gè)黃色的target文件夾就是編譯后的文件。而這里有個(gè)classes目錄,就是所謂的ClassPath,這個(gè)概念之后我們會(huì)經(jīng)常遇到,java項(xiàng)目所有的相關(guān)內(nèi)容編譯后都會(huì)直接放在ClassPath下。
target是編譯后的目錄,但仍需要將編譯后的文件夾轉(zhuǎn)化為jar文件。我們打開打包后的jar包。
test-1.jar可以看到target/classes目錄下的內(nèi)容直接放到了jar包的根目錄,并且多了個(gè)META-INF文件夾。至于META-INF文件夾有什么作用,暫且可以不用知道,不過我們目前可以確定的就是,ClassPath對應(yīng)著Jar包的根目錄,對應(yīng)著編譯后的target的classes目錄。
WAR包:
和jar包不同但經(jīng)常使用到的就是web項(xiàng)目打包后的war包了。我們重新創(chuàng)建一個(gè)項(xiàng)目,并且使用maven提供的約定好的web項(xiàng)目的目錄結(jié)構(gòu):maven-archetype-webapp
創(chuàng)建完成的項(xiàng)目基礎(chǔ)結(jié)構(gòu)如下
我們可以發(fā)現(xiàn)main目錄下還缺少一個(gè)java目錄,我們需要自己添加一個(gè)java目錄,并且設(shè)置成Root目錄,resources目錄設(shè)置成Source目錄,然后創(chuàng)建一個(gè)java類,至此一個(gè)基本的web模型已經(jīng)創(chuàng)建完成了。
接下來就是打包測試,我們運(yùn)行mvn package命令:
如同普通java項(xiàng)目一樣,項(xiàng)目結(jié)構(gòu)中多了個(gè)編譯后的target文件夾。只不過我們需要注意兩個(gè)子文件夾,分別是classes和web。classes文件夾下存放的依然是編譯后的.class文件,而原來的webapp目錄編譯后則變成了web目錄,并且將WEB-INF目錄保留了下來。另外你會(huì)發(fā)現(xiàn),classes文件夾在WEB-INF下也有一個(gè)。這兩個(gè)classes文件夾是一模一樣的。我們來打開war包看看:
和web目錄一模一樣。所以我們可以得出一個(gè)結(jié)論就是:ClassPath在web項(xiàng)目中就是/WEB-INF/classes目錄。
另外無論是java項(xiàng)目還是javaweb項(xiàng)目,都會(huì)有個(gè)resources文件夾,你試一下就可以知道,這個(gè)目錄下的內(nèi)容打包后都會(huì)被復(fù)制到ClassPath目錄下。
通常上面的測試我們可以了解到,jar包和war包的固定格式。通常來說我們不需要自己去打破約定,按照自己的方式設(shè)置項(xiàng)目目錄,因?yàn)轫?xiàng)目畢竟是很多人在同時(shí)完成,還是需要有一定的標(biāo)準(zhǔn)。
二、資源文件的加載
通過上面的介紹我們現(xiàn)在已經(jīng)很清楚什么是ClassPath路徑了對吧。下面我們來了解一下Java項(xiàng)目中資源文件的加載。
Java項(xiàng)目中加載資源文件通常有兩種方式:1、Class.getResource(String path)
2、Class.getClassLoader().getResource(String path)
這兩種方式有一些區(qū)別,首先來看1:
可以看出,如果是絕對路徑,則絕對路徑的起點(diǎn)為ClassPath,如果為相對路徑,則路徑的起點(diǎn)為該類的所在目錄,也就是圖中的TestClass所在的目錄。
然后來看2,依舊是上面那個(gè)項(xiàng)目結(jié)構(gòu):
可以看出如果使用類加載器加載資源,則只能填入相對路徑,且路徑的起點(diǎn)一定是ClassPath,而且跟這個(gè)類在哪沒有任何關(guān)系。
三、環(huán)境變量相關(guān)資源
在了解ClassLoader體系之前我們應(yīng)該先了解一下我們剛學(xué)Java時(shí)最頭疼的問題,環(huán)境變量。
大家對JDK和JRE一定不陌生,其中JRE是Java的運(yùn)行環(huán)境,而JDK包含了JRE。
jdk文件目錄JDK比JRE多出來的東西主要就是bin目錄下的一些exe程序,提供給我們一些強(qiáng)大的開發(fā)工具。常用的有javac、java、javap等。
jdk/bin目錄回想一下,學(xué)習(xí)Java的時(shí)候我們配置過三個(gè)環(huán)境變量:
JAVA_HOME:JDK的安裝目錄
CLASS_PATH:指向系統(tǒng)JAVA_HOME所在路徑的lib文件夾或者其下面的jar包
PATH:添加到PATH路徑下的exe文件,可以在cmd中直接使用。所以通常是將JAVA_HOME所在路徑的bin文件夾添加到PATH,這樣就能在cmd命令行中直接使用java、javac等命令了。我們在學(xué)習(xí)Mysql時(shí)配置Path同樣是這個(gè)原因。通過這里我們又學(xué)到了一個(gè)CLASS_PATH,只不過這里指的是系統(tǒng)變量。
最后附上一條個(gè)人認(rèn)為目前看到過寫的最全的一個(gè)關(guān)于類加載器的一篇文章,不過文章中有些地方有點(diǎn)錯(cuò)誤,比如引導(dǎo)類加載器加載的并不是JAVA_HOME路徑下的類,而是JRE_HOME下的類。
https://blog.csdn.net/javazejian/article/details/73413292?blog.csdn.net總結(jié)
以上是生活随笔為你收集整理的maven 打包时缺少文件_(三)Java资源文件和路径相关扫盲的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 机器人专用符文_英雄联盟【LOL】手游部
- 下一篇: java美元兑换,(Java实现) 美元