21. 从零开始学springboot-搭建一个可以上线的项目结构-多模块篇(1)

前言

通过前面的多章学习,相信大家对于springboot整合各个基础依赖已经得心应手了。并且,对于各个依赖的选择和使用都有了一定的理解。本章,将对前段时间的所学做一个总结,会完成一个可以上生产的项目基础架构。
首先,我们来归纳一下一般项目的需求:

  • 多数据源
  • 分布式事务
  • 数据持久层
  • 缓存
  • 日志记录
  • druid数据源监控
  • api文档

以上需求基本囊括了所有项目的基础。那么我们,根据需求,对应我们的前几章所学,不难得出springboot+mybatis+多数据源+druid+atomikos+redis+log+swagger2 的搭配,另外,项目多环境的情况,还必须提供切换环境的配置。为了解决mybatis写entity个mapper.xml文件麻烦的问题,我们需要引入自动生成插件mybatis-generator。

再者,这边我们考虑到项目的解耦,还会在将整个项目拆分成多个独立的模块,这在实际开发过程中也是很重要的一部分。

项目结构定义

21. 从零开始学springboot-搭建一个可以上线的项目结构-多模块篇(1)_第1张图片
3.png

如图,我们把一个项目拆成了共4个模块

mr-entity 存放实体类(mapper类,mapper.xml文件)
mr-service 存放业务逻辑类
mr-utils 存放工具类,如redis等等工具
web-service 真正的web服务应用,依赖于以上三个模块。

关于项目拆分成多个模块的好处如下:

  1. 模块与模块松耦合,通过依赖来调用
  2. 重复的代码可以单独抽成一个模块共用
  3. 打包时可以分模块打包,做个java开发的都知道,项目会越来越大,后续整个项目打包编译时间会很长,所以多模块很有必要
  4. 不同的模块可以分配给不同的人开发维护,彼此不会冲突

创建父项目

21. 从零开始学springboot-搭建一个可以上线的项目结构-多模块篇(1)_第2张图片
1.png
21. 从零开始学springboot-搭建一个可以上线的项目结构-多模块篇(1)_第3张图片
2.png

注意,使用IDEA创建父项目时选择的是


21. 从零开始学springboot-搭建一个可以上线的项目结构-多模块篇(1)_第4张图片
4.png

创建父项目完成后,我们将项目下的src目录删掉,只保留pom.xml文件即可。

创建子项目

右键父项目


6.png

21. 从零开始学springboot-搭建一个可以上线的项目结构-多模块篇(1)_第5张图片
7.png

同样的操作依次创建
mr-entity
mr-service
mr-utils
web-service
这几个子模块,同时注意,除了web-service这个模块,将其它子模块的无关文件意义删除,精简项目结构。
删除后结构如下
mr-entity
删除

.mvn
src/test
.gitignore
HELP.md
mvnw
mvnw.cmd
删除java文件夹下的xxxxxxApplication入口文件(因为entity模块只是个公共类模块,无需运行)
21. 从零开始学springboot-搭建一个可以上线的项目结构-多模块篇(1)_第6张图片
8.png

mr-service
删除

.mvn
src/test
.gitignore
HELP.md
mvnw
mvnw.cmd
删除java文件夹下的xxxxxxApplication入口文件
21. 从零开始学springboot-搭建一个可以上线的项目结构-多模块篇(1)_第7张图片
9.png

mr-utils
删除

.mvn
src/test
.gitignore
HELP.md
mvnw
mvnw.cmd
删除java文件夹下的xxxxxxApplication入口文件
21. 从零开始学springboot-搭建一个可以上线的项目结构-多模块篇(1)_第8张图片
10.png

最后,强调下,web-service作为一个服务,不用做任何处理,不需要删除文件!

至此,精简后的多模块项目已经创建完毕,下面我们来通过pom文件来建立父子关系。

多模块父子关系建立

