当前位置: 首页 > news >正文

百度做网站需要交钱吗广州和广州市注册公司区别

百度做网站需要交钱吗,广州和广州市注册公司区别,如何做短信验证码网站,小程序模板购买引言 最近准备给自己之前写的项目做重构#xff0c;这是一个单体架构的小项目#xff0c;后端采用的是最常见的三层架构。因为项目比较简单#xff0c;其实采用三层架构就完全够了。但是呢#xff0c;小编最近在做DDD架构的项目#xff0c;于是就先拿之前写的一个老项目试…引言 最近准备给自己之前写的项目做重构这是一个单体架构的小项目后端采用的是最常见的三层架构。因为项目比较简单其实采用三层架构就完全够了。但是呢小编最近在做DDD架构的项目于是就先拿之前写的一个老项目试试手。在重构的过程中对DDD设计思想也有一些体会。于是我就写了这一个系列的博客来记录我从学习DDD架构思想再到将这种架构思想投入到实践的过程。 这一篇博客主要是先学习一下DDD架构思想也就是先入个门我会先介绍DDD架构思想中的一些概念然后再介绍根据DDD架构思想所设计出来的常见的架构分层最后就是入门实战根据上面介绍的架构分层搭建一个单体架构项目。 DDD分层架构 前言介绍 DDDDomain-Driven Design 领域驱动设计是由Eric Evans最先提出目的是对软件所涉及到的领域进行建模以应对系统规模过大时引起的软件复杂性的问题。整个过程大概是这样的开发团队和领域专家一起通过 通用语言(Ubiquitous Language)去理解和消化领域知识从领域知识中提取和划分为一个一个的子领域核心子域通用子域支撑子域并在子领域上建立模型再重复以上步骤这样周而复始构建出一套符合当前领域的模型。 开发目标 依靠领域驱动设计的设计思想通过事件风暴建立领域模型合理划分领域逻辑和物理边界建立领域对象及服务矩阵和服务架构图定义符合DDD分层架构思想的代码结构模型保证业务模型与代码模型的一致性。通过上述设计思想、方法和过程指导团队按照DDD设计思想完成微服务设计和开发。 高内聚低耦合通过将相关的领域概念和业务逻辑组织在一起实现高内聚。同时通过定义明确的上下文边界和良好的模块划分降低模块之间的依赖关系实现低耦合。这样可以提高代码的可读性、可维护性和可扩展性。 清晰的领域模型通过充血模型的方式将业务逻辑封装在领域对象中使领域模型具备自己的责任和行为。领域模型应该能够准确地反映业务需求对业务规则进行验证并与领域专家的语言保持一致。这样可以提高开发人员对业务的理解并减少误解和沟通成本。 易于扩展和演化项目结构应该具有良好的可扩展性能够支持未来的需求变更和功能扩展。通过使用聚合、领域事件等概念将系统分解为更小的、独立的组件可以降低变更的影响范围提高系统的可维护性。同时采用领域事件和事件驱动的方式可以更好地应对业务规则的变化和演化。 可测试性良好的项目结构应该支持单元测试、集成测试和端到端测试等不同层次的测试。通过将业务逻辑封装在领域对象中可以更容易地编写和执行单元测试并验证系统的功能和正确性。此外通过使用依赖注入等技术可以更方便地进行模块的替换和模拟提高测试的灵活性和可靠性。 基本的服务分层 这里看不懂没关系看完下面的内容再来看这里就会理解不少了。 基础概念 领域 领域就是用来确定范围的范围即边界这也是 DDD 在设计中不断强调边界的原因。简言之DDD 的领域就是这个边界内要解决的业务问题域。 领域可以进一步划分为子领域。我们把划分出来的多个子领域称为子域每个子域对应一个更小的问题域或更小的业务范围。领域可以拆分为多个子领域。一个领域相当于一个问题域领域拆分为子域的过程就是大问题拆分为小问题的过程。 其实很好理解DDD 的研究方法与自然科学的研究方法类似。当人们在自然科学研究中遇到复杂问题时通常的做法就是将问题一步一步地细分再针对细分出来的问题域逐个深入研究探索和建立所有子域的知识体系。当所有问题子域完成研究时我们就建立了全部领域的完整知识体系了 在领域不断划分的过程中领域会细分为不同的子域子域可以根据自身重要性和功能属性划分为三类子域它们分别是核心域、通用域和支撑域。 那么三类子域的作用分别是什么 核心域 核心域是指系统中最重要、最核心的业务领域它包含了组织的竞争优势所在也是系统的关键价值所在。在核心域中包含了核心业务逻辑和最关键的业务规则这些规则对系统的成功运行至关重要。在设计和开发过程中核心域通常是最需要投入精力和资源来进行建模和实现的部分。核心域通常是系统的重点关注对象是系统的灵魂所在。 通用域 通用域是指那些在多个系统中都普遍存在的通用业务领域它们通常不会直接带来组织的竞争优势但是对系统整体的功能提供了一定的支持。通用域中包含了通用的业务逻辑和规则这些规则在多个系统中都可能会有类似的实现。通用域通常是可以被复用的部分可以在不同的系统中得到共享和重用。 支撑域 支撑域是指那些对核心域和通用域提供支撑和服务的业务领域。支撑域通常包括了各种基础设施、技术支持、通用功能等它们并不直接参与核心业务流程但是对核心业务和通用业务的实现提供了必要的支持。支撑域为核心域和通用域提供了必要的基础设施和支持使它们能够顺利地实现业务目标。 领域事件 领域事件Domain Event是领域驱动设计中的一个重要概念用于表示在领域模型中发生的有意义的事件。它们通常代表着领域中的一些重要状态变化或业务行为可以被其他领域对象订阅和响应。 举例来说的话领域事件可以是业务流程的一个步骤比如投保业务缴费完成后触发投保单转保单的动作也可能是定时批处理过程中发生的事件比如批处理生成季缴保费通知单触发发送缴费邮件通知操作或者一个事件发生后触发的后续动作比如密码连续输错三次触发锁定账户的动作。 通过上面的例子我们可以看出通过领域事件驱动的异步化机制可以推动业务流程和数据在各个不同微服务之间的流转实现微服务的解耦减轻微服务之间服务调用的压力提升用户体验。 一个完整的领域事件 事件发布 事件存储 事件分发 事件处理。 事件发布构建一个事件需要唯一标识然后发布 事件存储发布事件前需要存储因为接收后的事件也会存储可用于重试或对账等就是每次执行一次具体的操作时把行为记录下来执行持久化。 事件分发服务内的应用服务或者领域服务直接发布给订阅者服务外需要借助消息中间件比如KafkaRabbitMQ等支持同步或者异步。 事件处理先将事件存储然后再处理。 当然了实际开发中事件存储和事件处理不是必须的。 因此实现方案发布订阅模式分为跨上下文kafkaRocketMq和上下文内spring事件Guava Event Bus的领域事件。 下面是一个领域事件的示例代码 // 领域事件类表示订单已创建的事件 public class OrderCreatedEvent {private final String orderId;private final String customerId;public OrderCreatedEvent(String orderId, String customerId) {this.orderId orderId;this.customerId customerId;}public String getOrderId() {return orderId;}public String getCustomerId() {return customerId;} }// 领域模型中的订单实体 public class Order {private String orderId;private String customerId;// 其他属性和方法省略// 创建订单的方法public void create(String orderId, String customerId) {// 执行订单创建的业务逻辑// 触发订单已创建的领域事件OrderCreatedEvent event new OrderCreatedEvent(orderId, customerId);DomainEventPublisher.publish(event);} }// 领域事件发布者 public class DomainEventPublisher {private static ListEventListener listeners new ArrayList();public static void publish(DomainEvent event) {for (EventListener listener : listeners) {listener.handleEvent(event);}}public static void subscribe(EventListener listener) {listeners.add(listener);} }// 领域事件监听器接口 public interface EventListener {void handleEvent(DomainEvent event); }// 订单创建事件的监听器 public class OrderCreatedEventListener implements EventListener {public void handleEvent(DomainEvent event) {if (event instanceof OrderCreatedEvent) {OrderCreatedEvent orderCreatedEvent (OrderCreatedEvent) event;// 处理订单已创建的逻辑例如发送邮件通知等System.out.println(订单已创建订单号 orderCreatedEvent.getOrderId());}} }// 在应用层配置和使用领域事件 public class Application {public static void main(String[] args) {// 创建订单实例Order order new Order();// 注册订单创建事件的监听器DomainEventPublisher.subscribe(new OrderCreatedEventListener());// 创建订单order.create(123456, 7890);} } 在上述示例中我定义了一个名为OrderCreatedEvent的领域事件类它表示订单已创建的事件并包含了订单ID和客户ID等信息。在订单实体的create方法中当订单创建成功时会触发一个OrderCreatedEvent的领域事件并通过DomainEventPublisher来发布事件。 DomainEventPublisher是领域事件的发布者它负责管理事件的订阅者并将事件分发给它们。在示例中我定义了一个OrderCreatedEventListener作为订单创建事件的监听器它会在接收到订单创建事件后执行相应的逻辑例如发送邮件通知等。 在应用层的Application类中我创建了一个订单实例并注册了订单创建事件的监听器。当我调用订单的create方法时订单创建事件会被发布和处理从而完成相应的业务逻辑。 这是一个简单的领域事件示例实际应用中领域事件可以更复杂并且可能会有多个事件和多个监听器。通过使用领域事件我们可以更好地解耦业务逻辑并且允许各个领域对象之间进行松散的协作。 限界上下文 我们可以将限界上下文拆解为两个词限界和上下文。限界就是领域的边界而上下文则是语义环境。通过领域的限界上下文我们就可以在统一的领域边界内用统一的语言进行交流简单来说限界上下文可以理解为语义环境。 综合一下我认为限界上下文的定义就是用来封装通用语言和领域对象提供上下文环境保证在领域之内的一些术语、业务相关对象等通用语言有一个确切的含义没有二义性。这个边界定义了模型的适用范围使团队所有成员能够明确地知道什么应该在模型中实现什么不应该在模型中实现。 下面我举一个例子 在一个明媚的早晨孩子起床问妈妈“今天应该穿几件衣服呀”妈妈回答“能穿多少就穿多少”那到底是穿多还是穿少呢 如果没有具体的语义环境还真不太好理解。但是如果你已经知道了这句话的语义环境比如是寒冬腊月或者是炎炎夏日那理解这句话的涵义就会很容易了。 所以语言离不开它的语义环境。 而业务的通用语言就有它的业务边界我们不大可能用一个简单的术语没有歧义地去描述一个复杂的业务领域。限界上下文就是用来细分领域从而定义通用语言所在的边界。 正如电商领域的商品一样商品在不同的阶段有不同的术语在销售阶段是商品而在运输阶段则变成了货物。同样的一个东西由于业务领域的不同赋予了这些术语不同的涵义和职责边界这个边界就可能会成为未来微服务设计的边界。看到这我想你应该非常清楚了领域边界就是通过限界上下文来定义的。 理论上限界上下文就是微服务的边界。我们将限界上下文内的领域模型映射到微服务就完成了从问题域到软件的解决方案。 可以说限界上下文是微服务设计和拆分的主要依据。在领域模型中如果不考虑技术异构、团队沟通等其它外部因素一个限界上下文理论上就可以设计为一个微服务。 贫血模型和充血模型 贫血模型贫血模型指的是将数据和行为分离将数据保存在对象中而将业务逻辑操作放在服务层或外部类中。贫血模型认为对象只是简单地保存数据不具备独立的行为和能力 。 贫血模型具有一堆属性和set get方法存在的问题就是通过pojo这个对象上看不出业务有哪些逻辑一个pojo可能被多个模块调用只能去上层各种各样的service来调用这样以后当梳理这个实体有什么业务只能一层一层去搜service也就是贫血失忆症不够面向对象。 充血模型充血模型指的是在领域模型中将业务逻辑封装在实体对象中实体对象不仅包含数据属性还包含操作和行为方法。充血模型认为领域模型应该是富有行为和能力的具有自己的责任和职责。 比如如下user用户有改密码改手机号修改登录失败次数等操作都内聚在这个user实体中每个实体的业务都是清晰的就是充血模型充血模型的内存计算会多一些内聚核心业务逻辑处理。 说白了就是不只是有贫血模型中setter getter方法还有其他的一些业务方法这才是面向对象的本质通过user实体就能看出有哪些业务存在。 充血模式代码示例 NoArgsConstructor Getter public class User extends AggregateLong, User {/*** 用户名*/private String userName;/*** 姓名*/private String realName;/*** 手机号*/private String phone;/*** 密码*/private String password;/*** 锁定结束时间*/private Date lockEndTime;/*** 登录失败次数*/private Integer failNumber;/*** 用户角色*/private ListRole roles;/*** 部门*/private Department department;/*** 用户状态*/private UserStatus userStatus;/*** 用户地址*/private Address address;public User(String userName, String phone, String password) {saveUserName(userName);savePhone(phone);savePassword(password);}/*** 保存用户名* param userName*/private void saveUserName(String userName) {if (StringUtils.isBlank(userName)){Assert.throwException(用户名不能为空);}this.userName userName;}/*** 保存电话* param phone*/private void savePhone(String phone) {if (StringUtils.isBlank(phone)){Assert.throwException(电话不能为空);}this.phone phone;}/*** 保存密码* param password*/private void savePassword(String password) {if (StringUtils.isBlank(password)){Assert.throwException(密码不能为空);}this.password password;}/*** 保存用户地址* param province* param city* param region*/public void saveAddress(String province,String city,String region){this.address new Address(province,city,region);}/*** 保存用户角色* param roleList*/public void saveRole(ListRole roleList) {if (CollectionUtils.isEmpty(roles)){Assert.throwException(角色不能为空);}this.roles roleList;} } 实体和值对象 实体和值对象这两个概念都是领域模型中的领域对象。实体和值对象是组成领域模型的基础单元。 实体 在代码模型中实体的表现形式是实体类这个类包含了实体的属性和方法通过这些方法实现实体自身的业务逻辑。在 DDD 里这些实体类通常采用充血模型与这个实体相关的所有业务逻辑都在实体类的方法中实现跨多个实体的领域逻辑则在领域服务中实现。 实体Entity是一个唯一标识ID的对象它具有生命周期和可变状态并通过其标识属性来区分不同的实例。比如商品是商品上下文的一个实体通过唯一的商品 ID 来标识不管这个商品的数据如何变化商品的 ID 一直保持不变它始终是同一个商品。 在领域模型映射到数据模型时一个实体可能对应 0 个、1 个或者多个数据库持久化对象。大多数情况下实体与持久化对象是一对一。在某些场景中有些实体只是暂驻静态内存的一个运行态 实体它不需要持久化。比如基于多个价格配置数据计算后生成的折扣实体。 而在有些复杂场景下实体与持久化对象则可能是一对多或者多对一的关系。比如用户 user 与角色 role 两个持久化对象可生成权限实体一个实体对应两个持久化对象这是一对多的场景。再比如有些场景为了避免数据库的联表查询提升系统性能会将客户信息 customer 和账户信息 account 两类数据保存到同一张数据库表中客户和账户两个实体可根据需要从一个持久化对象中生成这就是多对一的场景。 代码示例用户实体 NoArgsConstructor Getter public class User extends AggregateLong, User {/*** 用户id-聚合根唯一标识*/private UserId userId;/*** 用户名*/private String userName;/*** 姓名*/private String realName;/*** 手机号*/private String phone;/*** 密码*/private String password;/*** 锁定结束时间*/private Date lockEndTime;/*** 登录失败次数*/private Integer failNumber;/*** 用户角色*/private ListRole roles;/*** 部门*/private Department department;/*** 领导*/private User leader;/*** 下属*/private ListUser subordinationList new ArrayList();/*** 用户状态*/private UserStatus userStatus;/*** 用户地址*/private Address address;public User(String userName, String phone, String password) {saveUserName(userName);savePhone(phone);savePassword(password);}/*** 保存用户名* param userName*/private void saveUserName(String userName) {if (StringUtils.isBlank(userName)){Assert.throwException(用户名不能为空);}this.userName userName;}/*** 保存电话* param phone*/private void savePhone(String phone) {if (StringUtils.isBlank(phone)){Assert.throwException(电话不能为空);}this.phone phone;}/*** 保存密码* param password*/private void savePassword(String password) {if (StringUtils.isBlank(password)){Assert.throwException(密码不能为空);}this.password password;}/*** 保存用户地址* param province* param city* param region*/public void saveAddress(String province,String city,String region){this.address new Address(province,city,region);}/*** 保存用户角色* param roleList*/public void saveRole(ListRole roleList) {if (CollectionUtils.isEmpty(roles)){Assert.throwException(角色不能为空);}this.roles roleList;}/*** 保存领导* param leader*/public void saveLeader(User leader) {if (Objects.isNull(leader)){Assert.throwException(leader不能为空);}this.leader leader;}/*** 增加下属* param user*/public void increaseSubordination(User user) {if (null user){Assert.throwException(leader不能为空);}this.subordinationList.add(user);} }值对象 值对象Value Object是没有唯一标识的对象它的价值在于其属性值本身。值对象是不可变的没有生命周期并且可以根据相等性来比较和判断是否相同。 简单来说值对象本质上就是一个集合。那这个集合里面有什么呢若干个用于描述目的、具有整体概念和不可修改的属性。那这个集合存在的意义又是什么在领域建模的过程中值对象可以保证属性归类的清晰和概念的完整性避免属性零碎。 /*** 地址数据*/ Getter public class Address extends ValueObject {/*** 省*/private String province;/*** 市*/private String city;/*** 区*/private String region;public Address(String province, String city, String region) {if (StringUtils.isBlank(province)){Assert.throwException(province不能为空);}if (StringUtils.isBlank(city)){Assert.throwException(city不能为空);}if (StringUtils.isBlank(region)){Assert.throwException(region不能为空);}this.province province;this.city city;this.region region;} }下面举一个简单的例子 人员实体原本包括姓名、年龄、性别以及人员所在的省、市、县、街道等属性。这样显示地址相关的属性不就很零碎现在我们可以将省、市、县、街道等属性拿出来构成一个地址属性集合这个集合就是值对象了。 拿在上面情况下可以把实体的属性进行聚合写出一个值对象呢 值对象逻辑上是实体属性的一部分用于描述实体的特征。值对象创建后就不允许修改了只能用另外一个值对象来整体替换。值对象是一些不会修改只能完整替换的属性值的集合你更关注他的属性和值它没有太多的业务行为用于描述实体的一些属性集被实体引用依附于实体的值对象基本没有自己的数据库表。是否要设计成值对象你要看这个对象是否后续还会来回修改会不会有生命周期。如果不可修改并且以后也不会专门针对它进行查询或者统计你就可以把它设计成值对象如果不行那就设计成实体吧。 在领域建模时我们可以将部分对象设计为值对象保留对象的业务涵义同时又减少了实体的数量在数据建模时我们可以将值对象嵌入实体减少实体表的数量简化数据库设计。 这里说一下DDD思想是提倡从领域设计出发而不是先设计数据模型。如果按照传统的数据模型设计通常是一个表对应一个实体一个主表关联多个从表当实体表太多时就会使数据库的设计变得无比复杂但是领域模型就可以通过将重点放在领域模型的设计和领域对象的行为上帮助开发团队更好地理解和处理复杂的业务问题并将其分解为可管理的领域对象和领域服务。 聚合 用专业术语来解释的话聚合Aggregate是一种用于组织和管理领域对象的设计模式。聚合将多个对象组合成一个逻辑单元以便于对领域对象进行操作和维护同时保证了领域对象之间的一致性和完整性。 你可以这么理解聚合就是由业务和逻辑紧密关联的实体和值对象组合而成的它们共同完成一个业务活动或者实现一个业务规则。聚合是数据修改和持久化的基本单元每一个聚合对应一个仓储实现数据的持久化。 聚合根 聚合根是聚合中的一个特殊对象它是聚合的入口点和协调者负责控制聚合内部的所有对象并将聚合与外部系统进行交互。聚合根具有唯一的标识符它代表了整个聚合是聚合中最重要的对象。 聚合根在聚合中担任着重要的角色它负责维护聚合内部的所有对象之间的关系保证聚合的一致性和完整性。聚合根还负责处理聚合内部的业务逻辑并与外部系统进行交互比如持久化和查询数据等。 需要注意的是聚合根并不是聚合内部的所有对象的代表它只是聚合的入口点。聚合根与聚合内部的其他对象之间的关系是通过引用关系来建立的不同的聚合内部也可以有相同类型的对象 举例分析 下面我举个例子来说明聚合诞生的完整过程 假设我们正在设计一个电子商务系统其中有两个核心领域对象订单Order和订单项OrderItem。订单对象表示用户下的订单订单项对象表示订单中的商品项。 首先我们需要确定聚合的范围。在这个例子中我们可以将订单作为聚合因为订单是一个完整的业务活动单元包含了订单项等相关信息。 创建聚合根。我们将创建一个名为Order的聚合根它具有唯一标识符例如订单号和相关属性如订单状态、支付方式等。聚合根还负责处理与订单相关的业务逻辑如计算订单总金额、验证支付状态等。 添加实体和值对象。在Order聚合内部我们可以定义实体和值对象比如OrderItem实体表示订单中的商品项具有自己的属性如商品ID、数量、价格等。值对象可以表示一些不可变的属性例如订单地址、收货人姓名等。 确定聚合内部的关系和约束。在这个例子中订单项是依赖于订单的因此需要将订单项作为订单的子对象。订单项与订单之间的关系通过引用来建立在订单中保存订单项的集合。 定义聚合根的行为。根据业务需求我们可以在Order聚合根中定义一些方法和操作例如添加订单项、删除订单项、取消订单等。这些方法负责维护聚合内部对象之间的一致性并处理相应的业务逻辑。 注意聚合边界。聚合根应该是聚合中唯一可以直接访问的对象外部系统通过聚合根来与聚合进行交互。其他聚合内部的对象应该通过聚合根来进行访问和操作以确保聚合的完整性和一致性。 架构分层 用户接口层 用户接口层是前端应用和微服务之间服务访问和数据交换的桥梁。接口服务位于用户接口层用于处理用户发送的Restful请求和解析用户输入的配置文件等并将信息传递给应用层。或获取应用服务的数据后进行数据组装向前端提供数据服务。主要服务形态是 Facade 服务。Facade 服务分为接口和实现两个部分。完成服务定向DO 与 DTO 数据的转换和组装实现前端与应用层数据的转换和交换 代码示例用户接口层User Interface Layer // UserController.java RestController RequestMapping(/users) public class UserController {Autowiredprivate UserService userService;PostMapping(/)public ResponseEntity createUser(RequestBody CreateUserRequest request) {UserDTO userDTO userService.createUser(request);return ResponseEntity.ok(userDTO);} }应用层 应用层是很薄的一层理论上不应该有业务规则或逻辑主要面向用例和流程相关的操作。但应用层又位于领域层之上因为领域层包含多个聚合所以它可以协调多个聚合的服务和领域对象完成服务编排和组合协作完成业务操作。除了同步方法调用外还可以发布或者订阅领域事件权限校验、事务控制一个事务对应一个聚合根。 应用层负责不同聚合之间的服务和数据协调负责微服务之间的事件发布和订阅。通过应用服务对外暴露微服务的内部功能这样就可以隐藏领域层核心业务逻辑的复杂性以及内部实现机制。应用层的主要服务形态有应用服务、事件发布和订阅服务。应用服务内用于组合和编排的服务主要来源于领域服务也可以是外部微服务的应用服务。 代码示例应用层Application Layer // UserService.java Service public class UserService {Autowiredprivate UserRepository userRepository;public UserDTO createUser(CreateUserRequest request) {User user new User(request.getUsername(), request.getEmail);userRepository.save(user);return new UserDTO(user.getId(), user.getUsername(), user.getEmail());} } 领域层 领域服务位于领域层为完成领域中跨实体或值对象的操作转换而封装的服务领域服务以与实体和值对象相同的方式参与实施过程。领域服务对同一个实体的一个或多个方法进行组合和封装或对多个不同实体的操作进行组合或编排对外暴露成领域服务。领域服务封装了核心的业务逻辑。实体自身的行为在实体类内部实现向上封装成领域服务暴露。为隐藏领域层的业务逻辑实现所有领域方法和服务等均须通过领域服务对外暴露。为实现微服务内聚合之间的解耦原则上禁止跨聚合的领域服务调用和跨聚合的数据相互关联。 代码示例领域层Domain Layer // User.java Entity public class User {IdGeneratedValue(strategy GenerationType.IDENTITY)private Long id;private String username;private String email;// 构造函数、Getter和Setter等略 }// UserRepository.java Repository public interface UserRepository extends JpaRepositoryUser, Long { }基础层 也叫基础设施层基础层是贯穿所有层的它的作用就是为其它各层提供通用的技术和基础服务包括第三方工具、驱动、消息中间件、网关、文件、缓存以及数据库等。比较常见的功能还是提供数据库持久化基础层的服务形态主要是仓储服务。仓储服务包括接口和实现两部分。仓储接口服务供应用层或者领域层服务调用仓储实现服务完成领域对象的持久化或数据初始化。 代码示例基础层Infrastructure Layer // JpaUserRepository.java Repository public class JpaUserRepository implements UserRepository {Autowiredprivate JpaUserDao userDao;Overridepublic void save(User user) {userDao.save(user);}// 其他持久化操作的实现 } DDD设计思想 所以前面讲了那么多那DDD架构分层设计思想到底是什么呢下面我给出我的理解 领域驱动设计DDD是一种软件设计方法其核心思想是将业务领域的知识和规则贯穿于整个软件开发过程中以确保软件系统能够更好地反映现实世界的业务需求。DDD 设计思想的关键点包括以下几个方面 领域模型DDD 强调通过领域模型来表达业务领域的复杂性和规则。领域模型是对业务概念、过程和规则的抽象表示它基于业务专家和开发团队之间的沟通和协作帮助理解业务需求并将其映射到软件设计中。 模型驱动设计在DDD 中领域模型是设计的核心它驱动着软件系统的构建。开发团队需要不断地与业务人员合作深入理解业务需求并将这些需求转化为可执行的领域模型。 通用语言为了促进业务人员和开发人员之间的沟通和理解DDD 强调采用通用语言Ubiquitous Language。通用语言是指在整个软件开发过程中使用的统一的业务术语和概念以确保所有人对业务领域的理解保持一致。 分层架构在DDD 中通常会采用分层架构来组织软件系统其中包括领域层、应用层和基础设施层。这种分层设计有助于将业务逻辑与技术实现分离提高系统的可维护性和可扩展性。 持续演化领域驱动设计认识到业务领域的复杂性和不断变化因此强调软件系统应该是持续演化的。开发团队需要不断地根据业务需求和反馈进行调整和改进以确保系统能够满足业务的变化和发展。 DDD 设计思想致力于将业务领域的知识和规则融入到软件设计中以提高软件系统的质量、灵活性和适应能力从而更好地满足业务需求。 项目实战 项目结构 具体代码 下面展示重点代码块需要完整项目的可以下载绑定资源 application/UserService.java | 应用层用户服务领域层服务做具体实现 package com.kjz.application.service;import com.kjz.domain.model.aggregates.UserRichInfo;/*** 应用层用户服务*/ public interface UserService {UserRichInfo queryUserInfoById(Long id);}domain/repository/IuserRepository.java | 领域层资源库由基础层实现 package com.kjz.domain.repository;import com.kjz.infrastructure.po.UserEntity;public interface IUserRepository {void save(UserEntity userEntity);UserEntity query(Long id);}domain/service/UserServiceImpl.java | 应用层实现类应用层是很薄的一层可以只做服务编排 package com.kjz.domain.service;import com.kjz.application.service.UserService; import com.kjz.domain.model.aggregates.UserRichInfo; import com.kjz.domain.model.vo.UserInfo; import com.kjz.domain.model.vo.UserSchool; import com.kjz.domain.repository.IUserRepository; import com.kjz.infrastructure.po.UserEntity; import org.springframework.stereotype.Service;import javax.annotation.Resource; import java.util.ArrayList; import java.util.List;Service(userService) public class UserServiceImpl implements UserService {Resource(name userRepository)private IUserRepository userRepository;Overridepublic 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(厂里);ListUserSchool 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 | 数据库对象类 package com.kjz.infrastructure.po;/*** 数据库实体对象用户实体 */ public class UserEntity {private Long id;private String name;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;}}infrastructrue/repository/UserRepository.java | 领域层定义接口基础层资源库实现 package com.kjz.infrastructure.repository.mysql;import com.kjz.domain.repository.IUserRepository; import com.kjz.infrastructure.dao.UserDao; import com.kjz.infrastructure.po.UserEntity; import org.springframework.stereotype.Repository;import javax.annotation.Resource;Repository(userMysqlRepository) public class UserMysqlRepository implements IUserRepository {Resourceprivate UserDao userDao;Overridepublic void save(UserEntity userEntity) {userDao.save(userEntity);}Overridepublic UserEntity query(Long id) {return userDao.query(id);} }interfaces/dto/UserInfoDto.java | DTO对象类隔离数据库类 package com.kjz.interfaces.dto;public class UserInfoDto {private Long id; // IDpublic Long getId() {return id;}public void setId(Long id) {this.id id;}}interfaces/facade/DDDController.java | 门面接口 package com.kjz.interfaces.facade;import com.kjz.application.service.UserService; import com.kjz.interfaces.dto.UserInfoDto; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody;import javax.annotation.Resource;Controller public class DDDController {Resource(name userService)private UserService userService;RequestMapping(/index)public String index(Model model) {return index;}RequestMapping(/api/user/queryUserInfo)ResponseBodypublic ResponseEntity queryUserInfo(RequestBody UserInfoDto request) {return new ResponseEntity(userService.queryUserInfoById(request.getId()), HttpStatus.OK);}}综上总结 以上基于DDD一个基本入门的结构演示完成实际开发可以按照此模式进行调整。目前这个架构分层还不能很好的进行分离以及层级关系的引用还不利于扩展。后续会持续完善以及可以组合搭建RPC框架等让整个架构更利于互联网开发。 专栏持续更新中感兴趣的读者大大可以关注我一下哟谢谢
http://wiki.neutronadmin.com/news/131747/

