參考若依后台管理項目,感覺一個好的項目程序的健壯性十分重要,其中很多程序設計思路和技巧規范值得我們好好學習。其中碰到的第一個那便是創建 Springboot 多模塊項目,實際操作中遇到很多問題,特此記錄一下。
多模塊項目優點:https://www.yuque.com/xihuanxiaorang/ng3te7/awrxnc多模塊項目通常由一個父模塊和若干個子模塊構成,每個模塊對應着一個 pom 文件。父模塊與子模塊之間通過繼承與聚合相互關聯。多模塊適用於一些比較大的項目,通過合理的模塊拆分,實現代碼的復用,便於維護和管理。
1、RuoYi 項目文件結構
com.ruoyi
├── common // 工具類
│ └── annotation // 自定義注解
│ └── config // 全局配置
│ └── constant // 通用常量
│ └── core // 核心控制
│ └── enums // 通用枚舉
│ └── exception // 通用異常
│ └── filter // 過濾器處理
│ └── utils // 通用類處理
├── framework // 框架核心
│ └── aspectj // 注解實現
│ └── config // 系統配置
│ └── datasource // 數據權限
│ └── interceptor // 攔截器
│ └── manager // 異步處理
│ └── security // 權限控制
│ └── web // 前端控制
├── ruoyi-generator // 代碼生成(可移除)
├── ruoyi-quartz // 定時任務(可移除)
├── ruoyi-system // 系統代碼
├── ruoyi-admin // 后台服務
├── ruoyi-xxxxxx // 其他模塊
2、RuoYi 各模塊間的依賴關系