我们在父pom.xml添加:

    
        org.springframework.boot
        spring-boot-starter-parent
        2.1.4.RELEASE
    
    
    pom
    
        mr-entity
        mr-service
        mr-utils
        web-service
    

然后我们在各个子模块的pom.xml文件依次添加父依赖


    
        com.mrcoder
        mrcoder-service
        1.0.0
        ../pom.xml
    

同时,除了web-service这个子模块,删除其它子模块的 标签。

添加依赖和子模块之间的依赖关系

好了,通过以上的操作,父子模块关系很清晰了,但是子模块与子模块之间的依赖关系还没有建立(意思就是,mr-entity作为实体类模块,肯定会被mr-service模块使用,那么如何在mr-service模块内使用mr-entity的实体类呢?)
接下来 ,我们来修改pom.xml文件建立这种依赖关系

mr-entity模块不依赖任务子模块,所以无需任务改动,关于注释的build信息,大家先不用管。
mr-entity/pom.xml



    4.0.0
    com.mrcoder
    mr-entity
    0.0.1
    mr-entity
    mr-entity

    
        com.mrcoder
        mrcoder-service
        1.0.0
        ../pom.xml
    

    
        
            
                
                
            
            
            
                
                
                
                
                    
                    
                    
                    
                    
                
            
        
    

mr-service模块依赖mr-utils和mr-entity
mr-service/pom.xml



    4.0.0
    com.mrcoder
    mr-service
    0.0.1
    mr-service
    mr-service

    
        com.mrcoder
        mrcoder-service
        1.0.0
        ../pom.xml
    

    
        
            com.mrcoder
            mr-entity
            0.0.1
        
        
            com.mrcoder
            mr-utils
            0.0.1
        
    

mr-utils不依赖任何子模块
mr-utils/pom.xml



    4.0.0
    com.mrcoder
    mr-utils
    0.0.1
    mr-utils
    mr-utils

    
        com.mrcoder
        mrcoder-service
        1.0.0
        ../pom.xml
    

最后我们看真正的对外服务模块web-service(大家实际开发时最好在模块的命名上和其它子模块区分开,比如作者就喜欢加个-service后缀来代表它是真正的对外服务模块)
web-service依赖其它的所有子模块,其它子模块其实就是web-service拆分出去的~
web-service/pom.xml



    4.0.0
    com.mrcoder
    web-service
    0.0.1
    web-service
    web-service

    
        com.mrcoder
        mrcoder-service
        1.0.0
        ../pom.xml
    

    
        
            com.mrcoder
            mr-entity
            0.0.1
        
        
            com.mrcoder
            mr-utils
            0.0.1
        
        
            com.mrcoder
            mr-service
            0.0.1
        
    

    
    
        
            
                org.springframework.boot
                spring-boot-maven-plugin
                
                    
                    com.mrcoder.webservice.WebServiceApplication
                    ZIP
                
                
                    
                        
                            repackage
                        
                    
                
            
        
    

关于build块,大家先不用管,这是关于打包代码,后续作者会讲。

至此模块间的依赖关系已建立完成

添加依赖

