• 程序员除了会CRUD之外,还应该知道什么叫CQRS!


                    <section powered-by="xiumi.us" class="" style="margin-top: 10px;margin-bottom: 10px;white-space: normal;letter-spacing: 0.544px;font-size: 16px;background-color: rgb(255, 255, 255);text-align: center;" data-mpa-powered-by="yiban.io"></section><section class="" mpa-from-tpl="t"><p style="max- 100%;min-height: 1em;letter-spacing: 2px;margin-left: 16px;margin-right: 16px;line-height: 1.75em;box-sizing: border-box !important;overflow-wrap: break-word !important;word-break: normal !important;" class=""><span style="max- 100%;color: rgb(83, 78, 78);letter-spacing: 2px;font-size: 16px;box-sizing: border-box !important;overflow-wrap: break-word !important;word-break: normal !important;">今天主要跟大家分享一下什么是 CQRS,以及在项目中如何去使用。</span></p><p style="max- 100%;min-height: 1em;letter-spacing: 2px;margin-left: 16px;margin-right: 16px;line-height: 1.75em;box-sizing: border-box !important;overflow-wrap: break-word !important;word-break: normal !important;" class=""><span style="max- 100%;color: rgb(83, 78, 78);letter-spacing: 2px;font-size: 16px;box-sizing: border-box !important;overflow-wrap: break-word !important;word-break: normal !important;"><br></span></p><p style="max- 100%;min-height: 1em;letter-spacing: 2px;margin-left: 16px;margin-right: 16px;line-height: 1.75em;box-sizing: border-box !important;overflow-wrap: break-word !important;word-break: normal !important;" class=""><em><span style="color: rgb(61, 167, 66);"><strong><span style="max- 100%;letter-spacing: 2px;font-size: 16px;box-sizing: border-box !important;overflow-wrap: break-word !important;word-break: normal !important;">1</span></strong></span></em><span style="color: rgb(61, 167, 66);"><strong><span style="max- 100%;letter-spacing: 2px;font-size: 16px;box-sizing: border-box !important;overflow-wrap: break-word !important;word-break: normal !important;">. CRUD系统</span></strong></span></p><p style="max- 100%;min-height: 1em;letter-spacing: 2px;margin-left: 16px;margin-right: 16px;line-height: 1.75em;box-sizing: border-box !important;overflow-wrap: break-word !important;word-break: normal !important;" class=""><span style="max- 100%;color: rgb(83, 78, 78);letter-spacing: 2px;font-size: 16px;box-sizing: border-box !important;overflow-wrap: break-word !important;word-break: normal !important;"></span></p><p style="max- 100%;min-height: 1em;letter-spacing: 2px;margin-left: 16px;margin-right: 16px;line-height: 1.75em;box-sizing: border-box !important;overflow-wrap: break-word !important;word-break: normal !important;" class=""><span style="max- 100%;color: rgb(83, 78, 78);letter-spacing: 2px;font-size: 16px;box-sizing: border-box !important;overflow-wrap: break-word !important;word-break: normal !important;">我们平常最熟悉的就是三层架构,通常都是通过数据访问层来修改或者查询数据,一般修改和查询使用的是相同的实体。然后通过业务层来处理业务逻辑,将处理结果封装成DTO对象返回给控制层,再通过前端渲染。反之亦然。</span></p><p style="max- 100%;min-height: 1em;letter-spacing: 2px;margin-left: 16px;margin-right: 16px;line-height: 1.75em;box-sizing: border-box !important;overflow-wrap: break-word !important;word-break: normal !important;" class=""><span style="max- 100%;color: rgb(83, 78, 78);letter-spacing: 2px;font-size: 16px;box-sizing: border-box !important;overflow-wrap: break-word !important;word-break: normal !important;"><br></span></p><p style="text-align: center;"><img class="rich_pages " data-ratio="1.2238805970149254" data-s="300,640" data-src="https://img2018.cnblogs.com/blog/1112483/201909/1112483-20190906104222357-96794074.png" data-type="png" data-w="469" style="box-shadow: rgb(170, 170, 170) 0em 0em 1em 0px; border-radius: 9px;  74% !important; height: auto !important; visibility: visible !important;" _width="74%" src="https://img2018.cnblogs.com/blog/1112483/201909/1112483-20190906104330353-857200861.png" crossorigin="anonymous" data-fail="0"></p><p style="max- 100%;min-height: 1em;letter-spacing: 2px;margin-left: 16px;margin-right: 16px;line-height: 1.75em;box-sizing: border-box !important;overflow-wrap: break-word !important;word-break: normal !important;" class=""><span style="max- 100%;color: rgb(83, 78, 78);letter-spacing: 2px;font-size: 16px;box-sizing: border-box !important;overflow-wrap: break-word !important;word-break: normal !important;"></span><br></p></section><section class="" mpa-from-tpl="t"><p style="max- 100%;min-height: 1em;letter-spacing: 2px;margin-left: 16px;margin-right: 16px;line-height: 1.75em;box-sizing: border-box !important;overflow-wrap: break-word !important;word-break: normal !important;" class=""><span style="max- 100%;color: rgb(83, 78, 78);letter-spacing: 2px;font-size: 16px;box-sizing: border-box !important;overflow-wrap: break-word !important;word-break: normal !important;">这里基本上是围绕关系数据库构建而成的“创建、读取、更新、删除”系统(即CRUD系统),此类系统在一些业务逻辑简单的项目中可能没有什么问题,但是随着系统逻辑变得复杂,用户增多,这种设计就会出现一些性能问题。</span></p><p style="max- 100%;min-height: 1em;letter-spacing: 2px;margin-left: 16px;margin-right: 16px;line-height: 1.75em;box-sizing: border-box !important;overflow-wrap: break-word !important;word-break: normal !important;" class=""><span style="max- 100%;color: rgb(83, 78, 78);letter-spacing: 2px;font-size: 16px;box-sizing: border-box !important;overflow-wrap: break-word !important;word-break: normal !important;"><br></span></p><p style="max- 100%;min-height: 1em;letter-spacing: 2px;margin-left: 16px;margin-right: 16px;line-height: 1.75em;box-sizing: border-box !important;overflow-wrap: break-word !important;word-break: normal !important;" class=""><span style="max- 100%;color: rgb(83, 78, 78);letter-spacing: 2px;font-size: 16px;box-sizing: border-box !important;overflow-wrap: break-word !important;word-break: normal !important;">我们经常用到的解决方案就是对数据库进行读写分离。让主数据库处理事务性的增、删、改操作,让从数据库处理查询操作,然后主从数据库之间进行同步。但是这只是从DB角度处理了读写分离,从业务或者系统层面上来说,读和写的逻辑仍然是存放在一起的,他们都是操作同一个实体对象。</span></p><p style="max- 100%;min-height: 1em;letter-spacing: 2px;margin-left: 16px;margin-right: 16px;line-height: 1.75em;box-sizing: border-box !important;overflow-wrap: break-word !important;word-break: normal !important;" class=""><span style="max- 100%;color: rgb(83, 78, 78);letter-spacing: 2px;font-size: 16px;box-sizing: border-box !important;overflow-wrap: break-word !important;word-break: normal !important;"><br></span></p><p style="max- 100%;min-height: 1em;letter-spacing: 2px;margin-left: 16px;margin-right: 16px;line-height: 1.75em;box-sizing: border-box !important;overflow-wrap: break-word !important;word-break: normal !important;" class=""><span style="max- 100%;color: rgb(83, 78, 78);letter-spacing: 2px;font-size: 16px;box-sizing: border-box !important;overflow-wrap: break-word !important;word-break: normal !important;">这时候,CQRS 就该登场了。</span></p><p style="max- 100%;min-height: 1em;letter-spacing: 2px;margin-left: 16px;margin-right: 16px;line-height: 1.75em;box-sizing: border-box !important;overflow-wrap: break-word !important;word-break: normal !important;" class=""><span style="max- 100%;color: rgb(83, 78, 78);letter-spacing: 2px;font-size: 16px;box-sizing: border-box !important;overflow-wrap: break-word !important;word-break: normal !important;"><br></span></p><p style="max- 100%;min-height: 1em;letter-spacing: 2px;margin-left: 16px;margin-right: 16px;line-height: 1.75em;box-sizing: border-box !important;overflow-wrap: break-word !important;word-break: normal !important;" class=""><em><span style="color: rgb(61, 167, 66);"><strong><span style="max- 100%;letter-spacing: 2px;font-size: 16px;box-sizing: border-box !important;overflow-wrap: break-word !important;word-break: normal !important;">2</span></strong></span></em><span style="color: rgb(61, 167, 66);"><strong><span style="max- 100%;letter-spacing: 2px;font-size: 16px;box-sizing: border-box !important;overflow-wrap: break-word !important;word-break: normal !important;">. CQRS系统</span></strong></span></p><p style="max- 100%;min-height: 1em;letter-spacing: 2px;margin-left: 16px;margin-right: 16px;line-height: 1.75em;box-sizing: border-box !important;overflow-wrap: break-word !important;word-break: normal !important;" class=""><span style="max- 100%;color: rgb(83, 78, 78);letter-spacing: 2px;font-size: 16px;box-sizing: border-box !important;overflow-wrap: break-word !important;word-break: normal !important;"><br></span></p><p style="max- 100%;min-height: 1em;letter-spacing: 2px;margin-left: 16px;margin-right: 16px;line-height: 1.75em;box-sizing: border-box !important;overflow-wrap: break-word !important;word-break: normal !important;" class=""><span style="max- 100%;color: rgb(83, 78, 78);letter-spacing: 2px;font-size: 16px;box-sizing: border-box !important;overflow-wrap: break-word !important;word-break: normal !important;">简单的说,CQRS(Command Query Responsibility Segration)就是一个系统,从架构上把 CRUD 系统拆分为两部分:命令(Command)处理和查询(Query)处理。其中命令处理包括增、删、改。</span></p><p style="max- 100%;min-height: 1em;letter-spacing: 2px;margin-left: 16px;margin-right: 16px;line-height: 1.75em;box-sizing: border-box !important;overflow-wrap: break-word !important;word-break: normal !important;" class=""><span style="max- 100%;color: rgb(83, 78, 78);letter-spacing: 2px;font-size: 16px;box-sizing: border-box !important;overflow-wrap: break-word !important;word-break: normal !important;"><br></span></p><p style="text-align: center;"><img class="rich_pages " data-ratio="1.3552036199095023" data-s="300,640" data-src="https://img2018.cnblogs.com/blog/1112483/201909/1112483-20190906104400352-1633815434.png" data-type="png" data-w="442" style="box-shadow: rgb(170, 170, 170) 0em 0em 1em 0px; border-radius: 15px;  69% !important; height: auto !important; visibility: visible !important;" _width="69%" src="https://img2018.cnblogs.com/blog/1112483/201909/1112483-20190906104449391-1088072546.png" crossorigin="anonymous" data-fail="0"></p><p style="max- 100%;min-height: 1em;letter-spacing: 2px;margin-left: 16px;margin-right: 16px;line-height: 1.75em;box-sizing: border-box !important;overflow-wrap: break-word !important;word-break: normal !important;" class=""><span style="max- 100%;color: rgb(83, 78, 78);letter-spacing: 2px;font-size: 16px;box-sizing: border-box !important;overflow-wrap: break-word !important;word-break: normal !important;"></span><br></p></section><section class="" mpa-from-tpl="t"><p style="max- 100%;min-height: 1em;letter-spacing: 2px;margin-left: 16px;margin-right: 16px;line-height: 1.75em;box-sizing: border-box !important;overflow-wrap: break-word !important;word-break: normal !important;" class=""><span style="max- 100%;color: rgb(83, 78, 78);letter-spacing: 2px;font-size: 16px;box-sizing: border-box !important;overflow-wrap: break-word !important;word-break: normal !important;">然后命令与查询两边可以用不同的架构实现,以实现CQ两端(即Command Side,简称C端;Query Side,简称Q端)的分别优化。两边所涉及到的实体对象也可以不同,从而继续演变成下面这样。</span></p><p style="max- 100%;min-height: 1em;letter-spacing: 2px;margin-left: 16px;margin-right: 16px;line-height: 1.75em;box-sizing: border-box !important;overflow-wrap: break-word !important;word-break: normal !important;" class=""><span style="max- 100%;color: rgb(83, 78, 78);letter-spacing: 2px;font-size: 16px;box-sizing: border-box !important;overflow-wrap: break-word !important;word-break: normal !important;"><br></span></p><p style="text-align: center;"><img class="rich_pages " data-ratio="1.205940594059406" data-s="300,640" data-src="https://img2018.cnblogs.com/blog/1112483/201909/1112483-20190906104516403-1309499305.png;" _width="80%" src="https://img2018.cnblogs.com/blog/1112483/201909/1112483-20190906104516403-1309499305.png" crossorigin="anonymous" data-fail="0"></p><p style="max- 100%;min-height: 1em;letter-spacing: 2px;margin-left: 16px;margin-right: 16px;line-height: 1.75em;box-sizing: border-box !important;overflow-wrap: break-word !important;word-break: normal !important;" class=""><span style="max- 100%;color: rgb(83, 78, 78);letter-spacing: 2px;font-size: 16px;box-sizing: border-box !important;overflow-wrap: break-word !important;word-break: normal !important;"></span><br></p></section><section class="" mpa-from-tpl="t"><p style="max- 100%;min-height: 1em;letter-spacing: 2px;margin-left: 16px;margin-right: 16px;line-height: 1.75em;box-sizing: border-box !important;overflow-wrap: break-word !important;word-break: normal !important;" class=""><span style="max- 100%;color: rgb(83, 78, 78);letter-spacing: 2px;font-size: 16px;box-sizing: border-box !important;overflow-wrap: break-word !important;word-break: normal !important;">当然了,CQRS 作为一个读写分离思想的架构,在数据存储方面,也没有做过多的约束。所以 CQRS可以有不同层次的实现。</span></p><p style="max- 100%;min-height: 1em;letter-spacing: 2px;margin-left: 16px;margin-right: 16px;line-height: 1.75em;box-sizing: border-box !important;overflow-wrap: break-word !important;word-break: normal !important;" class=""><span style="max- 100%;color: rgb(83, 78, 78);letter-spacing: 2px;font-size: 16px;box-sizing: border-box !important;overflow-wrap: break-word !important;word-break: normal !important;"><br></span></p><p style="max- 100%;min-height: 1em;letter-spacing: 2px;margin-left: 16px;margin-right: 16px;line-height: 1.75em;box-sizing: border-box !important;overflow-wrap: break-word !important;word-break: normal !important;" class=""><em><span style="color: rgb(61, 167, 66);"><strong><span style="max- 100%;letter-spacing: 2px;font-size: 16px;box-sizing: border-box !important;overflow-wrap: break-word !important;word-break: normal !important;">3</span></strong></span></em><span style="color: rgb(61, 167, 66);"><strong><span style="max- 100%;letter-spacing: 2px;font-size: 16px;box-sizing: border-box !important;overflow-wrap: break-word !important;word-break: normal !important;">. CQRS 实现方式</span></strong></span></p><p style="max- 100%;min-height: 1em;letter-spacing: 2px;margin-left: 16px;margin-right: 16px;line-height: 1.75em;box-sizing: border-box !important;overflow-wrap: break-word !important;word-break: normal !important;" class=""><span style="max- 100%;color: rgb(83, 78, 78);letter-spacing: 2px;font-size: 16px;box-sizing: border-box !important;overflow-wrap: break-word !important;word-break: normal !important;"><br></span></p><p style="max- 100%;min-height: 1em;letter-spacing: 2px;margin-left: 16px;margin-right: 16px;line-height: 1.75em;box-sizing: border-box !important;overflow-wrap: break-word !important;word-break: normal !important;" class=""><span style="max- 100%;color: rgb(83, 78, 78);letter-spacing: 2px;font-size: 16px;box-sizing: border-box !important;overflow-wrap: break-word !important;word-break: normal !important;">CQRS 可以有两种实现方式。</span></p><p style="max- 100%;min-height: 1em;letter-spacing: 2px;margin-left: 16px;margin-right: 16px;line-height: 1.75em;box-sizing: border-box !important;overflow-wrap: break-word !important;word-break: normal !important;" class=""><span style="max- 100%;color: rgb(83, 78, 78);letter-spacing: 2px;font-size: 16px;box-sizing: border-box !important;overflow-wrap: break-word !important;word-break: normal !important;"><br></span></p><p style="max- 100%;min-height: 1em;letter-spacing: 2px;margin-left: 16px;margin-right: 16px;line-height: 1.75em;box-sizing: border-box !important;overflow-wrap: break-word !important;word-break: normal !important;" class=""><span style="max- 100%;color: rgb(83, 78, 78);letter-spacing: 2px;font-size: 16px;box-sizing: border-box !important;overflow-wrap: break-word !important;word-break: normal !important;">1)CQ 两端数据库共享,只是在上层代码上分离。这样做的好处是可以让我们的代码读写分离,更容易维护,而且不存在 CQ 两端的数据一致性问题,因为是共享一个数据库的。这种架构是非常实用的(也就是我上面画的那种)。</span></p><p style="max- 100%;min-height: 1em;letter-spacing: 2px;margin-left: 16px;margin-right: 16px;line-height: 1.75em;box-sizing: border-box !important;overflow-wrap: break-word !important;word-break: normal !important;" class=""><span style="max- 100%;color: rgb(83, 78, 78);letter-spacing: 2px;font-size: 16px;box-sizing: border-box !important;overflow-wrap: break-word !important;word-break: normal !important;"><br></span></p><p style="max- 100%;min-height: 1em;letter-spacing: 2px;margin-left: 16px;margin-right: 16px;line-height: 1.75em;box-sizing: border-box !important;overflow-wrap: break-word !important;word-break: normal !important;" class=""><span style="max- 100%;color: rgb(83, 78, 78);letter-spacing: 2px;font-size: 16px;box-sizing: border-box !important;overflow-wrap: break-word !important;word-break: normal !important;">2)CQ 两端不仅代码分离,数据库也分离,然后Q端数据由C端同步过来。同步方式有两种:同步或异步,如果需要 CQ 两端的强一致性,则需要用同步;如果能接受 CQ 两端数据的最终一致性,则可以使用异步。C端可以采用Event Sourcing(简称ES)模式,所有C端的最新数据全部用 Domain Event 表达即可;而要查询显示用的数据,则从Q端的 ReadDB(关系型数据库)查询即可(详细可以参考文献3)。</span></p><p style="max- 100%;min-height: 1em;letter-spacing: 2px;margin-left: 16px;margin-right: 16px;line-height: 1.75em;box-sizing: border-box !important;overflow-wrap: break-word !important;word-break: normal !important;" class=""><span style="max- 100%;color: rgb(83, 78, 78);letter-spacing: 2px;font-size: 16px;box-sizing: border-box !important;overflow-wrap: break-word !important;word-break: normal !important;"><br></span></p><p style="max- 100%;min-height: 1em;letter-spacing: 2px;margin-left: 16px;margin-right: 16px;line-height: 1.75em;box-sizing: border-box !important;overflow-wrap: break-word !important;word-break: normal !important;" class=""><em><strong><span style="max- 100%;letter-spacing: 2px;font-size: 16px;color: rgb(61, 167, 66);box-sizing: border-box !important;overflow-wrap: break-word !important;word-break: normal !important;">4</span></strong></em><strong><span style="max- 100%;letter-spacing: 2px;font-size: 16px;color: rgb(61, 167, 66);box-sizing: border-box !important;overflow-wrap: break-word !important;word-break: normal !important;">. CQRS 的简单实现</span></strong></p><p style="max- 100%;min-height: 1em;letter-spacing: 2px;margin-left: 16px;margin-right: 16px;line-height: 1.75em;box-sizing: border-box !important;overflow-wrap: break-word !important;word-break: normal !important;" class=""><span style="max- 100%;color: rgb(83, 78, 78);letter-spacing: 2px;font-size: 16px;box-sizing: border-box !important;overflow-wrap: break-word !important;word-break: normal !important;"><br></span></p><p style="max- 100%;min-height: 1em;letter-spacing: 2px;margin-left: 16px;margin-right: 16px;line-height: 1.75em;box-sizing: border-box !important;overflow-wrap: break-word !important;word-break: normal !important;" class=""><span style="max- 100%;color: rgb(83, 78, 78);letter-spacing: 2px;font-size: 16px;box-sizing: border-box !important;overflow-wrap: break-word !important;word-break: normal !important;">说了这么多,该怎么实现呢?我们以上面提到的第一种方式为例:代码层面实现分离,数据库共享。这种方式在企业里也非常实用。</span></p><p style="max- 100%;min-height: 1em;letter-spacing: 2px;margin-left: 16px;margin-right: 16px;line-height: 1.75em;box-sizing: border-box !important;overflow-wrap: break-word !important;word-break: normal !important;" class=""><span style="max- 100%;color: rgb(83, 78, 78);letter-spacing: 2px;font-size: 16px;box-sizing: border-box !important;overflow-wrap: break-word !important;word-break: normal !important;"><br></span></p><p style="max- 100%;min-height: 1em;letter-spacing: 2px;margin-left: 16px;margin-right: 16px;line-height: 1.75em;box-sizing: border-box !important;overflow-wrap: break-word !important;word-break: normal !important;" class=""><span style="max- 100%;color: rgb(83, 78, 78);letter-spacing: 2px;font-size: 16px;box-sizing: border-box !important;overflow-wrap: break-word !important;word-break: normal !important;">首先有几个概念需要介绍一下,CQRS 模式中,首先需要有 Command,这个 Command 命令会对应一个实体和一个命令的执行类。那整个系统中肯定有很多不同的 Command,那么还需要一个 CommandBus 来做命令的分发处理。</span></p><p style="max- 100%;min-height: 1em;letter-spacing: 2px;margin-left: 16px;margin-right: 16px;line-height: 1.75em;box-sizing: border-box !important;overflow-wrap: break-word !important;word-break: normal !important;" class=""><span style="max- 100%;color: rgb(83, 78, 78);letter-spacing: 2px;font-size: 16px;box-sizing: border-box !important;overflow-wrap: break-word !important;word-break: normal !important;"><br></span></p><p style="max- 100%;min-height: 1em;letter-spacing: 2px;margin-left: 16px;margin-right: 16px;line-height: 1.75em;box-sizing: border-box !important;overflow-wrap: break-word !important;word-break: normal !important;" class=""><span style="max- 100%;color: rgb(83, 78, 78);letter-spacing: 2px;font-size: 16px;box-sizing: border-box !important;overflow-wrap: break-word !important;word-break: normal !important;">可能大家觉得比较抽象,我来写几行示例代码,一看就明白了。假设有个订单模块,我要新增一个订单信息。那么根据上文的分析,需要有个新增命令以及对应的订单实体(并不一定和数据库的订单实体完全对应)。首先先创建一个命令接口(绑定命令对应的实体),接口内部有个该命令的处理方法。</span></p><p style="max- 100%;min-height: 1em;letter-spacing: 2px;margin-left: 16px;margin-right: 16px;line-height: 1.75em;box-sizing: border-box !important;overflow-wrap: break-word !important;word-break: normal !important;" class=""><span style="max- 100%;color: rgb(83, 78, 78);letter-spacing: 2px;font-size: 16px;box-sizing: border-box !important;overflow-wrap: break-word !important;word-break: normal !important;"><br></span></p><section data-mpa-preserve-tpl-color="t" data-mpa-template="t" class="" mpa-preserve="t" mpa-from-tpl="t" style="margin-left: 0.5em;margin-right: 0.5em;"><pre style="margin:0;padding:0;border-radius:none;background:none;"><code style="border-radius: 4px;font-size: 0.85em;margin: 0px 0.15em;background: rgb(40, 44, 52);color: rgb(171, 178, 191);display: block;padding: 5.95px;overflow-x: auto;white-space: nowrap;" class="hljs java"><span class="" style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline; 39px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;"><span class="hljs-keyword">public</span></span> <span class="" style="color: rgb(171, 178, 191);background: rgba(0, 0, 0, 0);display: inline; 138px;text-decoration: none solid rgb(171, 178, 191);font-weight: 400;font-style: normal;"><span class="" style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline; 58px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;"><span class="hljs-class"><span class="hljs-keyword">interface</span></span></span><span class="hljs-class"> </span><span class="" style="color: rgb(230, 192, 123);background: rgba(0, 0, 0, 0);display: inline; 46px;text-decoration: none solid rgb(230, 192, 123);font-weight: 400;font-style: normal;"><span class="hljs-class"><span class="hljs-title">Command</span></span></span><span class="hljs-class">&lt;</span><span class="" style="color: rgb(230, 192, 123);background: rgba(0, 0, 0, 0);display: inline; 6px;text-decoration: none solid rgb(230, 192, 123);font-weight: 400;font-style: normal;"><span class="hljs-class"><span class="hljs-title">T</span></span></span><span class="hljs-class">&gt; </span></span>{<br mpa-from-tpl="t"> <span class="" style="color: rgb(171, 178, 191);background: rgba(0, 0, 0, 0);display: inline; 183px;text-decoration: none solid rgb(171, 178, 191);font-weight: 400;font-style: normal;"><span class="" style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline; 26px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">&nbsp; &nbsp; <span class="hljs-function">Object</span></span><span class="hljs-function">&nbsp;</span><span class="" style="color: rgb(97, 174, 238);background: rgba(0, 0, 0, 0);display: inline; 46px;text-decoration: none solid rgb(97, 174, 238);font-weight: 400;font-style: normal;"><span class="hljs-function"><span class="hljs-title">execute</span></span></span><span class="" style="color: rgb(171, 178, 191);background: rgba(0, 0, 0, 0);display: inline; 105px;text-decoration: none solid rgb(171, 178, 191);font-weight: 400;font-style: normal;"><span class="hljs-function"><span class="hljs-params">(T commandModel)</span></span></span></span>;<br mpa-from-tpl="t">}</code></pre></section><p style="max- 100%;min-height: 1em;letter-spacing: 2px;margin-left: 16px;margin-right: 16px;line-height: 1.75em;box-sizing: border-box !important;overflow-wrap: break-word !important;word-break: normal !important;" class=""><span style="max- 100%;color: rgb(83, 78, 78);letter-spacing: 2px;font-size: 16px;box-sizing: border-box !important;overflow-wrap: break-word !important;word-break: normal !important;"></span><br></p></section><section class="" mpa-from-tpl="t"><p style="max- 100%;min-height: 1em;letter-spacing: 2px;margin-left: 16px;margin-right: 16px;line-height: 1.75em;box-sizing: border-box !important;overflow-wrap: break-word !important;word-break: normal !important;" class=""><span style="max- 100%;color: rgb(83, 78, 78);letter-spacing: 2px;font-size: 16px;box-sizing: border-box !important;overflow-wrap: break-word !important;word-break: normal !important;">OK,接下来我们可以创建订单的新增命令了。</span></p><p style="max- 100%;min-height: 1em;letter-spacing: 2px;margin-left: 16px;margin-right: 16px;line-height: 1.75em;box-sizing: border-box !important;overflow-wrap: break-word !important;word-break: normal !important;" class=""><span style="max- 100%;color: rgb(83, 78, 78);letter-spacing: 2px;font-size: 16px;box-sizing: border-box !important;overflow-wrap: break-word !important;word-break: normal !important;"><br></span></p><section data-mpa-preserve-tpl-color="t" data-mpa-template="t" class="" mpa-preserve="t" mpa-from-tpl="t" style="margin-left: 0.5em;margin-right: 0.5em;"><pre style="margin:0;padding:0;border-radius:none;background:none;"><code style="border-radius: 4px;font-size: 0.85em;margin: 0px 0.15em;background: rgb(40, 44, 52);display: block;padding: 5.95px;overflow-x: auto;white-space: nowrap;" class="hljs java"><span style="font-size: 14px;"><span class="" style="color: rgb(97, 174, 238);background: rgba(0, 0, 0, 0);display: inline; 65px;text-decoration: none solid rgb(97, 174, 238);font-weight: 400;font-style: normal;"><span class="hljs-meta">@Component</span></span><br mpa-from-tpl="t"><span class="" style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline; 39px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;"><span class="hljs-meta">public</span></span> <span class="" style="color: rgb(171, 178, 191);background: rgba(0, 0, 0, 0);display: inline; 406px;text-decoration: none solid rgb(171, 178, 191);font-weight: 400;font-style: normal;"><span class="" style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline; 33px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;"><span class="hljs-class"><span class="hljs-keyword">class</span></span></span><span class="hljs-class"> </span><span class="" style="color: rgb(230, 192, 123);background: rgba(0, 0, 0, 0);display: inline; 118px;text-decoration: none solid rgb(230, 192, 123);font-weight: 400;font-style: normal;"><span class="hljs-class"><span class="hljs-title">CreateOrderCommand</span></span></span><span class="hljs-class"> </span><span class="" style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline; 66px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;"><span class="hljs-class"><span class="hljs-keyword">implements</span></span></span><span class="hljs-class"> </span><span class="" style="color: rgb(230, 192, 123);background: rgba(0, 0, 0, 0);display: inline; 46px;text-decoration: none solid rgb(230, 192, 123);font-weight: 400;font-style: normal;"><span class="hljs-class"><span class="hljs-title">Command</span></span></span><span class="hljs-class">&lt;</span><span class="" style="color: rgb(230, 192, 123);background: rgba(0, 0, 0, 0);display: inline; 104px;text-decoration: none solid rgb(230, 192, 123);font-weight: 400;font-style: normal;"><span class="hljs-class"><span class="hljs-title">CreateOrderModel</span></span></span><span class="hljs-class">&gt; </span></span><span style="color: rgb(171, 178, 191);">{</span><br mpa-from-tpl="t"><br mpa-from-tpl="t"> <span class="" style="color: rgb(97, 174, 238);background: rgba(0, 0, 0, 0);display: inline; 59px;text-decoration: none solid rgb(97, 174, 238);font-weight: 400;font-style: normal;">&nbsp; &nbsp; <span class="hljs-meta">@Override</span></span><br mpa-from-tpl="t"> <span class="" style="background: rgba(0, 0, 0, 0);display: inline; 327px;text-decoration: none solid rgb(171, 178, 191);font-weight: 400;font-style: normal;"><span class="" style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline; 39px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">&nbsp; &nbsp; <span class="hljs-function"><span class="hljs-keyword">public</span></span></span><span class="hljs-function"> </span><span class="" style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline; 26px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;"><span class="hljs-function">Object</span></span><span class="" style="background: rgba(0, 0, 0, 0);display: inline; 26px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;color: rgb(171, 178, 191);"><span class="hljs-function">&nbsp;</span></span><span class="" style="color: rgb(97, 174, 238);background: rgba(0, 0, 0, 0);display: inline; 46px;text-decoration: none solid rgb(97, 174, 238);font-weight: 400;font-style: normal;"><span class="hljs-function"><span class="hljs-title">execute</span></span></span><span class="" style="color: rgb(171, 178, 191);background: rgba(0, 0, 0, 0);display: inline; 196px;text-decoration: none solid rgb(171, 178, 191);font-weight: 400;font-style: normal;"><span class="hljs-function"><span class="hljs-params">(CreateOrderModel model)</span></span></span><span class="hljs-function"> </span></span><span style="color: rgb(171, 178, 191);">{</span><br mpa-from-tpl="t"> <span class="" style="color: rgb(92, 99, 112);background: rgba(0, 0, 0, 0);display: inline; 79px;text-decoration: none solid rgb(92, 99, 112);font-weight: 400;font-style: italic;">&nbsp; &nbsp; &nbsp; &nbsp; <span class="hljs-comment">// 具体的逻辑</span></span><br mpa-from-tpl="t"><span style="color: rgb(171, 178, 191);"><span class="hljs-comment">&nbsp; &nbsp; }</span></span><br mpa-from-tpl="t"><span style="color: rgb(171, 178, 191);"><span class="hljs-comment">}</span></span></span></code></pre></section><p style="max- 100%;min-height: 1em;letter-spacing: 2px;margin-left: 16px;margin-right: 16px;line-height: 1.75em;box-sizing: border-box !important;overflow-wrap: break-word !important;word-break: normal !important;" class=""><span style="max- 100%;color: rgb(83, 78, 78);letter-spacing: 2px;font-size: 16px;box-sizing: border-box !important;overflow-wrap: break-word !important;word-break: normal !important;"></span><br></p></section><section class="" mpa-from-tpl="t"><p style="max- 100%;min-height: 1em;letter-spacing: 2px;margin-left: 16px;margin-right: 16px;line-height: 1.75em;box-sizing: border-box !important;overflow-wrap: break-word !important;word-break: normal !important;" class=""><span style="max- 100%;color: rgb(83, 78, 78);letter-spacing: 2px;font-size: 16px;box-sizing: border-box !important;overflow-wrap: break-word !important;word-break: normal !important;">到这里,我们写好了具体的创建订单命令的逻辑,那么该命令需要放到 CommandBus 中去执行,所以我们要写这个 CommandBus。</span></p><p style="max- 100%;min-height: 1em;letter-spacing: 2px;margin-left: 16px;margin-right: 16px;line-height: 1.75em;box-sizing: border-box !important;overflow-wrap: break-word !important;word-break: normal !important;" class=""><span style="max- 100%;color: rgb(83, 78, 78);letter-spacing: 2px;font-size: 16px;box-sizing: border-box !important;overflow-wrap: break-word !important;word-break: normal !important;"><br></span></p><section data-mpa-preserve-tpl-color="t" data-mpa-template="t" class="" mpa-preserve="t" mpa-from-tpl="t" style="margin-left: 0.5em;margin-right: 0.5em;"><pre style="margin:0;padding:0;border-radius:none;background:none;"><code style="border-radius: 4px;font-size: 0.85em;margin: 0px 0.15em;background: rgb(40, 44, 52);color: rgb(171, 178, 191);display: block;padding: 5.95px;overflow-x: auto;white-space: nowrap;" class="hljs ruby"><span class="" style="color: rgb(97, 174, 238);background: rgba(0, 0, 0, 0);display: inline; 65px;text-decoration: none solid rgb(97, 174, 238);font-weight: 400;font-style: normal;">@Component</span><br mpa-from-tpl="t"><span class="" style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline; 39px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">public</span> <span class="" style="color: rgb(171, 178, 191);background: rgba(0, 0, 0, 0);display: inline; 111px;text-decoration: none solid rgb(171, 178, 191);font-weight: 400;font-style: normal;"><span class="" style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline; 33px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;"><span class="hljs-class"><span class="hljs-keyword">class</span></span></span><span class="hljs-class"> </span><span class="" style="color: rgb(230, 192, 123);background: rgba(0, 0, 0, 0);display: inline; 66px;text-decoration: none solid rgb(230, 192, 123);font-weight: 400;font-style: normal;"><span class="hljs-class"><span class="hljs-title">CommandBus</span></span></span><span class="hljs-class"> </span></span><span class="hljs-class">{</span><br mpa-from-tpl="t"><span class="hljs-class"> </span><span class="" style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline; 39px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;"><span class="hljs-class">&nbsp; &nbsp; <span class="hljs-title">public</span></span></span><span class="hljs-class"> &lt;T&gt; </span><span class="" style="color: rgb(171, 178, 191);background: rgba(0, 0, 0, 0);display: inline; 255px;text-decoration: none solid rgb(171, 178, 191);font-weight: 400;font-style: normal;"><span class="" style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline; 26px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;"><span class="hljs-class"><span class="hljs-title">Object</span></span></span><span class="hljs-class">&nbsp;</span><span class="" style="color: rgb(97, 174, 238);background: rgba(0, 0, 0, 0);display: inline; 53px;text-decoration: none solid rgb(97, 174, 238);font-weight: 400;font-style: normal;"><span class="hljs-class"><span class="hljs-title">dispatch</span></span></span><span class="" style="color: rgb(171, 178, 191);background: rgba(0, 0, 0, 0);display: inline; 163px;text-decoration: none solid rgb(171, 178, 191);font-weight: 400;font-style: normal;"><span class="hljs-class">(<span class="hljs-title">Command</span>&lt;T&gt; <span class="hljs-title">cmd</span>, <span class="hljs-title">T</span> <span class="hljs-title">model</span>)</span></span><span class="hljs-class"> </span></span><span class="hljs-class">{</span><br mpa-from-tpl="t"><span class="hljs-class"> </span><span class="" style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline; 39px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;"><span class="hljs-class">&nbsp; &nbsp; &nbsp; &nbsp; <span class="hljs-title">return</span></span></span><span class="hljs-class"> <span class="hljs-title">cmd</span>.<span class="hljs-title">excute</span>(<span class="hljs-title">model</span>);</span><br mpa-from-tpl="t">&nbsp; &nbsp; }<br mpa-from-tpl="t">}</code></pre></section><p style="max- 100%;min-height: 1em;letter-spacing: 2px;margin-left: 16px;margin-right: 16px;line-height: 1.75em;box-sizing: border-box !important;overflow-wrap: break-word !important;word-break: normal !important;" class=""><span style="max- 100%;color: rgb(83, 78, 78);letter-spacing: 2px;font-size: 16px;box-sizing: border-box !important;overflow-wrap: break-word !important;word-break: normal !important;"></span></p></section><section class="" mpa-from-tpl="t"><p style="max- 100%;min-height: 1em;letter-spacing: 2px;margin-left: 16px;margin-right: 16px;line-height: 1.75em;box-sizing: border-box !important;overflow-wrap: break-word !important;word-break: normal !important;" class=""><span style="max- 100%;color: rgb(83, 78, 78);letter-spacing: 2px;font-size: 16px;box-sizing: border-box !important;overflow-wrap: break-word !important;word-break: normal !important;">可能大家会看着有点晕,甚至有点绕,没关系,我解释一下:这个 dispatch 方法就相当于分发执行,内部根据传入的具体 Command 以及对应的 model,去执行该 Command 实现的逻辑。</span></p><p style="max- 100%;min-height: 1em;letter-spacing: 2px;margin-left: 16px;margin-right: 16px;line-height: 1.75em;box-sizing: border-box !important;overflow-wrap: break-word !important;word-break: normal !important;" class=""><span style="max- 100%;color: rgb(83, 78, 78);letter-spacing: 2px;font-size: 16px;box-sizing: border-box !important;overflow-wrap: break-word !important;word-break: normal !important;"><br></span></p><p style="max- 100%;min-height: 1em;letter-spacing: 2px;margin-left: 16px;margin-right: 16px;line-height: 1.75em;box-sizing: border-box !important;overflow-wrap: break-word !important;word-break: normal !important;" class=""><span style="max- 100%;color: rgb(83, 78, 78);letter-spacing: 2px;font-size: 16px;box-sizing: border-box !important;overflow-wrap: break-word !important;word-break: normal !important;">好了,那我们在熟悉的 Controller 层该如何去调用呢?很简单,如下:</span></p><p style="max- 100%;min-height: 1em;letter-spacing: 2px;margin-left: 16px;margin-right: 16px;line-height: 1.75em;box-sizing: border-box !important;overflow-wrap: break-word !important;word-break: normal !important;" class=""><span style="max- 100%;color: rgb(83, 78, 78);letter-spacing: 2px;font-size: 16px;box-sizing: border-box !important;overflow-wrap: break-word !important;word-break: normal !important;"><br></span></p><section data-mpa-preserve-tpl-color="t" data-mpa-template="t" class="" mpa-preserve="t" mpa-from-tpl="t" style="margin-left: 0.5em;margin-right: 0.5em;"><pre style="margin:0;padding:0;border-radius:none;background:none;"><code style="border-radius: 4px;font-size: 0.85em;margin: 0px 0.15em;background: rgb(40, 44, 52);color: rgb(171, 178, 191);display: block;padding: 5.95px;overflow-x: auto;white-space: nowrap;" class="hljs less"><span class="" style="color: rgb(97, 174, 238);background: rgba(0, 0, 0, 0);display: inline; 98px;text-decoration: none solid rgb(97, 174, 238);font-weight: 400;font-style: normal;"><span class="hljs-variable">@RestController</span></span><br mpa-from-tpl="t"><span class="" style="color: rgb(97, 174, 238);background: rgba(0, 0, 0, 0);display: inline; 98px;text-decoration: none solid rgb(97, 174, 238);font-weight: 400;font-style: normal;"><span class="hljs-variable">@RequestMapping</span></span>(value = <span class="" style="color: rgb(152, 195, 121);background: rgba(0, 0, 0, 0);display: inline; 52px;text-decoration: none solid rgb(152, 195, 121);font-weight: 400;font-style: normal;"><span class="hljs-string">"/order"</span></span>)<br mpa-from-tpl="t"><span class="" style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline; 39px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">public</span> <span class="" style="color: rgb(171, 178, 191);background: rgba(0, 0, 0, 0);display: inline; 144px;text-decoration: none solid rgb(171, 178, 191);font-weight: 400;font-style: normal;"><span class="" style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline; 33px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">class</span> <span class="" style="color: rgb(230, 192, 123);background: rgba(0, 0, 0, 0);display: inline; 98px;text-decoration: none solid rgb(230, 192, 123);font-weight: 400;font-style: normal;">OrderController</span> </span>{<br mpa-from-tpl="t"><br mpa-from-tpl="t"> <span class="" style="color: rgb(97, 174, 238);background: rgba(0, 0, 0, 0);display: inline; 59px;text-decoration: none solid rgb(97, 174, 238);font-weight: 400;font-style: normal;">&nbsp; &nbsp; <span class="hljs-variable">@Resource</span></span><br mpa-from-tpl="t"> <span class="" style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline; 46px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">&nbsp; &nbsp; private</span> GetOrderInfoService getOrderInfoService;<br mpa-from-tpl="t"> <span class="" style="color: rgb(97, 174, 238);background: rgba(0, 0, 0, 0);display: inline; 59px;text-decoration: none solid rgb(97, 174, 238);font-weight: 400;font-style: normal;">&nbsp; &nbsp; <span class="hljs-variable">@Resource</span></span><br mpa-from-tpl="t"> <span class="" style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline; 46px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">&nbsp; &nbsp; private</span> CreateOrderCommand createOrderCommand;<br mpa-from-tpl="t"> <span class="" style="color: rgb(97, 174, 238);background: rgba(0, 0, 0, 0);display: inline; 59px;text-decoration: none solid rgb(97, 174, 238);font-weight: 400;font-style: normal;">&nbsp; &nbsp; <span class="hljs-variable">@Resource</span></span><br mpa-from-tpl="t"> <span class="" style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline; 46px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">&nbsp; &nbsp; private</span> CommandBus commandBus;<br mpa-from-tpl="t"><br mpa-from-tpl="t"> <span class="" style="color: rgb(97, 174, 238);background: rgba(0, 0, 0, 0);display: inline; 78px;text-decoration: none solid rgb(97, 174, 238);font-weight: 400;font-style: normal;">&nbsp; &nbsp; <span class="hljs-variable">@PostMapping</span></span>(value = <span class="" style="color: rgb(152, 195, 121);background: rgba(0, 0, 0, 0);display: inline; 66px;text-decoration: none solid rgb(152, 195, 121);font-weight: 400;font-style: normal;"><span class="hljs-string">"/getInfo"</span></span>)<br mpa-from-tpl="t"> <span class="" style="color: rgb(171, 178, 191);background: rgba(0, 0, 0, 0);display: inline; 340px;text-decoration: none solid rgb(171, 178, 191);font-weight: 400;font-style: normal;"><span class="" style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline; 39px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">&nbsp; &nbsp; public</span> Object <span class="" style="color: rgb(97, 174, 238);background: rgba(0, 0, 0, 0);display: inline; 78px;text-decoration: none solid rgb(97, 174, 238);font-weight: 400;font-style: normal;">getOrderInfo</span><span class="" style="color: rgb(171, 178, 191);background: rgba(0, 0, 0, 0);display: inline; 163px;text-decoration: none solid rgb(171, 178, 191);font-weight: 400;font-style: normal;">(GetOrderInfoModel model)</span> </span>{<br mpa-from-tpl="t"> <span class="" style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline; 39px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">&nbsp; &nbsp; &nbsp; &nbsp; <span class="hljs-selector-tag">return</span></span> <span class="hljs-selector-tag">getOrderInfoService</span><span class="hljs-selector-class">.getOrderInfos</span>(model);<br mpa-from-tpl="t">&nbsp; &nbsp; }<br mpa-from-tpl="t"><br mpa-from-tpl="t"> <span class="" style="color: rgb(97, 174, 238);background: rgba(0, 0, 0, 0);display: inline; 78px;text-decoration: none solid rgb(97, 174, 238);font-weight: 400;font-style: normal;">&nbsp; &nbsp; @<span class="hljs-selector-tag">PostMapping</span></span>(value = <span class="" style="color: rgb(152, 195, 121);background: rgba(0, 0, 0, 0);display: inline; 52px;text-decoration: none solid rgb(152, 195, 121);font-weight: 400;font-style: normal;"><span class="hljs-string">"/creat"</span></span>)<br mpa-from-tpl="t"> <span class="" style="color: rgb(171, 178, 191);background: rgba(0, 0, 0, 0);display: inline; 354px;text-decoration: none solid rgb(171, 178, 191);font-weight: 400;font-style: normal;"><span class="" style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline; 39px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">&nbsp; &nbsp; <span class="hljs-selector-tag">public</span></span> <span class="hljs-selector-tag">Object</span> <span class="" style="color: rgb(97, 174, 238);background: rgba(0, 0, 0, 0);display: inline; 98px;text-decoration: none solid rgb(97, 174, 238);font-weight: 400;font-style: normal;"><span class="hljs-selector-tag">createOrderInfo</span></span><span class="" style="color: rgb(171, 178, 191);background: rgba(0, 0, 0, 0);display: inline; 158px;text-decoration: none solid rgb(171, 178, 191);font-weight: 400;font-style: normal;">(CreateOrderModel model)</span> </span>{<br mpa-from-tpl="t"> <span class="" style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline; 39px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">&nbsp; &nbsp; &nbsp; &nbsp; <span class="hljs-selector-tag">return</span></span> <span class="hljs-selector-tag">commandBus</span><span class="hljs-selector-class">.dispatch</span>(createOrderCommand, model);<br mpa-from-tpl="t">&nbsp; &nbsp; }<br mpa-from-tpl="t">}</code></pre></section><p style="max- 100%;min-height: 1em;letter-spacing: 2px;margin-left: 16px;margin-right: 16px;line-height: 1.75em;box-sizing: border-box !important;overflow-wrap: break-word !important;word-break: normal !important;" class=""><span style="max- 100%;color: rgb(83, 78, 78);letter-spacing: 2px;font-size: 16px;box-sizing: border-box !important;overflow-wrap: break-word !important;word-break: normal !important;"></span></p></section><section class="" mpa-from-tpl="t"><p style="max- 100%;min-height: 1em;letter-spacing: 2px;margin-left: 16px;margin-right: 16px;line-height: 1.75em;box-sizing: border-box !important;overflow-wrap: break-word !important;word-break: normal !important;" class=""><span style="max- 100%;color: rgb(83, 78, 78);letter-spacing: 2px;font-size: 16px;box-sizing: border-box !important;overflow-wrap: break-word !important;word-break: normal !important;">我还写了一个获取订单信息的接口,大家有没有发现,查询和插入是不同的方式,插入走的是 CommandBus 分发到 CreateOrderCommand 去执行,而查询则是直接走 service 层去查。这就是 CQRS 模式。</span></p><p style="max- 100%;min-height: 1em;letter-spacing: 2px;margin-left: 16px;margin-right: 16px;line-height: 1.75em;box-sizing: border-box !important;overflow-wrap: break-word !important;word-break: normal !important;" class=""><span style="max- 100%;color: rgb(83, 78, 78);letter-spacing: 2px;font-size: 16px;box-sizing: border-box !important;overflow-wrap: break-word !important;word-break: normal !important;"><br></span></p><p style="max- 100%;min-height: 1em;letter-spacing: 2px;margin-left: 16px;margin-right: 16px;line-height: 1.75em;box-sizing: border-box !important;overflow-wrap: break-word !important;word-break: normal !important;" class=""><span style="max- 100%;color: rgb(83, 78, 78);letter-spacing: 2px;font-size: 16px;box-sizing: border-box !important;overflow-wrap: break-word !important;word-break: normal !important;">当然了,当命令越来越多的时候,也可以将 CommandBus 抽象出接口,可以根据业务需求,实现多个不同的 CommandBus 来分发命令。</span></p><p style="max- 100%;min-height: 1em;letter-spacing: 2px;margin-left: 16px;margin-right: 16px;line-height: 1.75em;box-sizing: border-box !important;overflow-wrap: break-word !important;word-break: normal !important;" class=""><span style="max- 100%;color: rgb(83, 78, 78);letter-spacing: 2px;font-size: 16px;box-sizing: border-box !important;overflow-wrap: break-word !important;word-break: normal !important;"><br></span></p><p style="max- 100%;min-height: 1em;letter-spacing: 2px;margin-left: 16px;margin-right: 16px;line-height: 1.75em;box-sizing: border-box !important;overflow-wrap: break-word !important;word-break: normal !important;" class=""><span style="color:#534e4e;"><span style="font-size: 16px;">除此之外,CQRS 还可以用在任务调度模块中,不同的任务可以包含不同的 Command,实际中运用是非常广泛的。</span></span></p><p style="max- 100%;min-height: 1em;letter-spacing: 2px;margin-left: 16px;margin-right: 16px;line-height: 1.75em;box-sizing: border-box !important;overflow-wrap: break-word !important;word-break: normal !important;" class=""><span style="color:#534e4e;"><span style="font-size: 16px;"><br></span></span></p><p style="max- 100%;min-height: 1em;letter-spacing: 2px;margin-left: 16px;margin-right: 16px;line-height: 1.75em;box-sizing: border-box !important;overflow-wrap: break-word !important;word-break: normal !important;" class=""><em><span style="color: rgb(61, 167, 66);"><strong><span style="font-size: 16px;">5</span></strong></span></em><span style="color: rgb(61, 167, 66);"><strong><span style="font-size: 16px;">. 总结</span></strong></span></p><p style="max- 100%;min-height: 1em;letter-spacing: 2px;margin-left: 16px;margin-right: 16px;line-height: 1.75em;box-sizing: border-box !important;overflow-wrap: break-word !important;word-break: normal !important;" class=""><span style="color:#534e4e;"><span style="font-size: 16px;"><br></span></span></p><p style="max- 100%;min-height: 1em;letter-spacing: 2px;margin-left: 16px;margin-right: 16px;line-height: 1.75em;box-sizing: border-box !important;overflow-wrap: break-word !important;word-break: normal !important;" class=""><span style="color:#534e4e;"><span style="font-size: 16px;">CQRS 是一种思想很简单清晰的设计模式,他通过在业务上分离操作和查询来使得系统具有更好的可扩展性及性能,使得能够对系统的不同部分进行扩展和优化。在 CQRS 中,所有的涉及到对 DB 的操作都是通过发送 Command,然后特定的 Command 触发对应事件来完成操作,也可以做成异步的,主要看业务上的需求了。</span></span></p><p style="max- 100%;min-height: 1em;letter-spacing: 2px;margin-left: 16px;margin-right: 16px;line-height: 1.75em;box-sizing: border-box !important;overflow-wrap: break-word !important;word-break: normal !important;" class=""><span style="color:#534e4e;"><span style="font-size: 16px;"><br></span></span></p><p style="max- 100%;min-height: 1em;letter-spacing: 2px;margin-left: 16px;margin-right: 16px;line-height: 1.75em;box-sizing: border-box !important;overflow-wrap: break-word !important;word-break: normal !important;" class=""><span style="color:#534e4e;"><span style="font-size: 16px;">CQRS 虽然在思想上简单,但是实现上相对来说复杂些,也涉及到 DDD 的一些概念了,当然了,这篇文章主要是介绍以及演示 CQRS 模式的基本实践,更多知识需要大家再深入的去学习。</span></span></p><p style="max- 100%;min-height: 1em;letter-spacing: 2px;margin-left: 16px;margin-right: 16px;line-height: 1.75em;box-sizing: border-box !important;overflow-wrap: break-word !important;word-break: normal !important;" class=""><span style="color:#534e4e;"><span style="font-size: 16px;"><br></span></span></p><p style="max- 100%;min-height: 1em;letter-spacing: 2px;margin-left: 16px;margin-right: 16px;line-height: 1.75em;box-sizing: border-box !important;overflow-wrap: break-word !important;word-break: normal !important;" class=""><span style="color:#534e4e;"><span style="font-size: 16px;">最后,希望阅读完本文,能对你有所帮助。</span></span></p><p style="max- 100%;min-height: 1em;letter-spacing: 2px;margin-left: 16px;margin-right: 16px;line-height: 1.75em;box-sizing: border-box !important;overflow-wrap: break-word !important;word-break: normal !important;" class=""><span style="color:#534e4e;"><span style="font-size: 16px;"><br></span></span></p><p style="max- 100%;min-height: 1em;letter-spacing: 2px;margin-left: 16px;margin-right: 16px;line-height: 1.75em;box-sizing: border-box !important;overflow-wrap: break-word !important;word-break: normal !important;" class=""><span style="color:#534e4e;"><span style="font-size: 16px;">参考文献:</span></span></p><p style="max- 100%;min-height: 1em;letter-spacing: 2px;margin-left: 16px;margin-right: 16px;line-height: 1.75em;box-sizing: border-box !important;overflow-wrap: break-word !important;word-break: normal !important;" class=""><span style="font-size: 13px;color: rgb(178, 178, 178);">1.https://msdn.microsoft.com/magazine/mt703431</span></p><p style="max- 100%;min-height: 1em;letter-spacing: 2px;margin-left: 16px;margin-right: 16px;line-height: 1.75em;box-sizing: border-box !important;overflow-wrap: break-word !important;word-break: normal !important;" class=""><span style="font-size: 13px;color: rgb(178, 178, 178);">2.https://blog.csdn.net/rocketluoqq/article/details/81434871<br></span></p><p style="max- 100%;min-height: 1em;letter-spacing: 2px;margin-left: 16px;margin-right: 16px;line-height: 1.75em;box-sizing: border-box !important;overflow-wrap: break-word !important;word-break: normal !important;" class=""><span style="font-size: 13px;color: rgb(178, 178, 178);">3.https://docs.microsoft.com/en-us/previous-versions/msp-n-p/dn589792(v=pandp.10)<br></span></p><p style="max- 100%;min-height: 1em;letter-spacing: 2px;margin-left: 16px;margin-right: 16px;line-height: 1.75em;box-sizing: border-box !important;overflow-wrap: break-word !important;word-break: normal !important;" class=""><span style="font-size: 13px;color: rgb(178, 178, 178);">4.https://www.cnblogs.com/yangecnu/p/Introduction-CQRS.html</span></p><p style="max- 100%;min-height: 1em;letter-spacing: 2px;margin-left: 16px;margin-right: 16px;line-height: 1.75em;box-sizing: border-box !important;overflow-wrap: break-word !important;word-break: normal !important;" class=""><span style="font-size: 13px;color: rgb(178, 178, 178);"><br></span></p></section><section class="" mpa-from-tpl="t"><section data-id="94155" mpa-from-tpl="t"></section></section><p style="margin: 0px;padding: 0px;max- 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;clear: both;min-height: 1em;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: 0.544px;orphans: 2;text-indent: 0px;text-transform: none;white-space: normal;-webkit-text-stroke- 0px;text-decoration-style: initial;text-decoration-color: initial;color: rgb(62, 62, 62);font-size: 16px;background-color: rgb(255, 255, 255);text-align: center;word-spacing: 2px;font-family: Avenir, -apple-system-font, 微软雅黑, sans-serif;widows: 1;line-height: 28.4444px;"><br style="margin: 0px;padding: 0px;max- 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></p><p style="margin: 0px;padding: 0px;max- 100%;min-height: 1em;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: 0.544px;orphans: 2;text-indent: 0px;text-transform: none;white-space: normal;-webkit-text-stroke- 0px;text-decoration-style: initial;text-decoration-color: initial;color: rgb(62, 62, 62);font-size: 16px;background-color: rgb(255, 255, 255);text-align: right;word-spacing: 2px;font-family: Avenir, -apple-system-font, 微软雅黑, sans-serif;widows: 1;line-height: 28.4444px;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="margin: 0px;padding: 0px;max- 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;font-variant-numeric: normal;font-variant-east-asian: normal;letter-spacing: 0.544px;font-weight: 700;font-family: Optima-Regular, PingFangTC-light;font-size: 14px;">点赞是</span><span style="margin: 0px;padding: 0px;max- 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;font-variant-numeric: normal;font-variant-east-asian: normal;letter-spacing: 0.544px;font-weight: 700;font-family: Optima-Regular, PingFangTC-light;font-size: 14px;color: rgb(255, 0, 0);">最大的支持&nbsp;</span><img class="__bg_gif" data-ratio="1.764" data-src="https://mmbiz.qpic.cn/mmbiz_gif/ibsfLhQMgy09JhlUaCQZm4kXHBSlPxPOOpOcfiaNmJRjoem28z1x3CbXNG2eQNK8Tic1Yyf1WqKZ3VibvSicNtwcguQ/640?wx_fmt=gif" data-type="gif" data-w="250" style="margin: 0px; padding: 0px; max- 100%; font-variant-numeric: normal; font-variant-east-asian: normal; letter-spacing: 0.544px; font-size: 15px; font-weight: 700; font-family: Optima-Regular, PingFangTC-light; line-height: 27.2px; text-align: center; vertical-align: middle; box-sizing: border-box !important; overflow-wrap: break-word !important; visibility: visible !important;  19.7188px !important; height: 34.784px !important;" width="19.7188px" _width="19.7188px" src="data:image/gif;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVQImWNgYGBgAAAABQABh6FO1AAAAABJRU5ErkJggg==" data-order="2"></p>
    

    原文地址:https://mp.weixin.qq.com/s/LVbhRTiyn-gUXtwgeHS79A

  • 相关阅读:
    window10环境安装elasticsearch、中文分词器analysisik、Kibana
    通过Dapr实现一个简单的基于.net的微服务电商系统(十九)——分布式事务之Saga模式
    通过Dapr实现一个简单的基于.net的微服务电商系统(十八)——服务保护之多级缓存
    通过Dapr实现一个简单的基于.net的微服务电商系统(二十)——Saga框架实现思路分享
    浅谈.net core如何使用EFCore为一个上下文注类型注入多个实例用于连接主从数据库
    安卓 载入涂鸦失败(Load doodle failed) 百度地图无法使用
    Git的基础使用(一)
    后端处理重复请求
    SpringAOP拦截器
    trap '' TERM
  • 原文地址:https://www.cnblogs.com/jpfss/p/11471524.html
Copyright © 2020-2023  润新知