我的编程空间,编程开发者的网络收藏夹
学习永远不晚

浅谈Java开发架构之领域驱动设计DDD落地

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

浅谈Java开发架构之领域驱动设计DDD落地

一、前言

整个过程大概是这样的,开发团队和领域专家一起通过 通用语言(Ubiquitous Language)去理解和消化领域知识,从领域知识中提取和划分为一个一个的子领域(核心子域,通用子域,支撑子域),并在子领域上建立模型,再重复以上步骤,这样周而复始,构建出一套符合当前领域的模型。

二、开发目标

依靠领域驱动设计的设计思想,通过事件风暴建立领域模型,合理划分领域逻辑和物理边界,建立领域对象及服务矩阵和服务架构图,定义符合DDD分层架构思想的代码结构模型,保证业务模型与代码模型的一致性。通过上述设计思想、方法和过程,指导团队按照DDD设计思想完成微服务设计和开发。

1、拒绝泥球小单体、拒绝污染功能与服务、拒绝一加功能排期一个月

2、架构出高可用极易符合互联网高速迭代的应用服务

3、物料化、组装化、可编排的服务,提高人效

三、服务架构

3.1、应用层{application}

  • 应用服务位于应用层。用来表述应用和用户行为,负责服务的组合、编排和转发,负责处理业务用例的执行顺序以及结果的拼装。
  • 应用层的服务包括应用服务和领域事件相关服务。
  • 应用服务可对微服务内的领域服务以及微服务外的应用服务进行组合和编排,或者对基础层如文件、缓存等数据直接操作形成应用服务,对外提供粗粒度的服务。
  • 领域事件服务包括两类:领域事件的发布和订阅。通过事件总线和消息队列实现异步数据传输,实现微服务之间的解耦。

3.2、领域层{domain}

  • 领域服务位于领域层,为完成领域中跨实体或值对象的操作转换而封装的服务,领域服务以与实体和值对象相同的方式参与实施过程。
  • 领域服务对同一个实体的一个或多个方法进行组合和封装,或对多个不同实体的操作进行组合或编排,对外暴露成领域服务。领域服务封装了核心的业务逻辑。实体自身的行为在实体类内部实现,向上封装成领域服务暴露。
  • 为隐藏领域层的业务逻辑实现,所有领域方法和服务等均须通过领域服务对外暴露。
  • 为实现微服务内聚合之间的解耦,原则上禁止跨聚合的领域服务调用和跨聚合的数据相互关联。

3.3、基础层{infrastructrue}

  • 基础服务位于基础层。为各层提供资源服务(如数据库、缓存等),实现各层的解耦,降低外部资源变化对业务逻辑的影响。
  • 基础服务主要为仓储服务,通过依赖反转的方式为各层提供基础资源服务,领域服务和应用服务调用仓储服务接口,利用仓储实现持久化数据对象或直接访问基础资源。

3.4、接口层{interfaces}

接口服务位于用户接口层,用于处理用户发送的Restful请求和解析用户输入的配置文件等,并将信息传递给应用层。

四、开发环境

jdk1.8【jdk1.7以下只能部分支持netty】

springboot 2.0.6.RELEASE

idea + maven

五、代码示例

itstack-demo-ddd-01

└── class="lazy" data-src

    ├── main

    │   ├── java

    │   │   └── org.itstack.demo

    │   │       ├── application

    │   │       │ ├── event

    │   │       │ │   └── ApplicationRunner.java

    │   │       │ └── service

    │   │       │     └── UserService.java

    │   │       ├── domain

    │   │       │ ├── model

    │   │       │ │   ├── aggregates

    │   │       │ │   │   └── UserRichInfo.java

    │   │       │ │   └── vo

    │   │       │ │       ├── UserInfo.java

    │   │       │ │       └── UserSchool.java

    │   │       │ ├── repository

    │   │       │ │   └── IuserRepository.java

    │   │       │ └── service

    │   │       │     └── UserServiceImpl.java

    │   │       ├── infrastructure

    │   │       │ ├── dao

    │   │       │ │   ├── impl

    │   │       │ │   │   └── UserDaoImpl.java

    │   │       │ │   └── UserDao.java

    │   │       │ ├── po

    │   │       │ │   └── UserEntity.java

    │   │       │ ├── repository

    │   │       │ │   ├── mysql

    │   │       │ │   │   └── UserMysqlRepository.java

    │   │       │ │   ├── redis

    │   │       │ │   │   └── UserRedisRepository.java

    │   │       │ │   └── UserRepository.java

    │   │       │ └── util

    │   │       │     └── RdisUtil.java

    │   │       ├── interfaces

    │   │       │ ├── dto

    │   │       │ │ └── UserInfoDto.java

    │   │       │ └── facade

    │   │       │ └── DDDController.java

    │   │       └── DDDApplication.java

    │   ├── resources

    │   │   └── application.yml

    │   └── webapp

    │       └── WEB-INF

    │        └── index.jsp

    └── test

         └── java

             └── org.itstack.demo.test

                 └── ApiTest.java