相关文章:

  • 个人站长做什么类型的网站个人网站设计规划书
  • 怎样在阿里做网站与wordpress集成软件
  • 4s店网站建设方案网站关于我们介绍模板
  • 六安网站建设报价方案网站怎么申请域名
  • 中国工程建设焊接协会网站线上营销的方式
  • wordpress网站代码文件太多wordpress给指定用户设置角色
  • 现在手机网站用什么做鄂州做网站公司
  • 加强网站备案管理专项行动做竞价推广这个工作怎么样
  • 什么叫网站策划书群晖 套件 wordpress
  • 深圳网站制作哪家好企业网站策划文案
  • 电子科技东莞网站建设简历免费模板可编辑word
  • 本地服务型网站开发wordpress 添加评论等级
  • 我公司要网站建设dedecms 网站导航
  • 微页制作网站模板下载自己怎么做微网站
  • 长沙网站空间青岛官网seo方法
  • 二手房网站建设方案网站怎么做的支付宝接口
  • 江苏省建设网站做网站的像素是多少
  • 网站建设系统分析互联网编程培训
  • 徐州网站公司自己开发的软件怎么卖
  • wordpress检索seo是什么及作用
  • 龙岗做网站多少钱手机端快速建站工具
  • 安徽城乡建设厅官方网站做网站合伙怎么分
  • 做网站学多长时间可以学会米粒网站建设
  • 电影采集网站流量教育培训网站有哪些
  • 网站集群建设解决方案wordpress 静态首页
  • 网站建设评分细则网站自己推广怎么做
  • 企业展示型网站 建站系统最近免费中文字幕mv免费高清版
  • 有口碑的网站建设湖南省郴州市宜章县
  • 医疗网站建设效果网站建设的一般步骤包含哪些
  • 网站如何排名成都中方互动做网站怎样