DDD(领域驱动设计)总体结构分为四层: Infrastructure(基础实施层),Domain(领域层),Application(应用层),Interfaces(表示层,也叫用户界面层或是接口层),
各个层面的作用下面介绍:
- 用户界面(表现层):负责给用户展示信息,并解释用户命令。
- 应用层:该层协调应用程序的活动。不包括任何业务逻辑,不保存业务对象的状态,但能保存应用程序任务过程的状态。(主要是调用领域层的接口如集群部署就放在这层,同时也能防止循环依赖)
- 领域层:这一层包括业务领域的信息。业务对象的状态在这里保存。业务对象的持久化和它们的状态可能会委托给基础设施层。(简单说就是对表对象增删改查的操作接口,真正的实现在基础设施层)
- 基础设施层:对其它层来说,这一层是一个支持性的库。它提供层之间的信息传递,实现业务对象的持久化,包含对用户界面层的支持性库等。
其实不管后端用什么语言:对 POST请求后端处理是类似的,比如:post参数校验和反序列化输入
比如对于 POST 请求,需要把用户的输入反序列化到后端类中。
Python Django 中的:
在视图类里指定:serializer_class = DataBaseInfoSerializer
然后在序列化类 DataBaseInfoSerializer 里自定义 validate 方法实现 post 参数校验,
当然也可以对在定义序列化类的字段时指定一些是否必填等基础校验
db_host = serializers.CharField(allow_null=True, required=False)
然后在视图类里得到校验后和序列化后的数据:
data = serializer.validated_data;
GoLang Beego 中的:
在视图函数中:
var v models.BackupPlanInput
err := json.Unmarshal(c.Ctx.Input.RequestBody, &backuPlanInput)
valid := validation.Validation{}
b, err := valid.Valid(&v)
在结构体 models.BackupPlanInput 中实现方法 Valid 就能做到 post 参数校验
func (p *BackupPlanInput) Valid(v *validation.Validation) {
}
Java SpringBoot 中的:在 DTO 类里通过注解实现 post 参数基本校验
FlowOrder flowOrder = flowOrderAssembler.dtoToEntity(dto)
Q: 为什么要分这么多层?DTO、实体类、DO
A:其实是给了一次做转换的机会即有一次处理数据的机会,比如:
DTO到实体类:即“用户输入”到“领域层实体类”的转换:
比如对于性别前端输入的是男女,后端存储0和1
实体类到DO:即 “领域层实体类”到“基础设施层的DO”的转换
比如通常后端数据库表中会增加逻辑删除字段和 版本控制 version 字段
这也吻合了一句名言:在计算机里,任何问题都可以通过加中间转换层来解决
DOT到实体类的转换示例:通过 expression 做自定义的处理
package com.jdd.flowmanager.interfaces.facade.assembler;
import com.jdd.flowmanager.domain.entity.FlowOrder;
import com.jdd.flowmanager.infrastructure.utils.JacksonUtils;
import com.jdd.flowmanager.interfaces.facade.dto.FlowOrderDTO;
import com.jdd.flowmanager.interfaces.facade.viewobject.FlowOrderVO;
import org.mapstruct.*;
import org.mapstruct.factory.Mappers;
import java.util.List;
import java.util.Map;
@Mapper(
nullValueMappingStrategy = NullValueMappingStrategy.RETURN_NULL,
nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.IGNORE,
nullValueCheckStrategy = NullValueCheckStrategy.ALWAYS
)
public interface FlowOrderAssembler {
FlowOrderAssembler INSTANCE = Mappers.getMapper(FlowOrderAssembler.class);
/**
* DTO转实体
*
* @param dto DTO
* @return 实体
*/
@Mapping(expression = "java(MapStructExpression.mapToStr(dto.getOrderDetails()))", target = "orderDetails")
FlowOrder dtoToEntity(FlowOrderDTO dto);
/**
* 实体转VO
*
* @param entity entity
* @return ViewObject
*/
FlowOrderVO entityToVO(FlowOrder entity);
}
class MapStructExpression {
public static String mapToStr(Map<String, Object> map){
return JacksonUtils.toJson(map);
}
}