我们将使用到的所有依赖加入到pom.xml




    4.0.0
    com.mrcoder
    mrcoder-service
    1.0.0

    
        org.springframework.boot
        spring-boot-starter-parent
        2.1.4.RELEASE
    

    
    pom
    
        mr-entity
        mr-service
        mr-utils
        web-service
    


    
        1.8
        2.1.4.RELEASE
        2.0.0
        1.1.16
        8.0.11
        1.4.7.RELEASE
        1.2.57
        1.3.2
        2.6.1
    


    
        
            org.springframework.boot
            spring-boot-starter
            ${sb.version}
        

        
            org.springframework.boot
            spring-boot-starter-test
            ${sb.version}
            test
        

        
        
            org.springframework.boot
            spring-boot-starter-web
            ${sb.version}
        
        
            org.mybatis.spring.boot
            mybatis-spring-boot-starter
            ${mybatis.version}
        
        
            com.alibaba
            druid-spring-boot-starter
            ${druid.version}
        
        
        
            org.springframework.boot
            spring-boot-starter-jta-atomikos
            ${sb.version}
        
        
        
            mysql
            mysql-connector-java
            ${mysql.version}
        
        
        
            org.springframework.boot
            spring-boot-starter-aop
            ${sb.version}
        
        
        
            org.springframework.boot
            spring-boot-starter-data-redis
            ${redis.version}
        
        
        
            com.alibaba
            fastjson
            ${fastjson.version}
        
        
        
            io.springfox
            springfox-swagger2
            ${swagger.version}
        
        
            io.springfox
            springfox-swagger-ui
            ${swagger.version}
        
        
    
    
        
            
                org.apache.maven.plugins
                maven-compiler-plugin
                3.8.0
                
                    ${java.version}
                    ${java.version}
                
            
            
                org.apache.maven.plugins
                maven-surefire-plugin
                
                    
                    true
                
            
        
    

关于依赖有和作用已在代码中注释,另外,仔细的同学肯定发现了,作者将版本号单独使用了标签包住了,这也是常用的方式,目的是为了方便的管理依赖版本,统一管理。

接下来,我们来完善各个子模块的代码。

mr-entity

结构如下


21. 从零开始学springboot-搭建一个可以上线的项目结构-多模块篇(1)_第9张图片
12.png

手动建立各个package和类文件

entity/master/Student

package com.mrcoder.mrentity.entity.master;
import java.io.Serializable;
public class Student implements Serializable {
    private Long id;
    private String name;
    private int age;
    private int grade;
    public Student() {
    }
    public Student(String name, int age, int grade) {
        this.name = name;
        this.age = age;
        this.grade = grade;
    }
    @Override
    public String toString() {
        return "Student{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", age=" + age +
                ", grade=" + grade +
                '}';
    }
    public Long getId() {
        return id;
    }
    public void setId(Long id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public int getGrade() {
        return grade;
    }
    public void setGrade(int grade) {
        this.grade = grade;
    }
}

entity/slave/Teacher

package com.mrcoder.mrentity.entity.slave;
import java.io.Serializable;
public class Teacher implements Serializable {
    private Long id;
    private String name;
    private int age;
    private int course;
    public Teacher() {
    }
    public Teacher(String name, int age, int course) {
        this.name = name;
        this.age = age;
        this.course = course;
    }
    @Override
    public String toString() {
        return "Teacher{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", age='" + age + '\'' +
                ", course='" + course + '\'' +
                '}';
    }
    public Long getId() {
        return id;
    }
    public void setId(Long id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public int getCourse() {
        return course;
    }
    public void setCourse(int course) {
        this.course = course;
    }
}

mapper/master/StudentMapper

package com.mrcoder.mrentity.mapper.master;
import com.mrcoder.mrentity.entity.master.Student;
import org.apache.ibatis.annotations.Select;
import java.util.List;
public interface StudentMapper {
    //    @Select("SELECT * FROM student")
    List getList();

    //    @Select("SELECT * FROM student WHERE id = #{id}")
    Student getById(Long id);

    //    @Insert("INSERT INTO student(age,grade,name) VALUES(#{age}, #{grade}, #{name})")
    Integer insert(Student student);

    //    @Update("UPDATE student SET name=#{name},age=#{age}, grade=#{grade} WHERE id =#{id}")
    Integer update(Student student);

    //    @Delete("DELETE FROM student WHERE id =#{id}")
    Integer delete(Long id);

    //注解方式,本项目不建议使用
    @Select("SELECT * FROM student")
    List getListByAnno();
}

mapper/slave/TeacherMapper

package com.mrcoder.mrentity.mapper.slave;
import com.mrcoder.mrentity.entity.slave.Teacher;
import java.util.List;
public interface TeacherMapper {
    //    @Select("SELECT * FROM teacher")
    List getList();

