领域驱动设计(Domain Driven Design)有一个官方的sample工程,名为DDDSample。
    架构图
    DDD领域驱动设计(Domain Driven Design) - 图1
    image.png
    接下来,我们用一个学生例子来看整体的架构
    业务分析:
    假设,有多个学生,学生有成绩和基本信息组成,我们就做一个最基本的案例,查看和新增。
    首先,构建最基本的设施层:
    image.png
    common:共通类存放地址
    dao:数据库实现接口
    po:映射数据库对象层
    repository:服务层

    1. package com.hikktn.infrastructure.common;
    2. /**
    3. * <p>
    4. * 返回消息体
    5. * common:共同使用类
    6. * </p>
    7. *
    8. * @author lisonglin
    9. * @version 1.0
    10. * @since 2022/1/24 16:23
    11. */
    12. public class ResponseBase {
    13. /**
    14. * 状态码
    15. */
    16. private int code;
    17. /**
    18. * 消息
    19. */
    20. private Object obj;
    21. public ResponseBase(int code, Object obj) {
    22. this.code = code;
    23. this.obj = obj;
    24. }
    25. public int getCode() {
    26. return code;
    27. }
    28. public void setCode(int code) {
    29. this.code = code;
    30. }
    31. public Object getObj() {
    32. return obj;
    33. }
    34. public void setObj(Object obj) {
    35. this.obj = obj;
    36. }
    37. }
    1. package com.hikktn.infrastructure.po;
    2. /**
    3. * <p>
    4. * 学生实体类
    5. * PO:数据库表结构到JAVA的映射类
    6. * </p>
    7. *
    8. * @author lisonglin
    9. * @version 1.0
    10. * @since 2022/1/24 16:48
    11. */
    12. public class StudentPo {
    13. /**
    14. * 主键
    15. */
    16. private int id;
    17. /**
    18. * 学生姓名
    19. */
    20. private String name;
    21. /**
    22. * 学生性别
    23. */
    24. private String sex;
    25. /**
    26. * 学生年龄
    27. */
    28. private int age;
    29. /**
    30. * 学生身高
    31. */
    32. private double stature;
    33. /**
    34. * 学生平均成绩
    35. */
    36. private double pjcj;
    37. /**
    38. * 学生语文成绩
    39. */
    40. private double ywcj;
    41. /**
    42. * 学生数学成绩
    43. */
    44. private double sxcj;
    45. /**
    46. * 学生英语成绩
    47. */
    48. private double yycj;
    49. /**
    50. * 兴趣爱好
    51. */
    52. private String xqah;
    53. /**
    54. * 母亲姓名
    55. */
    56. private String mqxm;
    57. /**
    58. * 父亲姓名
    59. */
    60. private String fqxm;
    61. public int getId() {
    62. return id;
    63. }
    64. public void setId(int id) {
    65. this.id = id;
    66. }
    67. public String getName() {
    68. return name;
    69. }
    70. public void setName(String name) {
    71. this.name = name;
    72. }
    73. public String getSex() {
    74. return sex;
    75. }
    76. public void setSex(String sex) {
    77. this.sex = sex;
    78. }
    79. public int getAge() {
    80. return age;
    81. }
    82. public void setAge(int age) {
    83. this.age = age;
    84. }
    85. public double getStature() {
    86. return stature;
    87. }
    88. public void setStature(double stature) {
    89. this.stature = stature;
    90. }
    91. public double getPjcj() {
    92. return pjcj;
    93. }
    94. public void setPjcj(double pjcj) {
    95. this.pjcj = pjcj;
    96. }
    97. public double getYwcj() {
    98. return ywcj;
    99. }
    100. public void setYwcj(double ywcj) {
    101. this.ywcj = ywcj;
    102. }
    103. public double getSxcj() {
    104. return sxcj;
    105. }
    106. public void setSxcj(double sxcj) {
    107. this.sxcj = sxcj;
    108. }
    109. public double getYycj() {
    110. return yycj;
    111. }
    112. public void setYycj(double yycj) {
    113. this.yycj = yycj;
    114. }
    115. public String getXqah() {
    116. return xqah;
    117. }
    118. public void setXqah(String xqah) {
    119. this.xqah = xqah;
    120. }
    121. public String getMqxm() {
    122. return mqxm;
    123. }
    124. public void setMqxm(String mqxm) {
    125. this.mqxm = mqxm;
    126. }
    127. public String getFqxm() {
    128. return fqxm;
    129. }
    130. public void setFqxm(String fqxm) {
    131. this.fqxm = fqxm;
    132. }
    133. }
    1. package com.hikktn.infrastructure.dao;
    2. import com.hikktn.infrastructure.po.StudentPo;
    3. import org.apache.ibatis.annotations.Insert;
    4. import org.apache.ibatis.annotations.Mapper;
    5. import org.apache.ibatis.annotations.Select;
    6. /**
    7. * <p>
    8. * 学生数据访问对象
    9. * </p>
    10. *
    11. * @author lisonglin
    12. * @version 1.0
    13. * @since 2022/1/24 17:32
    14. */
    15. @Mapper
    16. public interface StudentDao {
    17. /**
    18. * 新增学生的信息
    19. * @param studentPo 学生的基本信息
    20. */
    21. @Insert("insert ")
    22. void save(StudentPo studentPo);
    23. /**
    24. * 根据id查询学生基本信息
    25. * @param id 标识符
    26. * @return 学生的基本信息
    27. */
    28. @Select("select ")
    29. StudentPo queryById(int id);
    30. }
    1. package com.hikktn.infrastructure.repository;
    2. import com.hikktn.infrastructure.dao.StudentDao;
    3. import com.hikktn.infrastructure.po.StudentPo;
    4. import com.hikktn.domain.repository.IStudentRepository;
    5. import org.springframework.beans.factory.annotation.Autowired;
    6. /**
    7. * <p>
    8. * 学生服务层实现类(基础CRUD)
    9. * </p>
    10. *
    11. * @author lisonglin
    12. * @version 1.0
    13. * @since 2022/1/24 17:33
    14. */
    15. public class StudentRepositoryImpl implements IStudentRepository {
    16. @Autowired
    17. private StudentDao studentDao;
    18. @Override
    19. public void save(StudentPo studentPo) {
    20. studentDao.save(studentPo);
    21. }
    22. @Override
    23. public StudentPo queryById(int id) {
    24. return studentDao.queryById(id);
    25. }
    26. }

    如果没有复杂的业务,那么到这里就可以进行controller的返回调用:
    image.png
    dto:前端给后端传递的数据
    facade:控制层

    1. package com.hikktn.interfaces.dto;
    2. /**
    3. * <p>
    4. * 学生请求参数
    5. * DTO:前端给后端传递的数据
    6. * </p>
    7. *
    8. * @author lisonglin
    9. * @version 1.0
    10. * @since 2022/1/24 16:28
    11. */
    12. public class StudentDto {
    13. /**
    14. * 标识符
    15. */
    16. private int id;
    17. public int getId() {
    18. return id;
    19. }
    20. public void setId(int id) {
    21. this.id = id;
    22. }
    23. }
    1. package com.hikktn.interfaces.facade;
    2. import com.hikktn.application.service.IStudentService;
    3. import com.hikktn.domain.repository.IStudentRepository;
    4. import com.hikktn.infrastructure.common.ResponseBase;
    5. import com.hikktn.interfaces.dto.StudentDto;
    6. import org.springframework.beans.factory.annotation.Autowired;
    7. import org.springframework.http.HttpStatus;
    8. import org.springframework.stereotype.Controller;
    9. import org.springframework.web.bind.annotation.RequestBody;
    10. import org.springframework.web.bind.annotation.RequestMapping;
    11. import org.springframework.web.bind.annotation.RequestParam;
    12. /**
    13. * <p>
    14. * 学生控制层
    15. * </p>
    16. *
    17. * @author lisonglin
    18. * @version 1.0
    19. * @since 2022/1/24 16:02
    20. */
    21. @Controller
    22. public class StudentController {
    23. /**
    24. * 学生业务对象
    25. */
    26. @Autowired
    27. private IStudentRepository studentRepository;
    28. /**
    29. * 查询一个学生基本信息
    30. * @param request 学生id
    31. * @return 学生的信息
    32. */
    33. @RequestMapping("/queryById")
    34. public ResponseBase queryById(@RequestParam("id") StudentDto request) {
    35. return new ResponseBase(HttpStatus.OK.value(), studentRepository.queryById(request.getId()));
    36. }
    37. }

    当我们遇到复杂的业务时,比如我有两张表,学生基本信息表,学生成绩表,组成两个不同的对象,但要同时返回给前台,就要用到domain、interfaces层
    image.png
    application下的service:存放复杂接口
    domain:
    model:对象
    aggregates:聚合,后端返回给前端的聚合信息体
    vo:后端给前端传递的数据
    repository:存放基本接口(CRUD)
    service:复杂接口实现层

    1. package com.hikktn.application.service;
    2. import com.hikktn.domain.model.aggregates.StudentEverydayModel;
    3. /**
    4. * <p>
    5. * 应用层用户服务
    6. * </p>
    7. *
    8. * @author lisonglin
    9. * @version 1.0
    10. * @since 2022/1/24 16:04
    11. */
    12. public interface IStudentService {
    13. /**
    14. * 根据id查询学生日常
    15. * @param id 标识符
    16. * @return 学生的日常
    17. */
    18. StudentEverydayModel queryStudentEverydayModelById(int id);
    19. }
    1. package com.hikktn.domain.model.vo;
    2. /**
    3. * <p>
    4. * 学生基本信息
    5. * VO:后端给前端传递的数据
    6. * </p>
    7. *
    8. * @author lisonglin
    9. * @version 1.0
    10. * @since 2022/1/24 16:35
    11. */
    12. public class StudentDataVo {
    13. /**
    14. * 主键
    15. */
    16. private int id;
    17. /**
    18. * 学生姓名
    19. */
    20. private String name;
    21. /**
    22. * 学生性别
    23. */
    24. private String sex;
    25. /**
    26. * 学生年龄
    27. */
    28. private int age;
    29. /**
    30. * 学生身高
    31. */
    32. private double stature;
    33. /**
    34. * 是否成年(根据年龄进行判断,该字段没有在PO对象中)
    35. */
    36. private int isCn;
    37. public int getId() {
    38. return id;
    39. }
    40. public void setId(int id) {
    41. this.id = id;
    42. }
    43. public String getName() {
    44. return name;
    45. }
    46. public void setName(String name) {
    47. this.name = name;
    48. }
    49. public String getSex() {
    50. return sex;
    51. }
    52. public void setSex(String sex) {
    53. this.sex = sex;
    54. }
    55. public int getAge() {
    56. return age;
    57. }
    58. public void setAge(int age) {
    59. this.age = age;
    60. }
    61. public double getStature() {
    62. return stature;
    63. }
    64. public void setStature(double stature) {
    65. this.stature = stature;
    66. }
    67. public int getIsCn() {
    68. return isCn;
    69. }
    70. public void setIsCn(int isCn) {
    71. this.isCn = isCn;
    72. }
    73. }
    1. package com.hikktn.domain.model.vo;
    2. /**
    3. * <p>
    4. * 学生成绩的信息
    5. * VO:后端给前端传递的数据
    6. * </p>
    7. *
    8. * @author lisonglin
    9. * @version 1.0
    10. * @since 2022/1/24 16:36
    11. */
    12. public class StudentScoreVo {
    13. /**
    14. * 学生平均成绩
    15. */
    16. private double pjcj;
    17. /**
    18. * 学生语文成绩
    19. */
    20. private double ywcj;
    21. /**
    22. * 学生数学成绩
    23. */
    24. private double sxcj;
    25. /**
    26. * 学生英语成绩
    27. */
    28. private double yycj;
    29. /**
    30. * 是否合格(根据平均成绩进行判断,该字段没有在PO对象中)
    31. */
    32. private int isHg;
    33. public double getPjcj() {
    34. return pjcj;
    35. }
    36. public void setPjcj(double pjcj) {
    37. this.pjcj = pjcj;
    38. }
    39. public double getYwcj() {
    40. return ywcj;
    41. }
    42. public void setYwcj(double ywcj) {
    43. this.ywcj = ywcj;
    44. }
    45. public double getSxcj() {
    46. return sxcj;
    47. }
    48. public void setSxcj(double sxcj) {
    49. this.sxcj = sxcj;
    50. }
    51. public double getYycj() {
    52. return yycj;
    53. }
    54. public void setYycj(double yycj) {
    55. this.yycj = yycj;
    56. }
    57. public int getIsHg() {
    58. return isHg;
    59. }
    60. public void setIsHg(int isHg) {
    61. this.isHg = isHg;
    62. }
    63. }
    1. package com.hikktn.domain.model.aggregates;
    2. import com.hikktn.domain.model.vo.StudentDataVo;
    3. import com.hikktn.domain.model.vo.StudentScoreVo;
    4. /**
    5. * <p>
    6. * 学生日常
    7. * aggregates:聚合,后端返回给前端的聚合信息体
    8. * </p>
    9. *
    10. * @author lisonglin
    11. * @version 1.0
    12. * @since 2022/1/24 16:10
    13. */
    14. public class StudentEverydayModel {
    15. /**
    16. * 学生基本信息
    17. */
    18. private StudentDataVo studentDataVo;
    19. /**
    20. * 学生成绩的信息
    21. */
    22. private StudentScoreVo studentScoreVo;
    23. public StudentDataVo getStudentDataVo() {
    24. return studentDataVo;
    25. }
    26. public void setStudentDataVo(StudentDataVo studentDataVo) {
    27. this.studentDataVo = studentDataVo;
    28. }
    29. public StudentScoreVo getStudentScoreVo() {
    30. return studentScoreVo;
    31. }
    32. public void setStudentScoreVo(StudentScoreVo studentScoreVo) {
    33. this.studentScoreVo = studentScoreVo;
    34. }
    35. }
    1. package com.hikktn.domain.repository;
    2. import com.hikktn.infrastructure.po.StudentPo;
    3. import org.springframework.stereotype.Repository;
    4. /**
    5. * <p>
    6. * 学生的信息业务处理
    7. * repository:后端传给业务处理的PO数据
    8. * </p>
    9. *
    10. * @author lisonglin
    11. * @version 1.0
    12. * @since 2022/1/24 17:17
    13. */
    14. @Repository("studentRepository")
    15. public interface IStudentRepository {
    16. /**
    17. * 新增学生的信息
    18. * @param studentPo 学生的基本信息
    19. */
    20. void save(StudentPo studentPo);
    21. /**
    22. * 根据id查询学生基本信息
    23. * @param id 标识符
    24. * @return 学生的基本信息
    25. */
    26. StudentPo queryById(int id);
    27. }
    1. package com.hikktn.domain.service;
    2. import com.hikktn.application.service.IStudentService;
    3. import com.hikktn.domain.model.aggregates.StudentEverydayModel;
    4. import org.springframework.stereotype.Service;
    5. import javax.annotation.Resource;
    6. /**
    7. * <p>
    8. * 应用层实现类(聚合对象)
    9. * </p>
    10. *
    11. * @author lisonglin
    12. * @version 1.0
    13. * @since 2022/1/24 17:04
    14. */
    15. @Service("studentService")
    16. public class StudentServiceImpl implements IStudentService {
    17. @Resource(name = "iStudentService")
    18. private IStudentService studentService;
    19. @Override
    20. public StudentEverydayModel queryStudentEverydayModelById(int id) {
    21. return studentService.queryStudentEverydayModelById(id);
    22. }
    23. }

    最后就是启动类和配置信息

    1. package com.hikktn;
    2. import org.mybatis.spring.annotation.MapperScan;
    3. import org.springframework.boot.SpringApplication;
    4. import org.springframework.boot.autoconfigure.SpringBootApplication;
    5. /**
    6. * <p>
    7. * 主方法启动类
    8. * </p>
    9. *
    10. * @author lisonglin
    11. * @version 1.0
    12. * @since 2022/1/24 15:59
    13. */
    14. @SpringBootApplication
    15. @MapperScan("com.hikktn.infrastructure.dao")
    16. public class Application {
    17. public static void main(String[] args) {
    18. SpringApplication.run(Application.class, args);
    19. }
    20. }
    1. server:
    2. port: 9000
    3. spring:
    4. datasource:
    5. driver-class-name: com.mysql.jdbc.Driver
    6. url: jdbc:mysql://127.0.0.1:3306/test?useUnicode=true&characterEncoding=utf8&useSSL=false
    7. username: root
    8. password: 123