【SpringBoot】还不会SpringBoot项目模块分层?来这手把手教你

2023-04-20,,

前言

缘由

经常看到网上很多优秀的开源项目中,代码简洁,模块分层完美。反观自己代码层级混乱,,却不知如何整理分层。此文手把手教你一步一步创建模块,左手右手一个慢动作。结合本人实际开发及个人项目中分层思路的分享,大神请勿喷

⏲️本文阅读时长

约25分钟

主要目标

    熟练掌握SpringBoot项目分层思路,丝滑拆分模块
    熟悉代码层级依赖,规范化管理模块分布
    手把手实战学习,理论实践相结合

‍试用人群

    对于Springboot熟悉但是不知道合理分层小白
    有自己分层思路可以互相分享学习

快速链接

公众号:JavaDog程序狗

在公众号,发送【分层】 ,无任何套路即可获得

或访问https://blog.javadog.net/archives/boot-module

水图

下图反面教材,传统单体应用,结构臃肿

下图分层截选自本人的一个小项目,模块清晰,分工明确

我们要实现的小栗子的分层

正文

1.IDEA新建项目

起名第一步,一个好名字,说不定是个好的开始

假如我们的项目是个聊天相关的项目,英文对应chat,所以定义项目名为chat-boot,其他的以此效仿

点击New->project

选择Maven项目,并选择合适JDK版本,点击Next

录入项目名称,并填写GAV坐标,点击Finish

删除无用文件及目录,如src目录和*.iml文件

删除后项目目录

修改pom.xml中依赖,增加spring-boot-starter-parent

 <parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.1.RELEASE</version>
</parent>


2.创建子模块-dependencies(依赖层)

右击项目chat-boot,new ->Moudle新建模块chat-boot-dependencies

选择对应Module SDK版本,本人选择jdk1.8

填写子模块名 chat-boot-dependencies,然后检查对应GAV,点击Finish

生成子模块chat-boot-dependencies如下图

删除chat-boot-dependencies下无用文件及目录,如src目录,删除无用目录如下

