前言
通过前面的多章学习,相信大家对于springboot整合各个基础依赖已经得心应手了。并且,对于各个依赖的选择和使用都有了一定的理解。本章,将对前段时间的所学做一个总结,会完成一个可以上生产的项目基础架构。
首先,我们来归纳一下一般项目的需求:
- 多数据源
- 分布式事务
- 数据持久层
- 缓存
- 日志记录
- druid数据源监控
- api文档
以上需求基本囊括了所有项目的基础。那么我们,根据需求,对应我们的前几章所学,不难得出springboot+mybatis+多数据源+druid+atomikos+redis+log+swagger2 的搭配,另外,项目多环境的情况,还必须提供切换环境的配置。为了解决mybatis写entity个mapper.xml文件麻烦的问题,我们需要引入自动生成插件mybatis-generator。
再者,这边我们考虑到项目的解耦,还会在将整个项目拆分成多个独立的模块,这在实际开发过程中也是很重要的一部分。
项目结构定义
如图,我们把一个项目拆成了共4个模块
mr-entity 存放实体类(mapper类,mapper.xml文件)
mr-service 存放业务逻辑类
mr-utils 存放工具类,如redis等等工具
web-service 真正的web服务应用,依赖于以上三个模块。
关于项目拆分成多个模块的好处如下:
- 模块与模块松耦合,通过依赖来调用
- 重复的代码可以单独抽成一个模块共用
- 打包时可以分模块打包,做个java开发的都知道,项目会越来越大,后续整个项目打包编译时间会很长,所以多模块很有必要
- 不同的模块可以分配给不同的人开发维护,彼此不会冲突
创建父项目
注意,使用IDEA创建父项目时选择的是
创建父项目完成后,我们将项目下的src目录删掉,只保留pom.xml文件即可。
创建子项目
右键父项目
同样的操作依次创建
mr-entity
mr-service
mr-utils
web-service
这几个子模块,同时注意,除了web-service这个模块,将其它子模块的无关文件意义删除,精简项目结构。
删除后结构如下
mr-entity
删除
.mvn
src/test
.gitignore
HELP.md
mvnw
mvnw.cmd
删除java文件夹下的xxxxxxApplication入口文件(因为entity模块只是个公共类模块,无需运行)
mr-service
删除
.mvn
src/test
.gitignore
HELP.md
mvnw
mvnw.cmd
删除java文件夹下的xxxxxxApplication入口文件
mr-utils
删除
.mvn
src/test
.gitignore
HELP.md
mvnw
mvnw.cmd
删除java文件夹下的xxxxxxApplication入口文件
最后,强调下,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}
org.apache.maven.plugins
maven-surefire-plugin
true
关于依赖有和作用已在代码中注释,另外,仔细的同学肯定发现了,作者将版本号单独使用了
接下来,我们来完善各个子模块的代码。
mr-entity
结构如下
手动建立各个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中的
注释的代码是用mybatis用来自动生成代码的,细心的同学发现了,
这边有两个配置文件,一个是master,一个是slave,我们可以在mr-entity的结构中发现,所有的类文件都是通过master和slave包来区分两个数据源的,也就是master数据源的实体类就放到master包内~,生成代码的逻辑也是一样,所以这边会有两个配置文件,大家使用时,用到master自动生成时请注释slave的配置,用到slave就注释master。(这一块作者暂时没有找到能同时生成master和slave多个数据源代码而且不需要改配置的方式,后续有时间会去研究下)
最后,强调一下,关于master和slave命名的问题,不是我们理解的主从数据库关系,仅仅是作者习惯命名,和主从没有任何关系,各位看官可以自由命名!
关于resources/generator/masterGenerator.xml和resources/generator/slaveGenerator.xml,有两个地方需要大家根据实际情况修改后才能使用
master数据源生成代码的配置文件
resources/generator/masterGenerator.xml
slave数据源生成代码的配置文件
resources/generator/slaveGenerator.xml
项目地址
https://github.com/MrCoderStack/SpringBootFrame