公司有幾個老古董專案,應該是 10 年前開發的了,有一個是 JSP + Servlet,有一個還用的 SSH 框架,打包用的 Ant,是有多老啊,我想在座的各位很多都沒聽過吧。
為了持續整合、持續部署的需要,需要把這些老古董專案全改造成 Maven 管理,下面開搞。
快速建立一個 Maven 專案
Maven Archetype 介紹
如何快速建立一個 Maven 專案,可以通過 Maven 的 Archetype 來進行建立,Archetype 是 Maven 提供的各種各樣的工程模板,通過這些模板可以生成不同的 Maven 專案結構。
Maven 提供的 Archetype 列表如下:
Archetype ArtifactIds | Description |
---|---|
maven-archetype-archetype | generate a sample archetype project. |
maven-archetype-j2ee-simple | generate a simplifed sample J2EE application. |
maven-archetype-mojo | generate a sample a sample Maven plugin. |
maven-archetype-plugin | generate a sample Maven plugin. |
maven-archetype-plugin-site | generate a sample Maven plugin site. |
maven-archetype-portlet | generate a sample JSR-268 Portlet. |
maven-archetype-quickstart | generate a sample Maven project. |
maven-archetype-simple | generate a simple Maven project. |
maven-archetype-site | generate a sample Maven site which demonstrates some of the supported document types like APT, XDoc, and FML and demonstrates how to i18n your site. |
maven-archetype-site-simple | generate a sample Maven site. |
maven-archetype-webapp | generate a sample Maven Webapp project. |
這裡我們選擇 maven-archetype-quickstart
這個模板進行快速建立,因為它提供了一個標準的專案結構,基於這個基本專案結構可以進行後續擴充套件。
project
|-- pom.xml
`-- src
|-- main
| `-- java
| `-- $package
| `-- App.java
`-- test
`-- java
`-- $package
`-- AppTest.java
生成 Maven 專案
1)通過 Maven 命令
Maven 提供了命令快速建立 Maven 專案:
mvn archetype:generate
-DarchetypeGroupId=org.apache.maven.archetypes
-DarchetypeArtifactId=maven-archetype-quickstart
-DarchetypeVersion=1.4
命令中指定我們前面所說的 Maven Archetype:maven-archetype-quickstart
資訊。
執行過程中會提示讓你輸入專案的 Naven 座標資訊,直到建立完成。基礎部分這裡不撰述了,需要完整 Maven 教程的關注公眾號Java技術棧在後臺回覆"mvn"獲取。
2)通過 IDEs
通過 IDE 也能快速建立 Maven 專案,現在 Java IDEs 都支援 Maven 或者自帶 Maven 外掛,下面以 Intellij IDEA
為例進行建立。
選擇 maven-archetype-quickstart
:
輸入專案的 Naven 座標資訊:
選擇 Maven 及倉庫設定資訊:
等待專案構建完成,如下所示:
Maven 專案重構
Maven 專案配置
專案生成後,我們就可以把原系統的檔案移到新的 Maven 專案了,因生成的專案結構比較簡單,Maven 提供的 maven-archetype-webapp
模板也不符合要求:
我們的專案性質又是後臺系統,涉及到方方面面,所以還需要再完善其他資源目錄的建立:
- src
- main
- java
- resources
- filters
- webapp
- test
- java
- resources
這是一個比較標準的 Maven Web 專案結構,我把它弄成了一個基礎腳手架,還整合了各種現成的外掛和功能,後面其他專案轉 Maven 可以直接拿來套用。
已經上傳到了 Github:
主要目錄結構介紹:
目錄 | 說明 |
---|---|
src/main/java | 原始碼目錄 |
src/main/resources | 資源目錄 |
src/main/filters | 多環境配置過濾目錄 |
src/main/webapp | Web應用檔案目 |
src/test/java | 測試程式碼目錄 |
src/test/resources | 測試資源目錄 |
所有目錄建立完後,再根據檔案性質把原系統所有除了(*.jar)檔案移到對應的目錄,這裡沒什麼難度。
配置 Maven 環境資訊:
<build>
<filters>
<filter>src/main/filters/filter-${env}.properties</filter>
</filters>
<resources>
<resource>
<directory>src/main/resources/config</directory>
<filtering>true</filtering>
</resource>
<resource>
<directory>src/main/resources/resource</directory>
<filtering>false</filtering>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>${maven-compiler-plugin.version}</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>${maven-war-plugin.version}</version>
<configuration>
<failOnMissingWebXml>false</failOnMissingWebXml>
</configuration>
</plugin>
</plugins>
</build>
<profiles>
<profile>
<id>dev</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<env>dev</env>
</properties>
</profile>
<profile>
<id>test</id>
<properties>
<env>test</env>
</properties>
</profile>
<profile>
<id>mirror</id>
<properties>
<env>mirror</env>
</properties>
</profile>
<profile>
<id>prod</id>
<properties>
<env>prod</env>
</properties>
</profile>
</profiles>
Maven 依賴轉換
依賴轉換就是要把所有原系統的(*.jar)依賴包全部轉換為 Maven 依賴管理,這裡是難點,要解決編譯、啟動、執行時遇到的 jar 包衝突、版本衝突等異常。
我的思路是先把一些核心框架的依賴進行轉換,再進行一些比較獨立的公共工具包的轉換,最後就是一些不熟悉的依賴轉換。
引入 Maven 依賴的時候,看下其所有附屬的所有依賴,再逐漸從 lib 目錄刪除,直到全部刪除完成即轉換完成。
在找對應依賴的時候,如果中央倉庫找不到,其他遠端倉庫能找到的,就在公司私庫中新增該包所在的遠端倉庫代理配置。
如果中央倉庫或者其他遠端倉庫都找不到的,比如第三方的 SDK 包,就上傳到公司私庫。怎麼上傳到私庫,點選這裡閱讀,更多 Maven 教程在公眾號Java技術棧回覆maven進行閱讀。
根據 JAR 包找 Maven 依賴的時候,可能有多個名稱一樣的依賴,不知道引用哪個,這時候需要去原始 JAR 包中看下包名,根據包名就大概知道座標資訊了。
依賴傳遞:
在依賴轉換過程中,如果一個依賴又依賴了其他依賴,可以直接引用父依賴即可,如在老專案中存在:poi、poi-ooxm、poi-ooxml-schemas 這三個依賴:
但在 POI 依賴體系中,poi-ooxml
包又需要依賴其他兩個包,所以只需要引入 poi-ooxml
依賴即可:
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>4.1.2</version>
</dependency>
這樣就把這個包需要依賴的其他包都引進來了,這就是 Maven 管理依賴的好處,不會出現多包少包的情況,也能儘量避免依賴衝突。
依賴範圍:
在老專案中,所有 jar 包都在 web-inf/lib 目錄下,如:Servlet、JUnit,這些包在打完生產包之後也還在目錄下,沒有生命週期的管理。
在 Maven 中就能控制它們的生命週期:
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>${javax.servlet-api.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
Servlet 只需要編譯時用到,JUnit 只需要測試時用到,控制好每個包的依賴範圍,做到每個包的作用範圍最小化。
解決衝突:
當傳遞的依賴版本不符合,或者是同一個包出現不同版本導致衝突的時候要學會使用排除:
或者強制指定包版本:
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk16</artifactId>
<version>${bctsp-jdk16.version}</version>
</dependency>
有的時候,還要根據需要使用 classifier
指定不同 JDK 的版本:
<dependency>
<groupId>com.test</groupId>
<artifactId>test</artifactId>
<version>${test.version}</version>
<classifier>JDK6</classifier>
</dependency>
如原始碼編譯報錯,不知道引用的哪個 JAR 包、或者哪個版本,可以到原始專案中點對應的類引用進去看就知道了。
整個改造過程比較順利,就是編譯和執行時需要解決一些 JAR 包衝突導致的問題,根據上面的種種方法直至編譯、啟動正常。
以後可以舒舒服服用 Maven 咯。
整理了半天,無私分享給大家,希望你們能有收穫,覺得不錯,歡迎點贊、轉發喲~
近期熱文推薦:
1.Java 15 正式釋出, 14 個新特性,重新整理你的認知!!
2.終於靠開源專案弄到 IntelliJ IDEA 啟用碼了,真香!
3.我用 Java 8 寫了一段邏輯,同事直呼看不懂,你試試看。。
覺得不錯,別忘了隨手點贊+轉發哦!