cola是一个绝佳的DDD领域模式驱动的工程参考。
文章目录
生成第一个cola工程
mvn archetype:generate \
-DgroupId=com.alibaba.cola.demo.web \
-DartifactId=demo-web \
-Dversion=1.0.0-SNAPSHOT \
-Dpackage=com.alibaba.demo \
-DarchetypeArtifactId=cola-framework-archetype-web \
-DarchetypeGroupId=com.alibaba.cola \
-DarchetypeVersion=4.3.1
标准的业务系统分层大概如下:
分层解析
- adapter:适配层。负责前端展示,包括但不限于以下(web,wireless,wap)的路由和适配,相当于controller
- application:应用层。主要负责获取输入,组装上下文,参数校验,调用领域层做业务处理,如果需要的话,发送消息通知等。层次是开放的,应用层也可以绕过领域层,直接访问基础实施层
- domain:领域层。主要是封装了核心业务逻辑,并通过领域服务(Domain Service)和领域对象(Domain Entity)的方法对App层提供业务实体和业务逻辑计算。领域是应用的核心,不依赖任何其他层次
- infrastructure:基础实施层。主要负责技术细节问题的处理,比如数据库的CRUD、搜索引擎、文件系统、分布式服务的RPC等。此外,领域防腐的重任也落在这里,外部依赖需要通过gateway的转义处理,才能被上面的App层和Domain层使用
打开cola包结构如下:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6CF9p48o-1677494186762)(C:\Users\Vainycos\AppData\Roaming\Typora\typora-user-images\image-20220831153358888.png)]
对照上述标准分层,我们进行详细分析cola的架构设计:
Adapter:
- web:非必选。处理页面请求的Controller
- wireless:非必选。处理无线端的适配
- wap:非必选。处理wap端的适配
App:
- executor:必选。处理request,包括command和query
- consumer:非必选。处理外部message
- scheduler:非必选。处理定时任务
Domain:
- model:非必须。领域模型
- ability:非必须。领域能力,包括DomainService
- gateway:必须。领域网关,解耦利器
infrastructure:
- gatewayimpl:必选。网关实现
- mapper:非必选。ibatis数据库映射
- config:非必须。配置信息
Client:
- api:必选。服务对外透出的API
- dto:必选。服务对外的DTO
实操
建立一个学生管理模型,demo示例包含两个方法,分别是新增单个学生以及查询list。
infrastructure层,新建student.DO包,并新建StudentDO数据库映射实体类:
@Data
public class StudentDO {
/**
* 自增主键id
*/
private Long id;
/**
* 姓名
*/
private String name;
/**
* 年龄
*/
private int age;
}
domain层,
新建student包,并新建Student领域类,作为infra层的领域隔绝,去除id属性
@Data
public class Student {
/**
* 姓名
*/
private String name;
/**
* 年龄
*/
private int age;
}
新建StudentGateway接口
public interface StudentGateway {
Response add();
MultiResponse list();
}
在infrastructure层,新建mapper文件以及xml文件
@Mapper
public interface StudentMapper {
int insert(CustomerDO customerDO);
List<StudentDO> selectList();
}
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.alibaba.demo.student.StudentMapper">
<resultMap type="com.alibaba.demo.student.DO.StudentDO" id="studentMap">
<result property="id" column="id"/>
<result property="name" column="name"/>
<result property="age" column="age"/>
</resultMap>
<select id="selectList" resultType="com.alibaba.demo.student.DO.StudentDO" resultMap="studentMap">
select * from student
</select>
<insert id="insert" parameterType="com.alibaba.demo.student.DO.StudentDO" useGeneratedKeys="true" keyProperty="id">
insert into student(name, age)
VALUES (#{name},#{age})
</insert>
</mapper>
实现StudentGateway接口,新建StudentGatewayImpl
@Component
public class StudentGatewayImpl implements StudentGateway {
@Autowired
private StudentMapper studentMapper;
@Override
public Response add(Student student) {
StudentDO studentDO = new StudentDO();
// 可使用beancopy
studentDO.setName(student.getName());
studentDO.setAge(student.getAge());
studentMapper.insert(studentDO);
return Response.buildSuccess();
}
@Override
public MultiResponse list() {
return MultiResponse.of(studentMapper.selectList());
}
}
client包新增StudentService以及对应的入参和出参定义
public interface StudentService {
Response add();
MultiResponse list();
}
adapter->app->client->domain->infa
参考资料: