• 领域驱动设计


    1.基本概念

    VO(View Object):视图对象,用于展示层,它的作用是把某个指定页面(或组件)的所有数据封装起来。简称为页面对象。

    DTO(Data Transfer Object):数据传输对象,这个概念来源于J2EE的设计模式,原来的目的是为了EJB的分布式应用提供粗粒度的数据实体,以减少分布式调用的次数,从而提高分布式调用的性能和降低网络负载,但在这里,我泛指用于展示层与服务层之间的数据传输对象。

    DO(Domain Object):领域对象,就是从现实世界中抽象出来的有形或无形的业务实体。

    PO(Persistent Object):持久化对象,它跟持久层(通常是关系型数据库)的数据结构形成一一对应的映射关系,如果持久层是关系型数据库,那么,数据表中的每个字段(或若干个)就对应PO的一个(或若干个)属性。

    模型:

    用户发出请求(可能是填写表单),表单的数据在展示层被匹配为VO。

    展示层把VO转换为服务层对应方法所要求的DTO,传送给服务层。

    服务层首先根据DTO的数据构造(或重建)一个DO,调用DO的业务方法完成具体业务。

    服务层把DO转换为持久层对应的PO(可以使用ORM工具,也可以不用),调用持久层的持久化方法,把PO传递给它,完成持久化操作。

    对于一个逆向操作,如读取数据,也是用类似的方式转换和传递,略。

    2.基于DDD模型的微服务分层架构图

     

    3.dto的应用实例

    3.1 需求分析

    现有学生表,课程表,分数表,这三张表,要求通过学号查询出学生信息,包含课程和分数,这里我们采用dto思想进行操作。

    3.2 代码实现

    编写转换器,将实体类换成dto对象

    package com.gh.blog.dto;
    
    import com.github.pagehelper.PageInfo;
    import org.springframework.beans.BeanUtils;
    
    import java.util.ArrayList;
    import java.util.List;
    
    public interface Convert<DTO, ENTITY> {
    
        /**
         * 把ENTITY转换为DTO
         * @param entity
         * @return
         */
        default DTO convertFrom(ENTITY entity) {
            try {
                BeanUtils.copyProperties(entity, this);
                return (DTO)this;
            } catch (Exception e) {
                e.printStackTrace();
                throw new RuntimeException("系统异常");
            }
    
        }
    
        /**
         * 把List<ENTITY>转换为List<DTO>
         * @param entities
         * @return
         */
        default List<DTO> convertFrom(List<ENTITY> entities) {
            List dtoList = new ArrayList();
            for (ENTITY entity : entities) {
                try {
                    // 反射当前对象,Obj就是指的当前对象,也就是ArticleDTO
                    Object dto = this.getClass().newInstance();
    
                    // 拷贝参数,把entity中的参数数据,拷贝到obj
                    BeanUtils.copyProperties(entity, dto);
                    dtoList.add(dto);
                } catch (Exception e) {
                    e.printStackTrace();
                    throw new RuntimeException("系统异常");
                }
    
            }
            return dtoList;
        }
    
        /**
         * 把page<ENTITY>转换为page<DTO>
         * @param page
         * @return
         */
        default PageInfo<DTO> convertFrom(PageInfo page) {
            // 把page<Article>的list取出,进行转换
            List<ENTITY> entities = page.getList();
    
            // 把Article的list转换为ArticleDTO的list
            List<DTO> dtos = convertFrom(entities);
    
            // 更换page的内容
            page.setList(dtos);
            return page;
        }
    }

    我们这里返回给页面的一个dto对象

    @Getter
    @Setter
    public class StudentDetailDTO implements Convert<StudentDetailDTO, Student> {
    
        private String no;
        private String name;
        private Boolean sex;
        private Date birthday;
        private Date inSchoolDay;
        private String classCode;
        private String phone;
        private String homeAddress;
    
        private List<ScoreDTO> scores;
        
    }

    这里的dto包含了ScoreDTO进一步进行封装

    @Getter
    @Setter
    public class ScoreDTO implements Convert<ScoreDTO, Score> {
    
        private Double score;
    
        private Course course;
        
    }

    controller的实现

        @GetMapping("detail")
        public StudentDetailDTO studentDetail(String no) {
            StudentDetailDTO studentDetail = stuService.findDetail(no);
    
            return studentDetail;
        }

    service实现类

        @Override
        public StudentDetailDTO findDetail(String no) {
            // 查询学生信息并转换为dto
            StudentDetailDTO studentDetail = new StudentDetailDTO().convertFrom(stuMapper.findByNo(no));
            // 查询学生全部成绩
            List<ScoreDTO> scores = new ArrayList<>();
            //根据学号查成绩,然后拿到该学生的所有成绩,进行遍历
            for (Score item : scoreMapper.listByStudentNo(no)) {
                //把学生成绩用dto封装
                ScoreDTO score = new ScoreDTO().convertFrom(item);
                // 查询成绩对应课程
                Course course = courseMapper.getByCode(item.getCourseNo());
                score.setCourse(course);
                scores.add(score);
            }
            studentDetail.setScores(scores);
            return studentDetail;
        }

    dao是简单的单表查询操作,省略不写

    一点点学习,一丝丝进步。不懈怠,才不会被时代所淘汰!

  • 相关阅读:
    洛谷P2221 [HAOI2012]高速公路(线段树+概率期望)
    洛谷P2254 [NOI2005]瑰丽华尔兹(单调队列)
    洛谷P2607 [ZJOI2008]骑士(基环树)
    洛谷P1505 [国家集训队]旅游(树剖+线段树)
    洛谷P3250 [HNOI2016]网络(整体二分+树状数组+树剖)
    洛谷P3833 [SHOI2012]魔法树(树链剖分)
    洛谷P4216 [SCOI2015]情报传递(树剖+主席树)
    Ansible 利用playbook批量部署Nginx
    Ansible实现zabbix服务器agent端批量部署
    时间序列模型:ARIMA
  • 原文地址:https://www.cnblogs.com/fqh2020/p/14844383.html
Copyright © 2020-2023  润新知