完善chat-boot-dependencies下pom.xml依赖, 常用依赖放入,作为依赖主体,以下是本狗常用依赖,可酌情选择;记得把packaging改为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>chat-boot</artifactId>
<groupId>net.javadog.chat</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion> <artifactId>chat-dependencies</artifactId> <packaging>pom</packaging> <properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<mysql-connector-java.version>8.0.17</mysql-connector-java.version>
<druid.version>1.1.21</druid.version>
<mybatis-plus.version>3.4.1</mybatis-plus.version>
<fastjson.version>1.2.75</fastjson.version>
<hutool.version>5.5.8</hutool.version>
<lombok.versin>1.18.12</lombok.versin>
<easypoi.version>4.2.0</easypoi.version>
<springfox-swagger2.version>2.9.2</springfox-swagger2.version>
<springfox-swagger-ui.version>2.9.2</springfox-swagger-ui.version>
<knife4j.version>2.0.4</knife4j.version>
<weixin.version>4.4.5.B</weixin.version>
<shiro.version>1.3.2</shiro.version>
<jwt.version>3.2.0</jwt.version>
</properties> <dependencyManagement>
<dependencies>
<!--mybatis-plus-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>${mybatis-plus.version}</version>
</dependency> <!-- 数据库驱动,可根据自己需要自行删减,默认使用mysql -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql-connector-java.version}</version>
</dependency> <!--数据库连接池-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>${druid.version}</version>
</dependency> <!--fastjson-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>${fastjson.version}</version>
</dependency> <!--hutool-->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>${hutool.version}</version>
</dependency> <!--lombok-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.versin}</version>
</dependency> <!--swagger2-->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>${springfox-swagger2.version}</version>
</dependency> <!--swagger-ui-->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>${springfox-swagger-ui.version}</version>
</dependency> <!-- swagger接口文档 -->
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-spring-boot-starter</artifactId>
<version>${knife4j.version}</version>
</dependency> <!--easypoi导入导出-->
<dependency>
<groupId>cn.afterturn</groupId>
<artifactId>easypoi-base</artifactId>
<version>${easypoi.version}</version>
</dependency> <!--WxJava - 微信开发 Java SDK-->
<dependency>
<groupId>com.github.binarywang</groupId>
<artifactId>weixin-java-miniapp</artifactId>
<version>${weixin.version}</version>
</dependency> <!--整合Shiro安全框架-->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>${shiro.version}</version>
</dependency> <!--集成jwt实现token认证-->
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>${jwt.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
</project>

重点

此处用的标签是 dependencyManagement

dependencyManagement只是声明依赖,并不实现引入,因此子项目需要显示的声明需要用的依赖。如果不在子项目中声明依赖,是不会从父项目中继承下来只有在子项目中写了该依赖项,并且没有指定具体版本,才会从父项目中继承该项,并且version和scope都读取自父pom;另外如果子项目中指定了版本号,那么会使用子项目中指定的jar版本。


3.创建子模块-main(主启动层)

右击项目chat-boot,new ->Moudle新建模块chat-boot-main

选择对应Module SDK版本,本狗选择jdk1.8,点击Next

填写子模块名 chat-boot-main,然后检查对应GAV,点击Finish

生成子模块chat-boot-main如下图

完善chat-boot-main模块下pom.xml中依赖

    引入必要依赖
    完善profiles标签中环境相关
    配置build标签中插件
<?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>chat-boot</artifactId>
<groupId>net.javadog.chat</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion> <artifactId>chat-boot-main</artifactId> <properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties> <dependencyManagement>
<dependencies>
<dependency>
<groupId>net.javadog.chat</groupId>
<artifactId>chat-boot-dependencies</artifactId>
<version>1.0-SNAPSHOT</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement> <dependencies>
<!-- web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--lombok-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<!--swagger2-->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
</dependency>
<!--swagger-ui-->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
</dependency>
<!-- swagger接口文档 -->
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-spring-boot-starter</artifactId>
</dependency>
</dependencies> <build>
<finalName>chat</finalName>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
<configuration>
<fork>true</fork>
</configuration>
</plugin>
</plugins>
<resources>
<resource>
<directory>src/main/webapp</directory>
<filtering>false</filtering>
</resource>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.xml</include>
</includes>
</resource>
</resources>
</build> <profiles>
<profile>
<id>local</id>
<properties>
<spring.active>local</spring.active>
</properties>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
</profile>
<profile>
<id>dev</id>
<properties>
<spring.active>dev</spring.active>
</properties>
</profile>
<profile>
<id>prod</id>
<properties>
<spring.active>prod</spring.active>
</properties>
</profile>
</profiles>
</project>

重点

配置引入依赖chat-boot-dependencies,用作此模块依赖引入

<dependencyManagement>
<dependencies>
<dependency>
<groupId>net.javadog.chat</groupId>
<artifactId>chat-boot-dependencies</artifactId>
<version>1.0-SNAPSHOT</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>

配置build标签用于完善插件plugins,其中包含maven-compiler-plugin和maven-resources-plugin

<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-resources-plugin</artifactId>
<version>2.6</version>
<configuration>
<delimiters>
<delimiter>@</delimiter>
</delimiters>
<useDefaultDelimiters>false</useDefaultDelimiters>
</configuration>
</plugin>
</plugins>
<resources>
<resource>
<directory>src/main/webapp</directory>
<filtering>false</filtering>
</resource>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.xml</include>
</includes>
</resource>
</resources>
</build>

配置profiles环境变量标签,用于方便打包切换,本狗设置了 local、dev、prod三种环境

 <profiles>
<profile>
<id>local</id>
<properties>
<spring.active>local</spring.active>
</properties>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
</profile>
<profile>
<id>dev</id>
<properties>
<spring.active>dev</spring.active>
</properties>
</profile>
<profile>
<id>prod</id>
<properties>
<spring.active>prod</spring.active>
</properties>
</profile>
</profiles>

操作可在IDEA右上角方便切换环境

切记一定主动Reload一下Maven依赖

切记一定主动Reload一下Maven依赖

切记一定主动Reload一下Maven依赖

在chat-boot-main模块中加入启动类,在src/main/java下右键New=>Java Class

录入启动类名ChatApplication

完善ChatApplication启动类代码

package net.javadog.chat;

import com.github.xiaoymin.knife4j.spring.annotations.EnableKnife4j;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletComponentScan;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.env.Environment;
import springfox.documentation.swagger2.annotations.EnableSwagger2; import java.net.InetAddress;
import java.net.UnknownHostException; /**
* @author: hdx
* @Date: 2023-01-28 11:24
* @version: 1.0
**/
@SpringBootApplication
@ServletComponentScan
@Slf4j
@EnableSwagger2
@EnableKnife4j
public class ChatApplication {
public static void main(String[] args) throws UnknownHostException {
// 启动类
ConfigurableApplicationContext application = SpringApplication.run(ChatApplication.class, args);
// 打印基础信息
info(application);
} static void info(ConfigurableApplicationContext application) throws UnknownHostException {
Environment env = application.getEnvironment();
String ip = InetAddress.getLocalHost().getHostAddress();
String port = env.getProperty("server.port");
String active = env.getProperty("spring.profiles.active");
String contextPath = env.getProperty("server.servlet.context-path");
if (contextPath == null) {
contextPath = "";
}
log.info("\n----------------------------------------------------------\n\t" +
"欢迎访问 \thttps://blog.javadog.net\n\t" +
"示例程序【" + active + "】环境已启动! 地址如下:\n\t" +
"Local: \t\thttp://localhost:" + port + contextPath + "\n\t" +
"External: \thttp://" + ip + ':' + port + contextPath + '\n' +
"Swagger文档: \thttp://" + ip + ":" + port + contextPath + "/doc.html\n" +
"----------------------------------------------------------");
}
}

配置application.yml文件

application.yml

#============================#
# server 配置
#============================#
server:
port: 82
max-http-header-size: 10240
servlet:
context-path: /chat/v1 #============================#
# spring 配置
#============================#
spring:
application:
# 应用名
name: chat
profiles:
active: @spring.active@
servlet:
multipart:
max-request-size: 100MB
max-file-size: 100MB
jackson:
time-zone: GMT+8
date-format: yyyy-MM-dd HH:mm:ss.SSS
locale: zh_CN
serialization:
# 格式化输出
indent_output: false
main:
allow-circular-references: true
#解决swagger版本路径不兼容问题
mvc:
pathmatch:
matching-strategy: ant_path_matcher #============================#
# mybatisplus 配置
#============================#
mybatis-plus:
mapper-locations: classpath:mapper/*.xml
configuration:
map-underscore-to-camel-case: true
cache-enabled: true
lazy-loading-enabled: true
multiple-result-sets-enabled: true
log-impl: org.apache.ibatis.logging.nologging.NoLoggingImpl
global-config:
banner: false
db-config:
id-type: assign_id
table-underline: true
enable-sql-runner: true
#数据库类型
db-type: MYSQL
configuration-properties:
prefix:
#如果数据库为postgresql,则需要配置为blobType: BINARY
blobType: BLOB
#如果数据库为oracle或mssql,则需要配置为boolValue: 1
boolValue: true #============================#
# logging 配置
#============================#
logging:
level:
root: info
file:
path: /root/javadog/chat/logs/${spring.application.name}/
name: ${spring.application.name}
logback:
rollingpolicy:
max-history: 7
max-file-size: 10MB #============================#
# file 配置
#============================#
file:
# 静态附件前缀
static-prefix: attach
# 上传的文件对外暴露的访问路径
access-path-pattern: /${file.static-prefix}/**
# 文件上传目录
upload-folder: /root/javadog/chat/
# 文件上传最大
max-post-size: 10

application-local.yml

#服务配置
server:
port: 8001
max-http-header-size: 10240 # Mysql数据库
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/chat-boot?autoReconnect=true&useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=CONVERT_TO_NULL&useSSL=false&serverTimezone=CTT&nullCatalogMeansCurrent=true
username: root
password: root
redis:
host: localhost
port: 6379
password:

application-dev.yml

#服务配置
server:
port: 7001
max-http-header-size: 10240 # mybatisplus 配置
mybatis-plus:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

application-prod.yml

#服务配置
server:
port: 8005

顺便加一下logback-spring.xml 日志文件

<?xml version="1.0" encoding="UTF-8" ?>
<configuration scan="true" scanPeriod="60 seconds" debug="false">
<conversionRule conversionWord="clr" converterClass="org.springframework.boot.logging.logback.ColorConverter"/>
<conversionRule conversionWord="wex"
converterClass="org.springframework.boot.logging.logback.WhitespaceThrowableProxyConverter"/>
<conversionRule conversionWord="wEx"
converterClass="org.springframework.boot.logging.logback.ExtendedWhitespaceThrowableProxyConverter"/>
<property name="CONSOLE_LOG_PATTERN"
value="${CONSOLE_LOG_PATTERN:-%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr(${PID:- }){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}"/>
<property name="FILE_LOG_PATTERN"
value="${FILE_LOG_PATTERN:-%d{yyyy-MM-dd HH:mm:ss.SSS} ${LOG_LEVEL_PATTERN:-%5p} ${PID:- } --- [%t] %-40.40logger{39} : %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}"/> <springProperty scope="context" name="application.name" source="spring.application.name" defaultValue="javadog"/>
<springProperty scope="context" name="logging.path" source="logging.file.path" defaultValue="logs"/>
<springProperty scope="context" name="logging.file.max-size" source="logging.logback.rollingpolicy.max-size"
defaultValue="10MB"/>
<springProperty scope="context" name="logging.file.max-history" source="logging.logback.rollingpolicy.max-history"
defaultValue="30"/>
<contextName>${application.name}</contextName> <springProfile name="dev,prod">
<!--输出到控制台-->
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>${CONSOLE_LOG_PATTERN}</pattern>
</encoder>
</appender>
<root level="info">
<appender-ref ref="console"/>
</root>
</springProfile> <springProfile name="dev,test,prod">
<!--输出到文件-->
<appender name="file-info" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${logging.path}/info/${application.name}-info.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${logging.path}/info/${application.name}-info.%d{yyyy-MM-dd}.%i.log</fileNamePattern> <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>${logging.file.max-size}</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
<!--只保留最近n天的日志-->
<maxHistory>${logging.file.max-history}</maxHistory>
</rollingPolicy>
<!-- 追加方式记录日志 -->
<append>true</append>
<encoder>
<pattern>${FILE_LOG_PATTERN}</pattern>
</encoder>
</appender>
<appender name="file-warn" class="ch.qos.logback.core.rolling.RollingFileAppender">
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>warn</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
<file>${logging.path}/warn/${application.name}-warn.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${logging.path}$/warn/${application.name}-warn.%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>${logging.file.max-size}</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
<!--只保留最近n天的日志-->
<maxHistory>${logging.file.max-history}</maxHistory>
</rollingPolicy>
<encoder>
<pattern>${FILE_LOG_PATTERN}</pattern>
</encoder>
</appender>
<appender name="file-error" class="ch.qos.logback.core.rolling.RollingFileAppender">
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>error</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
<file>${logging.path}/error/${application.name}-error.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${logging.path}/error/${application.name}-error.%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>${logging.file.max-size}</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
<!--只保留最近n天的日志-->
<maxHistory>${logging.file.max-history}</maxHistory>
</rollingPolicy>
<encoder>
<pattern>${FILE_LOG_PATTERN}</pattern>
</encoder>
</appender> <root level="INFO">
<appender-ref ref="file-info"/>
<appender-ref ref="file-warn"/>
<appender-ref ref="file-error"/>
</root>
</springProfile> </configuration>

启动一下项目试试,启动如下证明成功。如果报错少依赖请再拉一下Maven依赖!!!


4.创建子模块-module(模块层)

右击项目chat-boot,new ->Moudle新建模块chat-boot-module

填写子模块名 chat-boot-module,然后检查对应GAV,点击Finish

生成子模块chat-boot-module如下图

删除chat-boot-module下无用文件及目录,如src目录,删除无用目录如下

自此外部大框架初步搭建成功

完善chat-boot-module下pom.xml依赖,如lombok,web等必要依赖

<?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>chat-boot</artifactId>
<groupId>net.javadog.chat</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion> <artifactId>chat-boot-module</artifactId>
<packaging>pom</packaging>
<modules>
<module>chat-boot-common</module>
<module>chat-boot-controller</module>
<module>chat-boot-dao</module>
<module>chat-boot-dto</module>
<module>chat-boot-entity</module>
<module>chat-boot-service</module>
</modules> <properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties> <dependencyManagement>
<dependencies>
<dependency>
<groupId>net.javadog.chat</groupId>
<artifactId>chat-boot-dependencies</artifactId>
<version>${project.parent.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement> <dependencies>
<!-- web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--WxJava - 微信开发 Java SDK-->
<dependency>
<groupId>com.github.binarywang</groupId>
<artifactId>weixin-java-miniapp</artifactId>
</dependency>
<!--lombok-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<!--hutool-->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
</dependency>
<!--swagger2-->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
</dependency>
<!--swagger-ui-->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
</dependency>
<!--整合Knife4j-->
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-spring-boot-starter</artifactId>
</dependency>
<!--整合Shiro安全框架-->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
</dependency>
<!--jwt-->
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
</dependency>
<!--mybatis-plus-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
</dependencies> </project>

一定要重新拉取依赖!

一定要重新拉取依赖!

一定要重新拉取依赖!


5.创建chat-boot-module模块下对应功能分层

目前本狗分为如下6层

common-共通层
controller-控制器层
dao-数据持久层
dto-数据传输对象层
entity-实体层
service-业务逻辑层

依次按照上述添加模块方式进行新增子模块,本狗如下示例一个,其余都如法炮制

右击项目chat-boot-module,new ->Moudle新建模块chat-boot-common

一定看清楚父模块是否正确

一定看清楚父模块是否正确

一定看清楚父模块是否正确

确认父级模块后,点击Finish,生成chat-boot-common模块

依次按照上述方法,新建其他模块

chat-boot-controller模块

chat-boot-dao模块

chat-boot-dto模块

chat-boot-entity模块

chat-boot-service模块

总体模块雏形基本完成

6.实际流程填充

模拟正常前端请求后台服务调用过程,进行实际代码补充

在chat-boot-entity下新建实体类User,在src/main/java下右键New=>Java Class,录入包名及类名

package net.javadog.chat.entity;

import lombok.Data;

/**
* @author: hdx
* @Date: 2023-01-28 14:26
* @version: 1.0
**/
@Data
public class User { private Long id; private String username; private String idCard;
}

在chat-boot-dto下新建目request和response,分别代表请求传输对象和返回传输对象,并分别在目录下创建UserRequest.java和UserResponse.java

package net.javadog.chat.request;

import lombok.Data;

/**
* @author: hdx
* @Date: 2023-01-28 14:59
* @version: 1.0
**/
@Data
public class UserRequest { private Long id; private String username;
}
package net.javadog.chat.response;

import lombok.Data;

/**
* @author: hdx
* @Date: 2023-01-28 14:59
* @version: 1.0
**/
@Data
public class UserResponse { private Long id; private String username;
}

在chat-boot-dao下修改chat-boot-dao模块下修改pom.xml文件依赖,引入chat-boot-entity;并增对应UserMapper.java

package net.javadog.chat.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import net.javadog.chat.entity.User; /**
* 用户mapper
*
* @author: hdx
* @Date: 2023-01-10 11:43
* @version: 1.0
**/
public interface UserMapper extends BaseMapper<User> {
}
<?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>chat-boot-module</artifactId>
<groupId>net.javadog.chat</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion> <artifactId>chat-boot-dao</artifactId> <properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties> <dependencies>
<dependency>
<groupId>net.javadog.chat</groupId>
<artifactId>chat-boot-entity</artifactId>
<version>${project.parent.version}</version>
</dependency>
</dependencies> </project>

在chat-boot-service下新建目录service和impl,并在对应目录下新建UserService.java和UserServiceImpl.java,并修改chat-boot-service模块下修改pom.xml文件依赖,引入chat-boot-dto,chat-boot-dao

package net.javadog.chat.service;

import com.baomidou.mybatisplus.extension.service.IService;
import net.javadog.chat.entity.User; /**
* 用户接口
*
* @author: hdx
* @Date: 2023-01-10 11:53
* @version: 1.0
**/
public interface UserService extends IService<User> { }
package net.javadog.chat.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import net.javadog.chat.entity.User;
import net.javadog.chat.mapper.UserMapper;
import net.javadog.chat.service.UserService;
import org.springframework.stereotype.Service; /**
* 用户接口实现类
*
* @author: hdx
* @Date: 2023-01-10 11:55
* @version: 1.0
**/
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService { }
<?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>chat-boot-module</artifactId>
<groupId>net.javadog.chat</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion> <artifactId>chat-boot-service</artifactId> <properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties> <dependencies>
<dependency>
<groupId>net.javadog.chat</groupId>
<artifactId>chat-boot-dao</artifactId>
<version>${project.parent.version}</version>
</dependency>
<dependency>
<groupId>net.javadog.chat</groupId>
<artifactId>chat-boot-dto</artifactId>
<version>${project.parent.version}</version>
</dependency>
</dependencies> </project>

在chat-boot-controller创建UserController.java,并修改chat-boot-controller模块下修改pom.xml文件依赖,引入chat-boot-dto,chat-boot-service

package net.javadog.chat.controller;

import cn.hutool.core.bean.BeanUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import net.javadog.chat.entity.User;
import net.javadog.chat.request.UserRequest;
import net.javadog.chat.response.UserResponse;
import net.javadog.chat.service.UserService;
import org.springframework.web.bind.annotation.*; import javax.annotation.Resource; /**
* 用户控制器
*
* @author: hdx
* @Date: 2022-12-07 15:48
* @version: 1.0
**/
@Api(tags = "用户控制器")
@RestController
@RequestMapping("/user")
public class UserController { @Resource
private UserService userService; @ApiOperation(value = "用户详情", notes = "用户详情")
@GetMapping
public UserResponse detail(UserRequest userRequest){
UserResponse userResponse = new UserResponse();
User user = userService.getById(userRequest.getId());
BeanUtil.copyProperties(user, userResponse);
return userResponse;
} }

重要补充

1.切记修改chat-boot-main下的pom.xml依赖,将chat-boot-controller模块加入

2.切记修改chat-boot-main下的pom.xml依赖,将chat-boot-dao模块加入

3.切记修改启动类ChatApplication中加入@MapperScan注解

<?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>chat-boot</artifactId>
<groupId>net.javadog.chat</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion> <artifactId>chat-boot-main</artifactId> <properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties> <dependencyManagement>
<dependencies>
<dependency>
<groupId>net.javadog.chat</groupId>
<artifactId>chat-boot-dependencies</artifactId>
<version>1.0-SNAPSHOT</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement> <dependencies>
<!-- web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--lombok-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<!--swagger2-->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
</dependency>
<!--swagger-ui-->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
</dependency>
<!-- swagger接口文档 -->
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-spring-boot-starter</artifactId>
</dependency> <!-- controller -->
<dependency>
<groupId>net.javadog.chat</groupId>
<artifactId>chat-boot-controller</artifactId>
<version>${project.parent.version}</version>
</dependency>
<!-- dao -->
<dependency>
<groupId>net.javadog.chat</groupId>
<artifactId>chat-boot-dao</artifactId>
<version>${project.parent.version}</version>
</dependency>
</dependencies> <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-resources-plugin</artifactId>
<version>2.6</version>
<configuration>
<delimiters>
<delimiter>@</delimiter>
</delimiters>
<useDefaultDelimiters>false</useDefaultDelimiters>
</configuration>
</plugin>
</plugins>
<resources>
<resource>
<directory>src/main/webapp</directory>
<filtering>false</filtering>
</resource>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.xml</include>
</includes>
</resource>
</resources>
</build> <profiles>
<profile>
<id>local</id>
<properties>
<spring.active>local</spring.active>
</properties>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
</profile>
<profile>
<id>dev</id>
<properties>
<spring.active>dev</spring.active>
</properties>
</profile>
<profile>
<id>prod</id>
<properties>
<spring.active>prod</spring.active>
</properties>
</profile>
</profiles>
</project>

package net.javadog.chat;

import com.github.xiaoymin.knife4j.spring.annotations.EnableKnife4j;
import lombok.extern.slf4j.Slf4j;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletComponentScan;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.env.Environment;
import springfox.documentation.swagger2.annotations.EnableSwagger2; import java.net.InetAddress;
import java.net.UnknownHostException; /**
* @author: hdx
* @Date: 2023-01-28 11:24
* @version: 1.0
**/
@SpringBootApplication
@ServletComponentScan
@Slf4j
@EnableSwagger2
@EnableKnife4j
@MapperScan(basePackages = {"net.javadog.chat.mapper"})
public class ChatApplication {
public static void main(String[] args) throws UnknownHostException {
// 启动类
ConfigurableApplicationContext application = SpringApplication.run(ChatApplication.class, args);
// 打印基础信息
info(application);
} static void info(ConfigurableApplicationContext application) throws UnknownHostException {
Environment env = application.getEnvironment();
String ip = InetAddress.getLocalHost().getHostAddress();
String port = env.getProperty("server.port");
String active = env.getProperty("spring.profiles.active");
String contextPath = env.getProperty("server.servlet.context-path");
if (contextPath == null) {
contextPath = "";
}
log.info("\n----------------------------------------------------------\n\t" +
"欢迎访问 \thttps://blog.javadog.net\n\t" +
"示例程序【" + active + "】环境已启动! 地址如下:\n\t" +
"Local: \t\thttp://localhost:" + port + contextPath + "\n\t" +
"External: \thttp://" + ip + ':' + port + contextPath + '\n' +
"Swagger文档: \thttp://" + ip + ":" + port + contextPath + "/doc.html\n" +
"----------------------------------------------------------");
}
}

7.示例DB更新

模拟正常前端请求后台服务调用过程,进行实际代码补充

DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
`id` bigint(20) NOT NULL COMMENT 'id',
`username` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '用户名',
`id_card` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '身份证',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic; -- ----------------------------
-- Records of user
-- ----------------------------
INSERT INTO `user` VALUES (1, 'JavaDog', '123123');

8.访问测试

浏览器访问http://localhost:8001/chat/v1/user?id=1

测试成功如下图所示

总结

以上示例只是简单示范分层思路,其中代码逻辑实现方式有很多种,大家选取适用自己就好,希望自己的思路能对大家有帮助

如遇缺少依赖情况,一定要重新拉取依赖!

写在最后

此生两悔,悔遇见你,更悔未早遇见你,珍惜当下拥有,勿念昔日美好。

JavaDog 狗屋地址
个人博客 https://blog.javadog.net
公众号 https://mp.weixin.qq.com/s/_vgnXoQ8FSobD3OfRAf5gw
CSDN https://blog.csdn.net/baidu_25986059
掘金 https://juejin.cn/user/2172290706716775
知乎 https://www.zhihu.com/people/JavaDog
简书 https://www.jianshu.com/u/1ff9c6bdb916
gitee https://gitee.com/javadog-net
GitHub https://github.com/javadog-net

【SpringBoot】还不会SpringBoot项目模块分层?来这手把手教你的相关教程结束。

《【SpringBoot】还不会SpringBoot项目模块分层?来这手把手教你.doc》

下载本文的Word格式文档,以方便收藏与打印。