之前我有记录过一次SpringBoot多模块项目的搭建,但是那一次只是做了一个小小的测试。只是把各模块联通之后就结束了。
最近要增加业务开发,要将目前的单模块项目改成多模块项目,我就参照了一下我上次搭建的流程,发现总是有报错。上次搭建的比较顺利,很多细枝末节也没有仔细去研究。结果就是这次多模块项目搭建的过程就充满了奇幻。就有了这篇笔记。
一:创建父项目
首先我们先在IDEA中创建一个父项目,使用Maven托管。如下图所示:
点击下一步,不需要添加任何依赖,点击创建完成即可。
项目创建成功如下图所示:
删除图上红框标注的所有文件,只保留pom.xml
二:创建子项目
我这里现阶段有两个子项目,分别是入口模块Entry和功能模块WxProgram。
我们先来创建入口模块Entry,入口模块,顾名思义就是他只做入口使用,除了启动类之外,没有其他任何功能。
功能模块WxProgram,就是一个完整的SpringBoot项目,该有的功能都有,例如:Controller,service,dao,pojo,filter等
1 :创建功能模块WxProgram
这个跟创建父工程的流程是一样的,唯一不同的就是第一步,如下图所示:
建议创建子模块的包名是一致的,我这里使用的组名是:com.modules(建议每个子模块使用的组名都一致)
2 :创建入口模块entry
参考创建功能模块WxProgram
三:配置父模块pom.xml
父模块得配置pom.xml比较简单,分为三部分:
1 :打包方式:
<!-- 父模块的打包方式-->
<packaging>pom</packaging>
2 :配置子模块
<!--将子模块放在一堆 start -->
<modules>
<module>WxProgram</module>
<module>Entry</module>
</modules>
<!--将子模块放在一堆 end -->
3 :配置build插件
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.1</version>
<configuration>
<skipTests>true</skipTests> <!--默认关掉单元测试 -->
</configuration>
</plugin>
</plugins>
</build>
4 :完整pom.xml文件内容:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.modules</groupId>
<artifactId>moolsnet</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>moolsnet</name>
<description>moolsnet</description>
<properties>
<java.version>11</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<spring-boot.version>2.6.13</spring-boot.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<!-- 父模块的打包方式-->
<packaging>pom</packaging>
<!--将子模块放在一堆 start -->
<modules>
<module>WxProgram</module>
<module>Entry</module>
</modules>
<!--将子模块放在一堆 end -->
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.1</version>
<configuration>
<skipTests>true</skipTests> <!--默认关掉单元测试 -->
</configuration>
</plugin>
</plugins>
</build>
</project>
5 :注意项:
1) 父项目的pom.xml文件中的dependency插件配置中的插件只能配置所有的子模块都用到的插件。
2) Devtools热更新插件不具有传递性,不要放公共maven库。
6 :子模块编译顺序
<!--将子模块放在一堆 start -->
<modules>
<module>WxProgram</module>
<module>Entry</module>
</modules>
<!--将子模块放在一堆 end -->
子模块的编译顺序就如同我们上边写的顺序一样。谁写在前边就先编译谁。
四:功能子模块pom.xml
子模块pom配置分为两种。功能子模块pom.xml配置和入口子模块配置。二者的区别就是在build标签部分配置。
1 :配置父模块信息
<!-- 配置父工程 -->
<parent>
<groupId>com.modules</groupId>
<artifactId>moolsnet</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<!-- 配置打包方式 -->
<packaging>jar</packaging>
2 :功能子模块build标签部分
<build>
<plugins>
<!--热部署配置插件-->
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<!--热部署配置-->
<configuration>
<!--fork:如果没有该项配置,整个devtools不会起作用-->
<fork>true</fork>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>11</source>
<target>11</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>${spring-boot.version}</version>
<configuration>
<!-- <mainClass>com.modules.MoolsnetApplication</mainClass>-->
<skip>true</skip>
</configuration>
<executions>
<execution>
<id>repackage</id>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
功能子模块部分需要将启动类那一行注释功能模块不需要启动类。
3 :dependency标签部分就是按需配置,你需要啥啥插件就配置啥插件。
五:入口子模块pom.xml配置
1 :配置父模块信息
<!-- 配置父工程 -->
<parent>
<groupId>com.modules</groupId>
<artifactId>moolsnet</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<!-- 配置打包方式 -->
<packaging>jar</packaging>
2 :配置功能模块依赖
<dependencies>
<!--devtools热部署-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional> <!-- 这个需要为 true 热部署才有效 -->
<scope>true</scope>
</dependency>
<!-- 配置WxProgram 模块依赖-->
<dependency>
<groupId>com</groupId>
<artifactId>WxProgram</artifactId>
<version>0.0.1-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
</dependencies>
3:入口子模块build标签部分
<build>
<plugins>
<!--热部署配置插件-->
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<!--热部署配置-->
<configuration>
<!--fork:如果没有该项配置,整个devtools不会起作用-->
<fork>true</fork>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>11</source>
<target>11</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>${spring-boot.version}</version>
<configuration>
<mainClass>com.modules.EntryApplication</mainClass>
<!-- 此行需要注释,否则打包之后的jar文件执行会报错没有主类-->
<!-- <skip>true</skip>-->
</configuration>
<executions>
<execution>
<id>repackage</id>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
六:配置入口模块启动类
这部分很简单,只需要在入口模块添加一个注解扫描第三方jar中的组件。
完整代码如下:
package com.modules;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;
//@SpringBootApplication(scanBasePackages = "com.modules")
@ComponentScan(basePackages = "com")
@SpringBootApplication
public class EntryApplication {
public static void main(String[] args) {
SpringApplication.run(EntryApplication.class, args);
}
}
注意一下,如果@ComponentScan注解扫描的范围与@SpringBootApplication扫描的范围一致,会报错:
冗余声明: @SpringBootApplication 已应用给定的 @ComponentScan
解决方式也很简单,扩大@ComponentScan扫描的范围。就如我上方的代码那样。
七:配置热更新
这部分很简单,但是我好像没有配置成功。
1 :子模块配置插件Devtools
<!--devtools热部署-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional> <!-- 这个需要为 true 热部署才有效 -->
<scope>true</scope>
</dependency>
2 :配置IDEA
File-Settings-Compiler-Build Project automatically 当修改配置文件,自动重启
中文版如下图所示:
你以为配置完这个就结束了嘛。不不不,你太年轻了
还需要配置本地的启动项设置如下图所示:
如果你界面的位置显示的跟我的不一样,那你需要新建一个,点击编辑配置:
最后一张图片中红框标注的位置需要配置一下。然后你就可以往下走了。
点击编辑配置,如下图所示:
点击修改选项,选择红框中标注的两个选项。然后,刚才点击的两个选项就到了如下图所示的位置:
这个两个位置的设置都是一样的,都设置为“更新类和资源”
到这里,你的IDEA再修改java文件,他就应该是热更新的了。
配置到这里,单模块项目是不好用得,多模块项目就不行了,后边开发的时候我也懒得配了,直接使用快捷键ctrl + F9即可编译项目。每次想调试项目之前按一下就可以了。时间长了就是肌肉记忆了。
八:maven的坑
之前都是使用单模块项目来开发,第一次换到多模块项目有点迷茫。直接在父项目中执行maven clean,如下图所示:
然后运行项目,启动项目不报错,浏览器访问报错:
报错就报错叭,关键是控制台还没有报错信息,这给我整的一头雾水,这可如何是好。
后来,我一琢磨,执行mvn clean 就是把编辑好的jar文件全部清除掉了,再次运行,打包的只是入口模块entry,而功能模块wxprogram是没有打包的,因此,我们使用mvn package现将功能模块wxprogram打包,在重新启动入口模块entry,发现,浏览器访问成功。
九:配置运行日志
这部分只需要在入口模块配置即可。
这部分请移步《SpringBoot(三)集成日志》
十:配置mybatis
这部分只需要在需要使用数据库的功能模块配置即可。
这部分请移步《SpringBoot(二)集成mybatis》
但是这里注意一个小小的问题:
我使用的是@SelectProvider等注解来操作数据库。因此我们需要在每个dao接口上配置@Mapper注解,因此我们就不需要在启动类上配置 @MapperScan注解进行全局扫描了。
十一:解决自动构建错误
项目报错:错误:Maven 资源编译器: 模块 'SpringBootBlog' 所需的 Maven 项目配置不可用。仅当从 IDE 启动外部构建时,才支持 Maven 项目编译。
解决方式如下图所示:
十二:打个包
打包顺序很简单,就是按照你的项目的依赖顺序进行打包,我这里的项目是先打包WxProgram功能模块,再打包Extry功能模块。
最后,使用命令行执行打包后的Entry.jar文件。能正常运行,说明打包成功。
以上大概就是多模块项目的创建过程。
有好的建议请在下方输入你的评论。