3、創建 Springboot 多模塊項目
在創建多模塊項目的時候,得先捋一捋每個模塊的作用,搞清楚每個模塊干什么用的動起手來才更加清晰,有目的性。
如上圖所示,分為4個子模塊和一個父模塊。
其中,common 模塊用於存放一些工具類,system 模塊主要存放 entity,service 和 mapper 文件,framwork 模塊主要用於管理框架的配置,admin 模塊作為整個后台管理系統的入口,主要存放一些 controller 文件。
1、創建 my-ruoyi 父模塊
新建項目,選擇新建 maven 項目,填寫所需的項目坐標。
pom.xml 文件配置:
<properties>
<my-ruoyi.version>1.0.0-SNAPSHOT</my-ruoyi.version>
<maven-jar-plugin.version>3.1</maven-jar-plugin.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>1.8</java.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.5.5</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- 通用工具-->
<dependency>
<groupId>top.xiaorang</groupId>
<artifactId>ruoyi-common</artifactId>
<version>${my-ruoyi.version}</version>
</dependency>
<!-- 系統模塊-->
<dependency>
<groupId>top.xiaorang</groupId>
<artifactId>ruoyi-system</artifactId>
<version>${my-ruoyi.version}</version>
</dependency>
<!-- 核心模塊-->
<dependency>
<groupId>top.xiaorang</groupId>
<artifactId>ruoyi-framework</artifactId>
<version>${my-ruoyi.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
<modules>
<module>ruoyi-common</module>
<module>ruoyi-system</module>
<module>ruoyi-framework</module>
<module>ruoyi-admin</module>
</modules>
<packaging>pom</packaging>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>${maven-jar-plugin.version}</version>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
<encoding>${project.build.sourceEncoding}</encoding>
</configuration>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<id>public</id>
<name>aliyun nexus</name>
<url>http://maven.aliyun.com/nexus/content/groups/public/</url>
<releases>
<enabled>true</enabled>
</releases>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>public</id>
<name>aliyun nexus</name>
<url>http://maven.aliyun.com/nexus/content/groups/public/</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>false</enabled>
</snapshots>
</pluginRepository>
</pluginRepositories>
刪除 src 目錄:因為父模塊不用來寫代碼,所以刪除不必要的目錄。
2、創建 ruoyi-common 模塊
點擊 my-ruoyi 父模塊,創建 ruoyi-common 公共模塊。
pom.xml 文件配置:
<dependencies>
<!-- 自定義驗證注解 -->
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
</dependency>
<!-- JSON工具類 -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
<!-- lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
</dependencies>
3、創建 ruoyi-system 模塊
同上面創建 ruoyi-common 模塊一樣創建 ruoyi-system 系統模塊。
pom.xml 文件配置:
<dependencies>
<!-- SpringDataJpa -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>top.xiaorang</groupId>
<artifactId>ruoyi-common</artifactId>
</dependency>
</dependencies>
該模塊主要用來編寫實體類,業務層和數據訪問層。
4、創建 ruoyi-framework 模塊
同上面創建 ruoyi-common 模塊一樣創建 ruoyi-framework 核心模塊。
pom.xml 文件配置:
<dependencies>
<dependency>
<groupId>top.xiaorang</groupId>
<artifactId>ruoyi-system</artifactId>
</dependency>
</dependencies>
5、創建 ruoyi-admin 模塊
同上面創建 ruoyi-common 模塊一樣創建 ruoyi-admin 后台管理模塊,即 web 模塊。
pom.xml 文件配置:
<dependencies>
<!-- SpringBoot Web容器 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Mysql驅動包 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>top.xiaorang</groupId>
<artifactId>ruoyi-framework</artifactId>
</dependency>
</dependencies>
該模塊主要用來編寫 Controller 層代碼。
最后,使用 postman 工具來測試一下是否能夠正確的訪問數據庫獲取數據:

代碼已經上傳到 GitHub,地址為 https://github.com/xihuanxiaorang/my-ruoyi
知識點擴展重要
1、scope=import
在使用 springboot 時,項目可能需要使用自己的父模塊,而不能繼承 spring-boot-starter-parent 時,任然可以通過使用 scope=import 來保持依賴管理,springboot 官方文檔推薦配置:
<dependencyManagement>
<dependencies>
<dependency>
<!-- 從Spring Boot導入依賴管理 -->
<groupId> org.springframework.boot </groupId>
<artifactId> spring-boot-dependencies </artifactId>
<version> 2.1 .12.RELEASE </version>
<type> pom </type>
<scope> import </scope>
</dependency>
</dependencies>
</dependencyManagement>
根據 maven 官方文檔對依賴范圍的描述:
- import
This scope is only supported on a dependency of type pom in thesection. It indicates the dependency is to be replaced with the effective list of dependencies in the specified POM's section. Since they are replaced, dependencies with a scope of import do not actually participate in limiting the transitivity of a dependency.
import 只能用在 dependencyManagement 塊中,它是將 spring-boot-dependencies 中 dependencyManagement 的 dependencies 全部引入到當前工程的 dependencyManagement 中,所以不存在依賴傳遞。
2、type=pom
根據 maven 官方文檔對 type 的描述:
- type:
Corresponds to the chosen dependency type. This defaults to jar. While it usually represents the extension on the filename of the dependency, that is not always the case: a type can be mapped to a different extension and a classifier. The type often corresponds to the packaging used, though this is also not always the case. Some examples are jar, ejb-client and test-jar: see default artifact handlers for a list. New types can be defined by plugins that set extensions to true, so this is not a complete list.
type,和被選擇依賴的類型相對應,默認為 jar。通常它和依賴模塊的擴展名一致,不過也不一定,因為一個模塊的類型,可以被映射為不同的擴展名或分類上。通常 type 和依賴模塊的 packaging 對應,盡管並不總是這樣。比如 type 的值 ejb-client, test-jar,具體可以看看默認的構件處理器。這里說的是,大多數的模塊,其實是有個默認的 packaging 與被依賴時候的 type 對應關系的,這個對應關系應該是有個構件處理器來決定的。

總結重要:
type=pom 說白了就是為了完全繼承對方的管理依賴和屬性定義。綠線解釋有些時候 dependency 里面的 type 不用加,有些時候不加卻報錯(即通常為了獲取繼承來的 pom.xml 里面的 properties 里面的各種包的版本號之類的信息,沒有的話就不能確定版本,當然報錯)
3、maven-compiler-plugin 插件
maven 是個項目管理工具,如果不告訴它代碼要使用什么樣的 jdk 版本編譯,它就會使用 maven-complier-plugin 編譯插件默認的 jdk 版本來編譯代碼,這樣就很容易出現版本不匹配的問題,以至於可能導致編譯不通過的問題。例如代碼中要是使用了 jdk1.8 的新特性(函數式編程),但是 maven 在編譯的時候使用的是 jdk7,那帶有 jdk1.8 新特性的代碼是不可能編譯通過的。為了避免此類問題的出現,在構件 mvane 項目的時候,應該先配置 maven-compiler-plugin 插件,指定項目源碼的 jdk 版本,編譯后的 jdk 版本,以及編碼方式。
從 3.8.0 版本后,maven-compiler-plugin 插件默認的 jdk 版本就由 1.5 變成 1.6 。但是這任然跟不上 jdk 的更新速度,目前大多數系統都在使用 jdk1.8。
maven-compiler-plugin 插件中 compiler:compile 有如下關於 jdk 版本變更的描述:

詳細配置:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
4、@Transient注解
實體類中如果使用了 @Table 注解后,要想添加表中不存在的字段,就可以使用 @Transient 注解。@Transient 注解表示該屬性並非是一個要映射到數據庫的字段,ORM框架會忽略該屬性。注解可以加在屬性上,也可以加上 get() 方法上。
5、@EqualsAndHashCode注解
這個注解的作用就是自動給 model bean 實現 equals 方法和 hashcode 方法。
如果使用 @EqualsAndHashCode(callSuper=false),就表示不調用父類的屬性,如果子類的屬性完全相同,那么 hashcode 的值就相同啦,用 equals 方法比較的時候就會返回 true。如果使用 @EqualsAndHashCode(callSuper=true),那就是用自己的屬性和父類繼承的屬性一起生成 hashcode,equals 方法比較的結果返回 false。
6、@DynamicInsert 和 @DynamicUodate 注解
@DynamicInsert:默認為 true,指定用於 insert 的 sql 將會再運行時動態生成,並且只包含那些非空值字段。
@DynamicUpdate:默認為 true,指定用於 update 的 sql 將會在運行時動態生成,並且只更新那些改變過的字段。
如果希望在新增的時候只包含設置了值的字段,更新時只包含發生變化的字段,那么就可以使用 @DynamicInsert 和 @DynamicUpdate 注解。
7、@IdClass 注解
@IdClass 注解可以實現一個實體類中有兩個主鍵,即聯合主鍵。首先我們需要創建一個聯合主鍵類並且實現序列化接口,類名為 SysUserRoleKey,該類中有 userId 和 roleId 這兩個字段,這個類的要求有三個:
-
需要實現 Serializable 接口
-
需要一個默認的 public 的 無參構造方法,使用 Lamada 的 @NoArgsConstructor 注解幫我們實現,或者如果沒有定義有參構造的情況下,這個注解也可以不需要,因為有默認的無參構造方法
-
重寫 equals 和 hashCode 方法。

使用的時候,在 SysUserRole 實體類上使用 @IdClass(value = SysUserRoleKey.class) 注解,然后 userId 和 roleId 都分別使用 @Id 注解即可。

參考鏈接
創建 springboot 多模塊項目:
https://blog.csdn.net/MacWx/article/details/103787209
type=pom 的理解:
