今天早上在CSDN首页看到了杨秀璋老师的《我与CSDN这十年》,感触很深,之后又去看了他之前的《向死而生,为爱而活》,好美!
前言
之前实习时接触到的项目以及好多网上的开源项目都是 springboot 多模块项目,所以就想试着自己搭建一个,学习一波。看了很多关于 springboot 多模块项目的博文,感觉都不是自己想要的样子,我觉得着这种只按照逻辑层(dao、service、controller、...)来拆分的多模块远远不能满足项目开发的需求,应该按照大模块划分,比如权限、api的调用端来划分。
源码:https://github.com/XGLLHZ/springboot-frame
正文
项目共有四个模块:
frame-authority:权限模块,
frame-main:启动模块
frame-mp:小程序模块,也就是只给小程序端提供 api
frame-web:web模块,只给 web 端提供 api
(当然这只是一种假设,得具体情况再做分析)
项目结构:
1、首先创建父工程,父工程为 springboot 项目,创建好之后删除 src、.mvn、HELP.md、mvnw、mvnw.cmd文件。因为父工程只扮演者一个组织架构的作用,所以不需要这些文件。
2、在父工程上右键新建 module,四个 module 也是 springboot 项目,依次创建 frame-main、frame-authority、frame-mp、frame-web 四个模块,创建完成之后,除 frame-main 之外,将其它三个模块的启动类、rescource文件夹下的所有文件都删掉。
注:加入在创建 frame-main 模块是的 groupId 为 org.huangzi ,artifactId main,那么其余三个模块的 groupId 则为 org.huangzi.main,否则的话,在启动类也就是 frame-main 模块启动时会扫描不到其它三个模块中的类。frame-main 是全局唯一的入口。
3、修改父工程的 pom.xml 文件:
<!--继承 springboot 提供的父工程-->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.0.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>org.huangzi</groupId>
<artifactId>frame</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>frame</name>
<description>Demo project for Spring Boot</description>
<packaging>pom</packaging> <!-- 打包方式为 pom -->
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<!--引入子模块-->
<modules>
<module>frame-main</module> <!--启动模块-->
<module>frame-authority</module> <!--权限模块-->
<module>frame-web</module> <!-- web 模块-->
<module>frame-mp</module> <!--小程序模块-->
</modules>
<dependencies>
<!-- springboot 多模块项目中的所有依赖都在父工程的 pom 文件中管理,包括版本等 -->
<!-- springboot 启动-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<!-- springboot 测试 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- springboot web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--在这里可以加入整个项目所有模块所需的依赖,比如权限、日志、数据库等-->
</dependencies>
<build>
<plugins>
<!-- 因为 frame 不是一个可运行的项目,所以使用 maven 打包方式(具体为啥还不知道) -->
<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>
</plugins>
</build>
4、修改 frame-main 启动模块的 pom.xml 文件:
<!--继承父模块-->
<parent>
<groupId>org.huangzi</groupId>
<artifactId>frame</artifactId>
<version>0.0.1-SNAPSHOT</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>org.huangzi</groupId>
<artifactId>main</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>main</name>
<description>Demo project for Spring Boot</description>
<packaging>jar</packaging> <!--注意打包方式为 jar-->
<dependencies>
<!--因为 frame-main 模块是启动模块,所以需要将其它所有的模块引进来,这样,每个模块都可以对外提供 api -->
<!-- 引入权限模块依赖 -->
<dependency>
<groupId>org.huangzi.main</groupId>
<artifactId>authority</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<!-- 引入 web 模块依赖 -->
<dependency>
<groupId>org.huangzi.main</groupId>
<artifactId>web</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<!-- 引入小程序模块依赖 -->
<dependency>
<groupId>org.huangzi.main</groupId>
<artifactId>mp</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<!-- 指定该类为全局唯一入口 -->
<mainClass>org.huangzi.main.MainApplication</mainClass>
<layout>ZIP</layout>
</configuration>
<executions>
<execution>
<!--可以把依赖的包都打包到生成的Jar包中-->
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
5、修改其余三个模块的 pom.xml 文件:(其余三个模块若无特殊应用场景,则跟下面的一样)
<!--继承父模块-->
<parent>
<groupId>org.huangzi</groupId>
<artifactId>frame</artifactId>
<version>0.0.1-SNAPSHOT</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>org.huangzi.main</groupId>
<artifactId>mp</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>mp</name>
<description>Demo project for Spring Boot</description>
<packaging>jar</packaging>
<dependencies>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
注:所有依赖的版本控制,包括 java 版本等,都可以统一在 父工程的 pom.xml 中配置。其次,yml 文件放在启动模块中,在扫描 .xml 文件以及 mapper 时需要特殊处理 。
备注:在 spriingboot 多模块项目中,注入类时好像与在单体项目中有所区别,具体什么原因我也不知道,但是解决办法如下:
主要使用 @Primary 和 @Qualifier这两个注解来解决(实际上这是解决当你要注入的类有两个时的解决办法,但是在多模块项目中尽管只有一个类,但它也会出现这样的错误)
@Service
@Primary #在被注入的类上加此注解,表示该类是注入的主要类
@Component("sysUserService")
public class SYSUserServiceImpl extends ServiceImpl<SYSUserMapper, SYSUser> implements SYSUserService {
@Autowired
SYSUserMapper sysUserMapper;
@Autowired
SYSUserRoleMapper sysUserRoleMapper;
@Autowired
SYSTokenMapper sysTokenMapper;
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
@Qualifier("sysUserService") #在需要注入的地方加此注解,意味合格者,表明哪个类才是需要注入的
SYSUserService sysUserService; //系统用户信息-账号、角色
@Autowired
FilterRequestRole filterRequestRole; //请求信息-url、角色
向死而生,为爱而活!