1.領域對象的使用
用於項目不同層次間的數據交互,並可以在不同層次中實現轉換;
所有的領域對象建議使用貧血模型;
領域對象的使用會使得類數量增多;
2.常見的幾種領域對象
1.PO (persistant object)持久對象 / Entity:通常對應數據模型 ( 數據庫 )。可以看成是與數據庫中的表相映射的 Java 對象, PO 中應該不包含任何對數據庫的操作。
2.DO(Domain Object)領域對象:從現實世界中抽象出來的有形或無形的業務實體。大多數情況下是與PO一一對應的。但是它還可以表示多個PO之間的業務關係(與PO接近)。
3.DTO(Data Transfer Object)數據傳輸對象:泛指用於展示層(web和api層)與服務層(service)之間的數據傳輸對象。
4.VO(View Object):視圖對象,用於展示層,它的作用是把某個指定頁面(或組件)的所有數據封裝起來(使用統一返回對象Result<xxxDto>()代替)。
5.QUERY: 查詢對象,用於數據訪問層。
常用的有:po/entity, dto, query
3.項目分層
(摘自阿里開發規範)
4.各層的領域對象
5.項目分包結構
web, api, service, dal
+---zhku-dal
| +---src\main\java\com\zhku\computer
| | | +---entity
| | | +---po
| | | +---manager
| | | +---mapper
| | | +---config
| | | +---enum
| | | /---resource
| | | +---xml
+---zhku-service
| +---src\main\java\com\zhku\computer
| | | +---impl
| | | +---remote
| | | +---convert
| | | +---util
+---zhku-service-api
| +---src\main\java\com\zhku\computer
| | | \---api
| | | +---service
| | | +---query
| | | +---dto
| | | +---exception
\---zhku-web
| +---src\main\java\com\zhku\computer
| | | \---web
| | | +---config
| | | +---api
| | | +---route
| | | +---mobile
web層 | UserController |
領域對象 | query, dto |
@PostMapping(value = "/v1/school/{userId}")
public ZHKUResult<UserDto> saveUser(@Validated UserSaveQuery query) {
userService.saveUser(query);
return new ZHKUResult<>();
}
@DeleteMapping(value = "/v1/school/{userId}")
public ZHKUResult removeUser(@Validated UserQuery query) {
userService.removeUser(query);
return new ZHKUResult();
}
@PutMapping(value = "/v1/school/{userId}")
public ZHKUResult<UserDto> updateUser(@Validated UserSaveQuery query) {
userService.updateUser(query);
return new ZHKUResult();
}
@GetMapping(value = "/v1/school/{userId}")
public ZHKUResult<UserDto> findUser(@Validated UserQuery query) {
return new ZHKUResult<UserDto>(userService.findUser(query));
}
service-api層 | UserService <interface> |
領域對象 | query, dto |
void saveUser(UserSaveQuery query);
void removeUser(UserQuery query)
void updateUser(UserSaveQuery query)
UserDto findUser(UserQuery query)
service層 | UserServiceImpl |
領域對象 | query, dto, po/entity |
void saveUser(UserSaveQuery query){
systemService.validated(query); //other service api, exp: dubbo api / http api
UserEntity user = convert.toUserEntity(query);
userManager.saveUser(user);
}
void deleteUser(UserQuery query){
String userId = query.getUserId();
userManager.deleteUser(userId);
}
void updateUser(usersaveQuery query){
UserEntity user = convert.toUserEntity(query);
userManager.updateUser(user);
}
UserDto findUser(UserQuery query){
String userId = query.getUserId();
UserEntity user = userManager.findUser(userId);
return convert.toUserDto(user);
}
dal-manager層 | userManager |
領域對象 | po/entity |
void saveUser(UserEntity user){
userMapper.saveUser(user);
}
void deleteUser(String userId){
userMapper.deleteUser(userId);
}
void updateUser(UserEntity user){
userMapper.updateUser(user);
}
UserEntity findUser(String userId){
return userMapper.findUser(userId);
}
dal層 | UserMapper <interface>,與xml綁定 |
領域對象 | po/entity |
void saveUser(@Param("user") UserEntity user);
void deleteUser(@Param("userId") String userId);
void updateUser(@Param("user")UserEntity user);
UserEntity findUser(@Param("userId")String userId);
ps: 領域對象轉換工具:mapstruct (實際使用存在部分字段轉換失敗的情況/bug,建議手動寫默認方法實現轉換,idea安裝GenerateAllSetter插件),或是淺拷貝 BeanUtils.copyProperties (缺點:1.對兩個轉換對象有要求,2.反射犧牲了性能)
實踐規約
1. 各個模塊層級之間,不能跨級引用,不能層級倒轉引用:即web -> api -> service -> service/manager -> dal;
2. 同層級只能單向引用不能循環引用,A service引用了B sevice,那麼B service不能引用A service;
3. Controller層統一獨立抽出放置網關中,所有的參數校驗放在網關層;
4. Service層只能注入DAO(不建議),Manager層的依賴;
5. po/entity不可在web層,api層中暴露,系統對外提供的領域對象爲dto;
6. 儘量每個請求使用不同的query;
7.dto需要實現序列化接口;