一、整体架构图
二、项目具体层次结构
(workorder指具体的业务分类)
1.interfaces-module
用户接口层
a.目录结构
│ pom.xml
│
└─src
└─main
├─java
│ └─com
│ └─sja
│ └─test
│ │ DddMainApplication.java //启动类
│ │
│ └─interfaces
│ └─web //提供给web的接口放在该目录下,如有提供给其他端的接口,则新建同级目录,如h5,app,client
│ └─workorder
│ WorkOrderController.java //工单操作入口
│
└─resources
│ application-dev.yml //环境配置
│ application.yml //环境配置
│ logback.xml //日志配置
│
└─db
└─migration
V1__init.sql //flyway脚本
b.用例代码
出参和入参在application-module中定义
创建工单,用户传入创建工单的命令
查询工单,用户传入查询工单的query参数
@RestController
@RequestMapping("/work-order")
public class WorkOrderController{
@Autowired
private WorkOrderAppService workOrderAppService;
@PostMapping
public CommonResponse<Void> create(@RequestBody AddWorkOrderCommand addWorkOrderCommand){
return workOrderAppService.create(addWorkOrderCommand);
}
@GetMapping("/page")
public CommonResponse<PageData<WorkOrderVO>> page(@RequestBody @Validated WorkOrderQuery workOrderQuery){
return workOrderAppService.page(workOrderQuery);
}
}
2.application-module
负责对domain的业务进行编排
a.目录结构
│ pom.xml
│
└─src
├─main
│ └─java
│ └─com
│ └─sja
│ └─test
│ └─application
│ └─workorder
│ ├─command //新增、更新的命令
│ │ AddWorkOrderCommand.java
│ │
│ ├─converter //类型转换器
│ │ WorkOrderAddCommandDomainConverter.java
│ │ WorkOrderVoDomainConverter.java
│ │
│ ├─query //查询参数
│ │ WorkOrderQuery.java
│ │
│ ├─service //appService
│ │ │ WorkOrderAppService.java
│ │ │
│ │ └─impl
│ │ WorkOrderAppServiceImpl.java
│ │
│ └─vo //vo视图
│ WorkOrderVO.java
│
└─test
└─java
b.用例代码
创建工单,将接收的命令转换为具体的领域domain,调用domain-module的方法
@Service
public class WorkOrderAppServiceImpl implements WorkOrderAppService {
@Autowired
private WorkOrderDomainService workOrderDomainService;
@Autowired
private WorkOrderAddCommandDomainConverter workOrderAddCommandDomainConverter;
@Autowired
private WorkOrderVoDomainConverter workOrderVoDomainConverter;
@Override
@Transactional(rollbackFor = Exception.class)
public CommonResponse<Void> create(AddWorkOrderCommand addWorkOrderCommand){
WorkOrderDomain workOrderDomain = workOrderAddCommandDomainConverter.toTarget(addWorkOrderCommand);
workOrderDomainService.create(workOrderDomain);
return CommonResponse.ok();
}
@Override
public CommonResponse<PageData<WorkOrderVO>> page(WorkOrderQuery workOrderQuery){
PageData<WorkOrderVO> voPage = new PageData<>();
IPage<WorkOrderDomain> domainPage = workOrderDomainService.page(workOrderQuery.getTenantName(), workOrderQuery.getPageNum(), workOrderQuery.getPageSize());
voPage.setTotal(domainPage.getTotal());
if (CollectionUtils.isNotEmpty(domainPage.getRecords())){
voPage.setRows(workOrderVoDomainConverter.toSourceList(domainPage.getRecords()));
}
return CommonResponse.ok(voPage);
}
}
3.domain-module
a.目录结构
│ pom.xml
│
└─src
├─main
│ └─java
│ └─com
│ └─sja
│ └─test
│ └─domain
│ └─workorder
│ ├─model //domain
│ │ WorkOrderDomain.java
│ │
│ ├─repository //仓储接口,实现在infrastructure-module
│ │ WorkOrderRepository.java
│ │
│ └─service //domainService,依赖仓储接口提供的能力
│ │ WorkOrderDomainService.java
│ │
│ └─impl
│ WorkOrderDomainServiceImpl.java
│
└─test
└─java
b.用例代码
采用依赖倒置思想,调用仓储提供的能力
@Service
public class WorkOrderDomainServiceImpl implements WorkOrderDomainService {
@Autowired
private WorkOrderRepository workOrderRepository;
@Override
public void create(WorkOrderDomain workOrderDomain) {
workOrderRepository.create(workOrderDomain);
}
@Override
public IPage<WorkOrderDomain> page(String tenantName, Integer pageNum, Integer pageSize) {
return workOrderRepository.page(tenantName, pageNum, pageSize);
}
}
4.infrastructure-module
a.目录结构
│ pom.xml
│
└─src
└─main
├─java
│ └─com
│ └─sja
│ └─test
│ └─infrastructure
│ └─workorder
│ ├─converter //类型转换器
│ │ WorkOrderDataObjectDomainConverter.java
│ │
│ ├─dataobject //实体,对应数据库表
│ │ WorkOrderDO.java
│ │
│ ├─mapper // mybatis-plus mapper接口
│ │ WorkOrderMapper.java
│ │
│ └─repository //仓储实现
│ WorkOrderRepositoryImpl.java
│
└─resources
└─mappers //mapper接口对应的xml文件
WorkOrderMapper.xml
b.用例代码
仓储实现调用ORM提供的CRUD功能,或缓存
@Repository
public class WorkOrderRepositoryImpl implements WorkOrderRepository {
@Autowired
private WorkOrderMapper workOrderMapper;
@Autowired
private WorkOrderDataObjectDomainConverter workOrderDataObjectDomainConverter;
@Override
public void create(WorkOrderDomain workOrderDomain) {
WorkOrderDO workOrderDO = workOrderDataObjectDomainConverter.toSource(workOrderDomain);
workOrderMapper.insert(workOrderDO);
}
@Override
public IPage<WorkOrderDomain> page(String tenantName, Integer pageNum, Integer pageSize) {
IPage<WorkOrderDomain> domainPage = new Page<>();
IPage<WorkOrderDO> doPage = new Page<>(pageNum, pageSize);
LambdaQueryWrapper<WorkOrderDO> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(StringUtils.isNotBlank(tenantName), WorkOrderDO::getTenantName, tenantName);
doPage = workOrderMapper.selectPage(doPage, queryWrapper);
domainPage.setTotal(doPage.getTotal());
if (CollectionUtils.isNotEmpty(doPage.getRecords())){
domainPage.setRecords(workOrderDataObjectDomainConverter.toTargetList(doPage.getRecords()));
}
return domainPage;
}
}
5.common-module
项目公用配置
a.目录结构
│ pom.xml
│
└─src
└─main
└─java
└─com
└─sja
└─test
└─common
├─aspect
│ ControllerLoggerAspect.java //日志打印
│
├─base
│ │ BaseDO.java
│ │
│ ├─converter
│ │ BaseSourceTargetConverter.java //基础转换器
│ │
│ └─enums
│ BaseResponseEnum.java
│ BusinessResponseEnum.java //自定义业务状态码
│
├─config
│ CustomIdGenerator.java
│ MybatisPlusAutoConfiguration.java //Mybatis-plus配置
│ SwaggerConfig.java
│ WebMvcConfig.java
│
├─enums
│ └─workorder
│ OrderStatusEnum.java
│ WorkOrderActionEnum.java
│ WorkOrderOperationEnum.java
│
├─exception //自定义异常
│ BusinessException.java
│ TokenRuntimeException.java
│
├─handler
│ CommonMetaObjectHandler.java //mybatis-plus字段填充
│ GlobalExceptionHandler.java
│
├─http
│ CommonResponse.java //rest接口返回包装类
│ PageData.java //分页数据包装类
│
├─interceptor
│ TokenInterceptor.java //token校验
│
└─utils
AESCBCUtil.java
JwtUtils.java