1.情景展示
在JavaWeb開發過程中,我們通常會基於springmvc分層思想對整個項目進行分層開發:
常見的就是分為model(域模型層)、dao(數據庫訪問層)、service(業務邏輯層)、controller(控制器層)、web(表現層),這樣分層之后,各個層之間的職責會比較明確,后期維護起來也相對比較容易。
通常我們會將其維護到一個模塊當中,也就是一個項目就是一個模塊,把不同的層用包進行區分,如下圖左側部分。
但是,隨着項目越來越復雜,每個層的規模也逐漸增大,在一個模塊中進行開發,會給測試和維護帶來不便,對於大型項目來說,一般會將每個層放到自己的模塊中,然后每個層建立聯系,單獨維護。
對於后期開發維護人員來說,右面這種分模塊的方式更直觀,看着比單模塊舒服很多。
好處不多說,用了才知道。
2.分層梳理
下面兩張圖片方便大家對於即將分開的模塊之間的關系有着重要的指導意義。
按照上面的思路,確定好哪些包需要移到哪些模塊,下面就着手遷移啦。
3.分模塊搭建/改造
新建模塊
選中項目,右鍵--》New--》Module
下一步
給模塊起個名字
關於名字,如果項目名稱不長的話,建議使用“項目名稱-模塊名稱”的方式,這樣更加直觀;
當然了,這是建議,直接取模塊名稱也是完全沒有問題的。
我們先來了解一下,新建模塊的結構:
說白了,這就是maven的標准目錄(因為還沒有Java文件,所以還沒生成target目錄,idea會幫我們完成的)。
第一步:遷移公共類(如果沒有就忽略);
base目錄,我放的是基本工具類等公共需要用到的東西
將這個base目錄直接拖拽到bill-base模塊java目錄下
在To package里輸入包名路徑,路徑構成一般為:
com.公司名稱.項目名稱.原來的包名,這有這樣,才能保證不同模塊的路徑前綴是一致的。
不存在的包名會被創建
創建成功后,class連同包名都會完成遷移
如果出現上面這種原來的被沒有刪除的情況,手動刪除即可。
我們知道,基本工具類一般情況下,是需要jar包依賴的,遷移成功后如果報錯的話:
鼠標懸浮上去,在idea中,點擊添加jar包,會自動將jar包依賴增加到對應的pom文件中。
注意:
由於是基礎工具類,其它模塊不一定會用到這個模塊,即使需要用到,也不一定就需要用這里面的jar包,所以,我們可以把bill-base里的依賴設置成可選依賴,這樣,其它模塊需要對應jar包時,需要重新引入依賴;也不宜引起jar包沖突。
第二步:遷移實體類;
新建model模塊
同樣,關鍵在於遷移的包名(要把po這個包放到哪里)
第二關鍵點:下圖提示,是在告訴我們,哪里用到了po包里的Java類
不要理會,強制遷移。
遷移成功
在這里,po層就顯得有些多余了,重命名,將其刪除即可。
第三步:遷移dao層;
新建dao模塊;
遷移dao層;
強制遷移;
如果出現多余的包名,通過重命名將其刪除。
我們知道,dao層又叫持久層,SQL映射也在這層完成,所以,我們只遷移dao層是遠遠不夠的,還可以將對應的SQL.xml遷移過來。
遷移SQLMap.xml文件;
拖拽遷移,並新建一個mapper文件夾
容易出錯的地方:
錯誤目錄長這個樣子,最終導致在啟動項目后,對應SQL無法執行的問題。
如果出現刪除原來目錄導致新生成的目錄也隨之消失的情況,只能還原,只拖動xml完成遷移了。
更改sqlMapper.xml的命名空間(與dao層相對照)
改對了,下面就不會再報紅了。
還沒結束,還需要完成jar包依賴的遷移;
首先是模塊依賴;
按照依賴對照關系,dao肯定需要依賴model。所以,在bill-dao的pom.xml中添加對model的依賴。
補充:在子模塊中,我們可以指定父pom文件訪問路徑,這樣方便我們跳轉及識別。
其次才是jar包依賴。
將父pom.xml中的關於mybatis,數據庫連接池,mybatis-plus等相關jar包依賴
重新導包
最后一步:重新編譯項目。
注意:這里,只重新編譯bill-dao模塊,因為還沒有遷移完畢,重新構建整個項目的話,報錯信息會出現一大坨,但我們根本無法修改。
說明:要想只編譯bill-dao模塊,需要鼠標通過點擊選中這個模塊,再進行Build選項時才會出現編譯這個模塊的選項。
你會發現一堆bill-dao模塊的報錯信息,不要怕。
雙擊錯誤信息,會直接跳轉到報錯的java類。
改成正確引用路徑即可。
挨個把所有bill-dao模塊的報錯信息改完就行了。
第四步:遷移service層;
如果我們像往常一樣進行遷移
這里會出現一個問題:
如果不是新建的目錄(一個不存在的目錄)的話,將會遷移失敗。
必須這樣做,才能遷移成功:
選中java目錄,右鍵新建package
選中service下的所有子包。
強制遷移。
遷移成功,但vo包沒有遷移過去。
引入模塊依賴,導包;
構建bill-service模塊
這里分兩種情況:
一種是向上依賴,像原來的dao層和po層已經被我們遷移了出來,改下路徑就行了;
另一種是向下依賴,service層依賴web層,這種向下串層的行為在模塊化后是不被允許的,
像:模塊A依賴模塊B,模塊B又依賴於模塊A,這種互相依賴是不被允許的,強制引入,在最終打包的時候會導致打包失敗;只能進行單向或單方依賴。
所以,解決辦法就是把service層需要的web層的相關包全部遷移到service模塊。
遷移完成
這里需要注意的是:
按理說,dto是需要放在web模塊的,但是,由於service模塊需要用到,所以,我只將dto里部分文件進行了遷移(最好不要這樣搞)。
遷移jar包依賴;
大部分的jar包依賴都集中在service模塊。
這里需要提醒的是:
雖然校驗和knife4j嚴格意義上來說,是屬於web模塊的東西,但是,web和service兩個模塊其實是不能完全撇清的,剪不斷理還亂。
既然service層要用,索性干脆把這類jar包全部從web層搬到service層,這樣,web模塊在引入service模塊后,也就引入了這些jar包依賴。
對於程序的運行,不受絲毫影響。
完成jar包遷移后,重新導包,重新編譯bill-service模塊,也許就會報錯了。
如果項目中使用了Lombok插件,就會報錯。
原因是:我們剛才將Lombokjar包依賴從父pom文件中遷移到了bill-service子pom文件,身為同級的bill-model自然就找不到啦。
所以,我們需要將lombok依賴從bill-service,遷移到bill-model。
前面也說了,只要其它同級模塊引入這個模塊,其它模塊就也能直接使用Lombok注解,無需重新引入jar依賴。
第五步:遷移web層。
鑒於上面相同目錄導致遷移失敗的問題,我們還是手動創建包名好了。
總之,在idea中進行遷移會引發各種各樣的路徑問題,真是能惡心死人,只能自己逐個排查或這等報錯再改啦。
遷移完畢
bill項目下的src變得空空如也,直接將這個src刪除即可。
也許,我們的項目所有模塊都會變成這個吊樣,真是想罵街:
都被強制加一個web包。
只能通過重命名后再將web目錄刪除。
需要提醒一點:
啟動類是放在項目根目錄下的,即:和web同級,別像我一樣,改着改着改懵了,把它們也放到了web目錄下,
導致的結果就是:
啟動項目后,一直報錯:找不到注入的service模塊類,A component required a bean of type...
添加模塊依賴;
說明:
第一,引入的模塊,必須指定版本號,不能省略<version>標簽;
第二,版本號的值可以跟隨項目通過,通過${project.version} 取值。
遷移jar包;
把父pom文件中所剩下的jar包依賴全部遷移到bill-web的pom文件中(父pom.xml中最好一個jar包依賴都不要留)。
bill-web的pom文件,除了模塊依賴,通常情況下只有單元測試和springboot相關依賴。
重新編譯bill-web目錄,解決報錯路徑問題。
修改啟動類注解掃描包;
dao路徑改成正確的
修改日志配置文件關於dao層的引用
修改攔截器關於控制層路徑引用
遷移項目構建工具;
將父pom.xml打包方式設為pom;
項目公共屬性配置,也在父pom文件中進行,子pom文件通過${}引入即可。
如果需要多環境支持,在父pom中添加profile即可。
父pom文件,還可以配置maven中央倉庫
模塊出錯
如果創建出來的模塊或者在遷移過程中導致java或resources目錄發生了變化:變成了普通目錄,就需要將該模塊刪除,重新創建。
刪除模塊
錯誤方式
第一步:remove module
選中要刪除的模塊,右鍵,選擇“Remove Module”。
從項目移除成功后,文件夾將會變色;
右鍵--》刪除即可。
但是,這種方式並不能刪除干凈,再次重建這個模塊時(模塊名稱一致),就會出現模塊出錯那種情況,這是idea惡心人的一點。
正確方式
在ide中根本就刪不干凈,最好的辦法就是關閉項目,然后從磁盤中刪掉項目,從svn或git上重新將整個項目下載下來再重新新建模塊(重頭再來)。
當然了,如果你不用再同一個模塊名字的話,對你來說是沒有任何影響的,也就犯不着刪掉整個項目了。
4.關於View層能否從Web層剝離出來的探究
剝離步驟:
第一步:創建view模塊,並將web/main目錄下的webapp目錄遷移到view/main下
第二步:指定view模塊的打包形式為:war(只有這樣,webapp目錄才不會被作為打包后的一層父目錄)
第三步:web模塊引入iew模塊依賴
第四步:重新導包並啟動項目;
項目啟動正常
瀏覽器訪問跳轉到jsp的請求
經過以上測試發現:無法將前端界面從web模塊進行剝離。
5.運行
改造完畢后,還是像不分模塊之前那樣,直接用main方法啟動類啟動項目即可。
根本不需要所謂的在pom.xml中指定唯一的main方法入口。
可能會出現這種情況:
解決辦法:
點擊這個啟動類,選擇“Edit Configurations”
打開配置頁面
在這里,我們會看到底部錯誤信息提示:在bill模塊中找不到這個啟動類。
實際上,bill是一個項目而不是模塊,我們只需要將模塊指定成該啟動類所在模塊即可。
展開“Environment”界面,在“Use classpath of module”中進行模塊切換即可。
如果能成功啟動還能看到原來的執行效果,那么項目多模塊的重構就完成了。
6.打包
要想打包,需要確定三個問題:
第一,打成什么樣的包(war還是jar)?
第二,哪個模塊作為主模塊(不是父模塊),之所以這樣叫,是因為,其它同級或子級模塊都將會被它包含在該模塊中。
對應前后端交互的項目,我們通常會將web模塊作為主模塊進行打包。
在web模塊對應的pom.xml中指定packaging,如果設置該標簽,與普通項目一樣,將默認被打成jar包。
添加構建工具;
指定構建工具,並引入springboot自帶的maven插件。
注意:其它模塊也是允許有自己的構建工具。
雖然,service模塊也指定了maven編譯插件,但是,web還是主模塊,並沒有受到影響。
這就讓我很疑惑了,idea是怎么選取web作為主模塊的?
為了測試這個問題,我將dao里也加上了springbootmaven插件
打包失敗:dao模塊沒有程序入口
通過以上實驗,大致了解到:
當pom.xml引入springbootmaven插件后,在打包時,該插件會在該模塊中尋找啟動類。將程序入口作為主模塊也就成了順理成章之事了。
所以,一般情況下,引入springbootmaven插件的模塊將會被作為主模塊。
第三,選擇哪個模塊進行打包?
通過上面得知:
既然,web會被識別為主模塊,那我們直接對它進行打包不就行啦?
執行package命令,結果卻打臉:
web模塊所依賴的這些同級模塊,竟被從maven倉庫中下載它們所對應的jar包,結果可想而知。
所以,不能用主模塊完成整個項目的打包。
在idea中,通過一個帶(root)的maven模塊完成項目打包。
也只有通過它才能完成整個項目的打包,下面的子模塊只能完成對自己模塊的打包。
通過root會分別對每個模塊進行打包,這是與沒有分模塊開發的項目,在打包時最大的區別。
打開右側的maven視圖
打jar包
在web模塊對應的pom中指定成jar包。
clean,package
日志輸出如下:
jar包展示
打war包
方式同上
war包展示
我們可以看到,其它模塊都被打成了jar包,因為我們沒有在對應的模塊的pom文件中指定打包形式。
我覺得這樣挺好的,提高了代碼的安全性,讓別人不能通過項目一下就全攬了所有代碼。
如果你還配置了多環境,勾選上指定環境再打包就可以了。