这是我参与8月更文挑战的第5天,活动详情查看: 8月更文挑战
最近在做一个很复杂的会员综合线下线上商城大型项目,单模块项目无法满足多人开发和架构,很多模块都是重复的就想到了把模块提出来,做成公共模块,基于maven的多模块项目,也好分工开发,也便于后期微服务重构
我刚开始创建项目的时候是基于单模块,开发的,我先开发的接口api 项目结构是这样的
core
模块是公共模块,mallapi 是小程序
api
,随然单体项目这样的结构也还清晰,但是后面我想到,还有后台
web api
,又要重新创建一个项目,core模块,数据库连接
mode
l模块这些都是通用的,又是需要在后台项目复制一遍,我觉得很不爽,不友好,代码很冗余,
于是就用
SpringBoot+Maven
多模块项目的构建、运行、打包,完美解决问题
我创建的基于
SpringBoot+Maven
多模块项目结构如下
kmall-admin
模块 后台模块,后台接口api
kmall-api
模块前端小程序,app的api
kmall-bean
实体bean 模块
kmall-common
公共模块
kmall-quartz
定时任务模块
kmall-service
服务模块
kmall-security
安全认证模块
kmall-sys
后台系统模块
项目依赖管理打包
首先最外层
kmall
是父模块 管理着所有的版本和依赖,外层pom如下
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>cn.soboys.kmall</groupId>
<artifactId>kmall</artifactId>
<version>1.0-SNAPSHOT</version>
<modules>
<module>kmall-common</module>
<module>kmall-bean</module>
<module>kmall-service</module>
<module>kmall-api</module>
<module>kmall-admin</module>
<module>kmall-sys</module>
<module>kmall-security</module>
<module>kmall-quartz</module>
</modules>
<packaging>pom</packaging>
<!--引用springBoot父项目-->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.4.7</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<kmall.version>1.0-SNAPSHOT</kmall.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>1.8</java.version>
<maven.compiler.plugin.version>3.7.0</maven.compiler.plugin.version>
<maven.resources.plugin.version>3.2.0</maven.resources.plugin.version>
<maven.jar.plugin.version>3.2.0</maven.jar.plugin.version>
<maven-war-plugin.version>3.2.3</maven-war-plugin.version>
<spring-boot.version>2.4.7</spring-boot.version>
<mybatis.plus.boot.starter.version>3.4.3</mybatis.plus.boot.starter.version>
<mybatis-plus-generator.version>3.4.1</mybatis-plus-generator.version>
<freemarker.version>2.3.31</freemarker.version>
<p6spy.version>3.9.0</p6spy.version>
<fastjson.version>1.2.76</fastjson.version>
<jjwt.version>0.9.1</jjwt.version>
<java-jwt.version>3.15.0</java-jwt.version>
<weixin-java-miniapp.version>4.0.0</weixin-java-miniapp.version>
<weixin-java-pay.version>4.0.0</weixin-java-pay.version>
<hutool.version>5.7.0</hutool.version>
<ip2region.version>1.0.3.RELEASE</ip2region.version>
<knife4j.version>3.0.1</knife4j.version>
</properties>
<!--dependencyManagement里只是声明依赖,并不自动实现引入,因此子项目需要显示的声明需要用的依赖
如果不在子项目中声明依赖,是不会从父项目中继承下来的;只有在子项目中写了该依赖项,并且没有指定具体版本,才会从父项目中继承该项,
并且version和scope都读取自父pom;另外如果子项目中指定了版本号,那么会使用子项目中指定的jar版本
<!--统一管理依赖的版本号-->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>cn.soboys.kmall</groupId>
<artifactId>kmall-common</artifactId>
<version>${kmall.version}</version>
</dependency>
<dependency>
<groupId>cn.soboys.kmall</groupId>
<artifactId>kmall-bean</artifactId>
<version>${kmall.version}</version>
</dependency>
<dependency>
<groupId>cn.soboys.kmall</groupId>
<artifactId>kmall-service</artifactId>
<version>${kmall.version}</version>
</dependency>
<dependency>
<groupId>cn.soboys.kmall</groupId>
<artifactId>kmall-security</artifactId>
<version>${kmall.version}</version>
</dependency>
<dependency>
<groupId>cn.soboys.kmall</groupId>
<artifactId>kmall-sys</artifactId>
<version>${kmall.version}</version>
</dependency>
<!--<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>${mybatis.plus.boot.starter.version}</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
<version>${mybatis-plus-generator.version}</version>
</dependency>
<dependency>
<groupId>com.github.hiwepy</groupId>
<artifactId>ip2region-spring-boot-starter</artifactId>
<version>${ip2region.version}</version>
</dependency>
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-spring-boot-starter</artifactId>
<version>${knife4j.version}</version>
</dependency>
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>${freemarker.version}</version>
</dependency>
<dependency>
<groupId>p6spy</groupId>
<artifactId>p6spy</artifactId>
<version>${p6spy.version}</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>${jjwt.version}</version>
</dependency>
<dependency>
<groupId>com.github.binarywang</groupId>
<artifactId>weixin-java-miniapp</artifactId>
<version>${weixin-java-miniapp.version}</version>
</dependency>
<dependency>
<groupId>com.github.binarywang</groupId>
<artifactId>weixin-java-pay</artifactId>
<version>${weixin-java-pay.version}</version>
</dependency>
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>${java-jwt.version}</version>
</dependency>
<!-- <dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>${hutool.version}</version>
</dependency>-->
<!--json 序列化-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>${fastjson.version}</version>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-core</artifactId>
<version>${hutool.version}</version>
<!--<exclusions>
<exclusion>
<groupId>cn.hutool</groupId>
<artifactId>hutool-setting</artifactId>
</exclusion>
</exclusions>-->
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-json</artifactId>
<version>${hutool.version}</version>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-http</artifactId>
<version>${hutool.version}</version>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-extra</artifactId>
<version>${hutool.version}</version>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-crypto</artifactId>
<version>${hutool.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
<!-- 环境信息 -->
<profiles>
<!-- 标机开发环境 -->
<profile>
<id>dev</id>
<properties>
<activeProfile>dev</activeProfile>
<serviceactive>servicedev</serviceactive>
<businessactive>businessdev</businessactive>
</properties>
<activation>
<activeByDefault>false</activeByDefault>
</activation>
</profile>
<!-- 测试环境 -->
<profile>
<id>test</id>
<properties>
<activeProfile>test</activeProfile>
<serviceactive>servicetest</serviceactive>
<businessactive>businesstest</businessactive>
</properties>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
</profile>
<!-- 生产环境 -->
<profile>
<id>product</id>
<properties>
<activeProfile>product</activeProfile>
<serviceactive>serviceproduct</serviceactive>
<businessactive>businessproduct</businessactive>
</properties>
<activation>
<activeByDefault>false</activeByDefault>
</activation>
</profile>
</profiles>
</project>
我们可以把很多公用
的配置放在父模块中如打包环境配置
,jar包版本依赖
,那样的话子模块的pom.xml配置的东西就非常的少了,方便阅读。
这里父项目的pom.xml主要是配置了都需要的SpringBoot
的相关引用,这样的话我们子项目完全不需要再重复引用了。另外其配置了profiles
属性,这个属性是让我们区分多环境是打包哪些配置文件,其id参数
就是我们的要打包环境的一个标识,比如我们打包测试环境我们只需要执行clean install -Ptest即可,-P后面的值即为这个id值,其中properties属性里面的列表是标识该环境生效的配置文件,属性里面的是SpringBoot配置文件后面的值,比如application-serviceproduct.properties其值就为serviceproduct
我们在看下kmall-common
公共模块pom配置如下
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>kmall</artifactId>
<groupId>cn.soboys.kmall</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>kmall-common</artifactId>
<dependencies>
<!--aop 切面-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<!--ip获取位置-->
<dependency>
<groupId>com.github.hiwepy</groupId>
<artifactId>ip2region-spring-boot-starter</artifactId>
</dependency>
<!--api 文档-->
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-spring-boot-starter</artifactId>
</dependency>
<!--数据库jar################-->
<!--mysql-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<!--mybatPlus-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
</dependency>
<!--生成器依赖-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
</dependency>
<!--MyBatis-Plus 从 3.0.3 之后移除了代码生成器与模板引擎的默认依赖,需要手动添加相关依赖:-->
<!--添加 模板引擎 依赖,MyBatis-Plus 支持 Velocity(默认)、
Freemarker、Beetl,用户可以选择自己熟悉的模板引擎,
如果都不满足您的要求,可以采用自定义模板引擎。-->
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
</dependency>
<!-- p6spy sql拦截调试-->
<dependency>
<groupId>p6spy</groupId>
<artifactId>p6spy</artifactId>
</dependency>
<!--数据库jar################-->
<!--微信小程序工具sdk-->
<dependency>
<groupId>com.github.binarywang</groupId>
<artifactId>weixin-java-miniapp</artifactId>
</dependency>
<!--微信支付工具sdk-->
<dependency>
<groupId>com.github.binarywang</groupId>
<artifactId>weixin-java-pay</artifactId>
</dependency>
<!--hutool 工具库-->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-core</artifactId>
<!--<exclusions>
<exclusion>
<groupId>cn.hutool</groupId>
<artifactId>hutool-setting</artifactId>
</exclusion>
</exclusions>-->
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-json</artifactId>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-http</artifactId>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-extra</artifactId>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-crypto</artifactId>
</dependency>
<!--json 序列化-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
</dependency>
</dependencies>
</project>
这里因为kmall
父模块做了项目版本管理,所以这里只需要引入依赖就可以,依赖版本由父模块决定
然后我们在看一下kmall-bean
模块pom
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>kmall</artifactId>
<groupId>cn.soboys.kmall</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>kmall-bean</artifactId>
<dependencies>
<dependency>
<groupId>cn.soboys.kmall</groupId>
<artifactId>kmall-common</artifactId>
</dependency>
<!--参数校验-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
</dependencies>
</project>
依赖于公共模块,也单独引用了参数校验依赖
我们在看一下kmall-service
模块pom
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>kmall</artifactId>
<groupId>cn.soboys.kmall</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>kmall-service</artifactId>
<dependencies>
<dependency>
<groupId>cn.soboys.kmall</groupId>
<artifactId>kmall-common</artifactId>
</dependency>
<dependency>
<groupId>cn.soboys.kmall</groupId>
<artifactId>kmall-bean</artifactId>
</dependency>
</dependencies>
</project>
依赖于公共模块,和bean模块
接下来我们看下两个主模块 kmall-api
有springboot启动类入口
ApiApplication
是springboot启动类
package cn.soboys.kmall.api;
import cn.hutool.extra.spring.EnableSpringUtil;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
@SpringBootApplication(scanBasePackages = {"cn.soboys.kmall"})
@MapperScan("cn.soboys.kmall.mapper")
@EnableSpringUtil
public class ApiApplication {
private static ApplicationContext applicationContext;
public static void main(String[] args) {
applicationContext =
SpringApplication.run(ApiApplication.class, args);
//displayAllBeans();
* 打印所以装载的bean
public static void displayAllBeans() {
String[] allBeanNames = applicationContext.getBeanDefinitionNames();
for (String beanName : allBeanNames) {
System.out.println(beanName);
我们来看一下他的pom
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>kmall</artifactId>
<groupId>cn.soboys.kmall</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>kmall-api</artifactId>
<packaging>war</packaging>
<dependencies>
<dependency>
<groupId>cn.soboys.kmall</groupId>
<artifactId>kmall-service</artifactId>
</dependency>
<!--jwt 认证-->
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
</dependency>
</dependencies>
<!--打包-->
<build>
<resources>
<resource>
<filtering>true</filtering>
<directory>src/main/resources</directory>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>${maven.compiler.plugin.version}</version>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
<encoding>${project.build.sourceEncoding}</encoding>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>${maven.resources.plugin.version}</version>
<configuration>
<encoding>${project.build.sourceEncoding}</encoding>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>${maven.jar.plugin.version}</version>
</plugin>
<!-- <plugin>
<artifactId>maven-war-plugin</artifactId>
<version>${maven-war-plugin.version}</version>
<configuration> <!– Exclude JCL and LOG4J since all logging should go through SLF4J. Note that we're excluding log4j-<version>.jar but keeping log4j-over-slf4j-<version>.jar –>
<packagingExcludes>
WEB-INF/lib/hutool-setting.jar,
</packagingExcludes>
</configuration>
</plugin>-->
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>repackage</goal><!--可以把依赖的包都打包到生成的Jar包中-->
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
这里pom做了一个打包的处理,我们需要打包时候只需要通过 IDEA 进行打包就可以啦
package进行打包war 发布到服务器就可以运行啦
我们再来看一下后台模块kmall-admin
有springboot启动类入口WebApplication
@SpringBootApplication
@MapperScan(value = {"cn.soboys.kmall.mapper","cn.soboys.kmall.sys.mapper","cn.soboys.kmall.security.mapper"},nameGenerator = UniqueNameGenerator.class)
@ComponentScan(value = {"cn.soboys.kmall"},nameGenerator = UniqueNameGenerator.class)
public class WebApplication {
private static ApplicationContext applicationContext;
public static void main(String[] args) {
applicationContext =
SpringApplication.run(WebApplication.class, args);
//displayAllBeans();
* 打印所以装载的bean
public static void displayAllBeans() {
String[] allBeanNames = applicationContext.getBeanDefinitionNames();
for (String beanName : allBeanNames) {
System.out.println(beanName);
看下它的pom结构
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>kmall</artifactId>
<groupId>cn.soboys.kmall</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<packaging>war</packaging>
<artifactId>kmall-admin</artifactId>
<dependencies>
<dependency>
<groupId>cn.soboys.kmall</groupId>
<artifactId>kmall-service</artifactId>
</dependency>
<dependency>
<groupId>cn.soboys.kmall</groupId>
<artifactId>kmall-sys</artifactId>
</dependency>
</dependencies>
<!--打包-->
<build>
<resources>
<resource>
<filtering>true</filtering>
<directory>src/main/resources</directory>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>${maven.compiler.plugin.version}</version>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
<encoding>${project.build.sourceEncoding}</encoding>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>${maven.resources.plugin.version}</version>
<configuration>
<encoding>${project.build.sourceEncoding}</encoding>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>${maven.jar.plugin.version}</version>
</plugin>
<!-- <plugin>
<artifactId>maven-war-plugin</artifactId>
<version>${maven-war-plugin.version}</version>
<configuration> <!– Exclude JCL and LOG4J since all logging should go through SLF4J. Note that we're excluding log4j-<version>.jar but keeping log4j-over-slf4j-<version>.jar –>
<packagingExcludes>
WEB-INF/lib/hutool-setting.jar,
</packagingExcludes>
</configuration>
</plugin>-->
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>repackage</goal><!--可以把依赖的包都打包到生成的Jar包中-->
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
这里我配置文件中环境激活是根据父模块pom中配置走的 spring.profiles.active=@activeProfile@,@serviceactive@,@businessactive@
这里的值取值与父pom中环境打包配置
然后我们在打包前勾选需要打包的环境就可以了
这样基于SpringBoot+Maven 多模块项目的构建、运行、打包实战就完成啦,如果有什么疑问可以关注我公众猿小叔