1
- # Java后台服务分层规范
1
+ # Java 后台服务分层规范
2
2
3
3
## 0. 分层概述
4
4
7
7
8
8
## 1. 分层示例:
9
9
10
- ![ 分层示例] ( ./resources/java_project_layer.png )
10
+ ![ 分层示例] ( .. /resources/java_project_layer.png )
11
11
12
12
其中各层的引用关系从上到下依次为:
13
- API层 -> Application层 -> DomainService -> Repository -> DomainModel
13
+ API 层 -> Application 层 -> DomainService -> Repository -> DomainModel
14
14
15
15
引用关系见下图
16
- ![ 分层示例] ( ./resources/java_layer_depencies.png )
16
+ ![ 分层示例] ( .. /resources/java_layer_depencies.png )
17
17
18
- ## 2. API层
18
+ ## 2. API 层
19
19
20
- API层用来定义对外的接口,对应于SpringMVC的Controller 。
21
- 在API层定义接口格式(比如Swagger的各种标记 ),也可以进行参数验证(比如使用@Validated )。
22
- 在API层实现登录及权限验证 。
23
- API层应该是很薄的一层 ,仅仅是参数验证,然后转发到Application层 。
20
+ API 层用来定义对外的接口,对应于 SpringMVC 的 Controller 。
21
+ 在 API 层定义接口格式(比如 Swagger 的各种标记 ),也可以进行参数验证(比如使用@Validated )。
22
+ 在 API 层实现登录及权限验证 。
23
+ API 层应该是很薄的一层 ,仅仅是参数验证,然后转发到 Application 层 。
24
24
25
- ## 3. 应用层(Application层 )
25
+ ## 3. 应用层(Application 层 )
26
26
27
27
应用层的每个方法定义软件要完成的一项任务;
28
28
应用层不包含具体的业务逻辑处理,而是协调业务逻辑层的类来完成任务;
29
- API返回代码应该在应用层进行定义 。
29
+ API 返回代码应该在应用层进行定义 。
30
30
31
- ## 4. 领域层(Domain层 )
31
+ ## 4. 领域层(Domain 层 )
32
32
33
33
领域层负责表达业务逻辑,是整个系统的核心层。
34
34
领域层的类根据职责不同,又划分为以下几部分:DomainModel, DomainService, Repository, ServiceProxy, Bo。
35
35
36
36
### 4.1 领域模型(DomainModel)
37
37
38
- - 领域模型应该是充血模型, 对DomainModel状态的修改应通过调用DomainModel的方法进行。
39
- - 领域模型参照DDD中的聚合 ,实体,值对象的概念进行划分,对DomainModel的任何修改都应该通过聚合根进行 。
40
- - 领域模型的创建属于领域层的职责,应该在领域层添加相应的工厂类(对于简单的实体,也可以直接在类中定义一个静态的create方法 )。
38
+ - 领域模型应该是充血模型, 对 DomainModel 状态的修改应通过调用 DomainModel 的方法进行。
39
+ - 领域模型参照 DDD 中的聚合 ,实体,值对象的概念进行划分,对 DomainModel 的任何修改都应该通过聚合根进行 。
40
+ - 领域模型的创建属于领域层的职责,应该在领域层添加相应的工厂类(对于简单的实体,也可以直接在类中定义一个静态的 create 方法 )。
41
41
- 领域模型中聚合根应该由自身来维护状态的完整性。
42
- - 领域模型不应该暴露在应用层之外,应该通过Bo (领域层的数据传输对象)来与领域层外部交互。
42
+ - 领域模型不应该暴露在应用层之外,应该通过 Bo (领域层的数据传输对象)来与领域层外部交互。
43
43
44
44
### 4.2 领域服务(DomainService)
45
45
@@ -49,37 +49,38 @@ API返回代码应该在应用层进行定义。
49
49
50
50
### 4.3 仓储(Repository)
51
51
52
- 仓储根据职责分成两类:修改和查询(create,update和delete都归类为修改 )。
53
- 这两类仓储可以采用不同的实现方式,比如修改采用Spring data JPA(Hibernate),而查询可以直接采用JdbcTemplate 。
52
+ 仓储根据职责分成两类:修改和查询(create,update 和 delete 都归类为修改 )。
53
+ 这两类仓储可以采用不同的实现方式,比如修改采用 Spring data JPA(Hibernate),而查询可以直接采用 JdbcTemplate 。
54
54
55
55
### 4.4 外部服务代理(ServiceProxy)
56
56
57
- 对外部服务的调用应封装在单独的类中。也可以封装出外部服务的接口,调用者只注入接口即可,外部服务的实现类在运行时由Spring注入 。
57
+ 对外部服务的调用应封装在单独的类中。也可以封装出外部服务的接口,调用者只注入接口即可,外部服务的实现类在运行时由 Spring 注入 。
58
58
59
59
### 4.5 Bo(领域层的数据传输对象)
60
60
61
- 对于领域层操作所需要的参数,或者领域层返回外部的数据,应该定义Bo对象 ,以避免暴露领域模型到外部。
62
- Bo对象只应该包含简单的数据字段和一些验证方法,也可以包含从领域模型到Bo对象的转换方法 。
61
+ 对于领域层操作所需要的参数,或者领域层返回外部的数据,应该定义 Bo 对象 ,以避免暴露领域模型到外部。
62
+ Bo 对象只应该包含简单的数据字段和一些验证方法,也可以包含从领域模型到 Bo 对象的转换方法 。
63
63
64
- ## 5. 基础设施层(infrastructure层 )
64
+ ## 5. 基础设施层(infrastructure 层 )
65
65
66
66
基础设施层包含一些通用逻辑,如系统配置,常量定义,日志处理,缓存等,以及一些第三方组件的封装。
67
67
68
- ## 6. utility层
68
+ ## 6. utility 层
69
69
70
- utility层包含一些共用的辅助方法 。
70
+ utility 层包含一些共用的辅助方法 。
71
71
72
72
## 7. 最佳实践
73
73
74
74
- 对于比较复杂的项目,每个分层中可以根据模块再分成多个目录,以方便管理。
75
- - 事务应该在ApplicationService或DomainService中定义 ,具体位置根据情况决定。
75
+ - 事务应该在 ApplicationService 或 DomainService 中定义 ,具体位置根据情况决定。
76
76
- 事务范围应尽量短,事务中不应包括远程服务调用及消息收发操作。
77
77
78
78
- 关于消息的发送应遵守以下约定:
79
- - 消息发送应该封装成独立的类,类名类似于xxxMessageProducer, 类定义放在DomainService目录下。
80
- - xxxMessageProducer类似DomainService,可以由其他的DomainService或ApplicationService调用。
79
+
80
+ - 消息发送应该封装成独立的类,类名类似于 xxxMessageProducer, 类定义放在 DomainService 目录下。
81
+ - xxxMessageProducer 类似 DomainService,可以由其他的 DomainService 或 ApplicationService 调用。
81
82
82
83
- 关于消息接收应遵守以下约定:
83
- - 消息接收的具体实现类应定义在最外层中,和Controller类似 ,并创建一个独立的目录,目录名为consumer,命名类似于xxxMessageConsumer ;
84
- - xxxMessageConsumer调用ApplicationService来完成实际处理 。
85
- - xxxMessageConsumer类似xxxController ,都是由外部调用发起。
84
+ - 消息接收的具体实现类应定义在最外层中,和 Controller 类似 ,并创建一个独立的目录,目录名为 consumer,命名类似于 xxxMessageConsumer ;
85
+ - xxxMessageConsumer 调用 ApplicationService 来完成实际处理 。
86
+ - xxxMessageConsumer 类似 xxxController ,都是由外部调用发起。
0 commit comments