    //    @Select("SELECT * FROM teacher WHERE id = #{id}")
    Teacher getById(Long id);

    //    @Insert("INSERT INTO teacher(age,course,name) VALUES(#{age}, #{course}, #{name})")
    void insert(Teacher teacher);

    //    @Update("UPDATE teacher SET name=#{name},age=#{age}, course=#{course} WHERE id =#{id}")
    void update(Teacher teacher);

    //    @Delete("DELETE FROM teacher WHERE id =#{id}")
    void delete(Long id);
}

resources/mapper/master/StudentMapper.xml




    
        
        
        
        
    

    
        id, name, age, grade
    

    

    

    
       INSERT INTO
            student
            (age,grade,name)
        VALUES
            (#{age}, #{grade}, #{name})
    

    
        UPDATE
        student
        SET
        age = #{age},
        grade = #{grade},
        name = #{name}
        WHERE
        id = #{id}
    

    
       DELETE FROM
             student
       WHERE
             id =#{id}
    


resources/mapper/master/TeacherMapper.xml




    
        
        
        
        
    

    
        id, name, age, course
    

    

    

    
       INSERT INTO
            teacher
            (age,course,name)
        VALUES
            (#{age}, #{course}, #{name})
    

    
        UPDATE
        teacher
        SET
        age = #{age},
        course = #{course},
        name = #{name}
        WHERE
        id = #{id}
    

    
       DELETE FROM
             teacher
       WHERE
             id =#{id}
    


关于resources/generator/文件夹下的内容,“熟读”我前几章的同学肯定知道,这俩个xml文件是mybatis用来自动生成entity和mapper文件的,这里不多赘述,不懂的同学可以百度“mybatis自动生成代码”查询。

这边顺带解释下mr-entity/pom.xml中的


21. 从零开始学springboot-搭建一个可以上线的项目结构-多模块篇(1)_第10张图片
13.png

注释的代码是用mybatis用来自动生成代码的,细心的同学发现了,


14.png

这边有两个配置文件,一个是master,一个是slave,我们可以在mr-entity的结构中发现,所有的类文件都是通过master和slave包来区分两个数据源的,也就是master数据源的实体类就放到master包内~,生成代码的逻辑也是一样,所以这边会有两个配置文件,大家使用时,用到master自动生成时请注释slave的配置,用到slave就注释master。(这一块作者暂时没有找到能同时生成master和slave多个数据源代码而且不需要改配置的方式,后续有时间会去研究下)

最后,强调一下,关于master和slave命名的问题,不是我们理解的主从数据库关系,仅仅是作者习惯命名,和主从没有任何关系,各位看官可以自由命名!

关于resources/generator/masterGenerator.xml和resources/generator/slaveGenerator.xml,有两个地方需要大家根据实际情况修改后才能使用


21. 从零开始学springboot-搭建一个可以上线的项目结构-多模块篇(1)_第11张图片
29.png

master数据源生成代码的配置文件
resources/generator/masterGenerator.xml





    
    

    

        
        
            
            
        

        
        

        
        
            
        

        
        
            
            
            
            
            
            
            
            
            
            
        

        
        
            
        

        
        
            
            
            
            
            
            
            
        

        
        

slave数据源生成代码的配置文件
resources/generator/slaveGenerator.xml





    
    

    

        
        
            
            
        

        
        

        
        
            
        

        
        
            
            
            
            
            
            
            
            
            
            
        

        
        
            
        

        
        
            
            
            
            
            
            
            
        

        
        

项目地址

https://github.com/MrCoderStack/SpringBootFrame

请关注我的订阅号

订阅号.png

你可能感兴趣的:(21. 从零开始学springboot-搭建一个可以上线的项目结构-多模块篇(1))