application/UserService.java | 应用层用户服务,领域层服务做具体实现


public interface UserService {

    UserRichInfo queryUserInfoById(Long id);

}

domain/repository/IuserRepository.java | 领域层资源库,由基础层实现


public interface IUserRepository {

    void save(UserEntity userEntity);

    UserEntity query(Long id);

}

domain/service/UserServiceImpl.java | 应用层实现类,应用层是很薄的一层可以只做服务编排


@Service("userService")
public class UserServiceImpl implements UserService {

    @Resource(name = "userRepository")
    private IUserRepository userRepository;

    @Override
    public UserRichInfo queryUserInfoById(Long id) {
        
        // 查询资源库
        UserEntity userEntity = userRepository.query(id);

        UserInfo userInfo = new UserInfo();
        userInfo.setName(userEntity.getName());

        // TODO 查询学校信息,外部接口
        UserSchool userSchool_01 = new UserSchool();
        userSchool_01.setSchoolName("振华高级实验中学");

        UserSchool userSchool_02 = new UserSchool();
        userSchool_02.setSchoolName("东北电力大学");

        List<UserSchool> userSchoolList = new ArrayList<>();
        userSchoolList.add(userSchool_01);
        userSchoolList.add(userSchool_02);

        UserRichInfo userRichInfo = new UserRichInfo();
        userRichInfo.setUserInfo(userInfo);
        userRichInfo.setUserSchoolList(userSchoolList);

        return userRichInfo;
    }

}

infrastructure/po/UserEntity.java | 数据库对象类


public class UserEntity {

    private Long id;
    private String name;

    get/set ...
}

infrastructrue/repository/UserRepository.java | 领域层定义接口,基础层资源库实现


@Repository("userRepository")
public class UserRepository implements IUserRepository {

    @Resource(name = "userMysqlRepository")
    private IUserRepository userMysqlRepository;

    @Resource(name = "userRedisRepository")
    private IUserRepository userRedisRepository;

    @Override
    public void save(UserEntity userEntity) {
        //保存到DB
        userMysqlRepository.save(userEntity);

        //保存到Redis
        userRedisRepository.save(userEntity);
    }

    @Override
    public UserEntity query(Long id) {

        UserEntity userEntityRedis = userRedisRepository.query(id);
        if (null != userEntityRedis) return userEntityRedis;

        UserEntity userEntityMysql = userMysqlRepository.query(id);
        if (null != userEntityMysql){
            //保存到Redis
            userRedisRepository.save(userEntityMysql);
            return userEntityMysql;
        }

        // 查询为NULL
        return null;
    }

}

interfaces/dto/UserInfoDto.java | DTO对象类,隔离数据库类


public class UserInfoDto {

    private Long id;        // ID

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

}

interfaces/facade/DDDController.java | 门面接口


@Controller
public class DDDController {

    @Resource(name = "userService")
    private UserService userService;

    @RequestMapping("/index")
    public String index(Model model) {
        return "index";
    }

    @RequestMapping("/api/user/queryUserInfo")
    @ResponseBody
    public ResponseEntity queryUserInfo(@RequestBody UserInfoDto request) {
        return new ResponseEntity<>(userService.queryUserInfoById(request.getId()), HttpStatus.OK);
    }

}

六、综上总结

以上基于DDD一个基本入门的结构演示完成,实际开发可以按照此模式进行调整。目前这个架构分层还不能很好的进行分离,以及层级关系的引用还不利于扩展。

以上就是浅谈Java开发架构之领域驱动设计DDD落地的详细内容,更多关于Java开发架构 领域驱动设计DDD落地的资料请关注编程网其它相关文章!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

浅谈Java开发架构之领域驱动设计DDD落地

下载Word文档到电脑,方便收藏和打印~

下载Word文档

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录