Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

zheng19851/ddd

Repository files navigation

架构风格

结合了整洁架构风格 、CQRS风格以及分层架构风格,并采用依赖原则分4层,如下:

  • adapter 接口适配层(适配dubbo、restful接口等协议)
  • application 应用层(实现用例的地方,eg:电商场景里的用户下单、商家发布商品等等)
  • domain 领域层(写领域逻辑的地方,eg:电商场景里的用户下单包含订单逻辑、商品逻辑、以及优惠逻辑等)
  • infrastructure 基础层(放Cache、MQ框架、数据库持久实现等的地方)

模块依赖关系以及与整洁架构风格模块对应关系: 采用依赖倒置的依赖关系

各模块详细拆解: DDD分层架构

DEMO

  • 执行ddd-module-demo/ddd-bootstrap下的App类的main方法
  • 创建一个商品
curl -H "Content-Type:application/json" -X POST http://localhost:8080/product/create --data '{"name":"test","description":"test description"}'

代码路径:ProductController.createProduct

http://localhost:8080/product/get?productId=1

代码路径:ProductController.getProduct

  • 获取商品信息(命令行)
curl -H "Content-Type:application/json" -X GET 'http://localhost:8080/product/get?productId=1'

代码路径:ProductController.getProduct

  • 分页查询商品信息(点击)

代码路径:ProductController.queryProducts

  • 修改商品
curl -H "Content-Type:application/json" -X POST http://localhost:8080/product/update --data '{"productId":"1","name":"test","description":"test description"}'

代码路径:ProductController.updateProduct

  • 禁用商品
curl -H "Content-Type:application/json" -X POST 'http://localhost:8080/product/deactivate?productId=1'

代码路径:ProductController.deactivateProduct

  • 启用商品
curl -H "Content-Type:application/json" -X POST 'http://localhost:8080/product/activate?productId=1'

代码路径:ProductController.activateProduct

  • 删除商品
curl -H "Content-Type:application/json" -X POST 'http://localhost:8080/product/delete?productId=1'

代码路径:ProductController.deleteProduct

使用方式

注意:需要提前将jar mvn clean install -Dmaven.test.skip=true进maven本地库或私库里

  • 方式1、如果你的应用「没有使用」SpringBoot
<dependency>
 <groupId>com.runssnail.ddd</groupId>
 <artifactId>ddd-spring</artifactId>
 <version>${ddd.version}</version>
</dependency>

增加spring配置,加入配置后,默认自动从spring上下文收集CommandHandler和EventHandler(需要在类上增加spring注解@Service、@Component等)

<bean id="commandBus" class="com.runssnail.ddd.spring.CommandBusFactoryBean"/>
<bean id="eventBus" class="com.runssnail.ddd.spring.EventBusFactoryBean"/>
 
  • 方式2、如果你的应用「使用」了SpringBoot
<dependency>
 <groupId>com.runssnail.ddd</groupId>
 <artifactId>ddd-spring-boot-starter</artifactId>
 <version>${ddd.version}</version>
</dependency>

重要组件介绍

  • Command(命令)

一个Command对象对应一个用例的请求数据

@Data
public class CreateProductCommand extends AbstractCommand<Result> {
 private String name;
 private String description;
 @Override
 public Class<Result> resultType() {
 return Result.class;
 }
}
  • Event(事件)

表示一个领域事件,用例完成后,发布一个领域事件

@Getter
public class ProductCreatedEvent extends AbstractEvent {
 private String productId;
 public ProductCreatedEvent(String productId) {
 this.productId = productId;
 }
}
  • CommandBus(命令总线)

分发Command到对应的CommandHandler里去处理业务 命令总线UML图

@Component
public class ProductApplicationService {
 @Autowired
 private CommandBus commandBus;
 /**
 * 创建商品
 *
 * @param command
 * @return
 */
 @Transactional
 public Result<Product> createProduct(CreateProductCommand command) {
 return commandBus.dispatch(command);
 }
}
  • EventBus(事件总线)

用来发布领域事件 事件总线UML图

 @Component
 public class CreateProductCommandHandler extends BaseCommandHandler<CreateProductCommand, Result> {
 
 // 这里省略...
 @Autowired
 private EventBus eventBus;
 
 @Override
 public Class<CreateProductCommand> supportCommand() {
 return CreateProductCommand.class;
 }
 
 @Override
 public Result<String> doHandle(CreateProductCommand command) {
 
 // 转换领域对象
 Product product = this.productDomainService.createProduct(command);
 
 // 保存数据
 productRepository.save(product);
 
 // 发布领域事件
 eventBus.publish(new ProductCreatedEvent(product.getProductId()));
 
 return Result.success(product.getProductId());
 }
 }
  • CommandHandler(命令处理器)

用来实现用例,一个Command对应一个CommandHandler

 @Component
 public class CreateProductCommandHandler extends BaseCommandHandler<CreateProductCommand, Result> {
 
 // 这里省略...
 
 @Override
 public Class<CreateProductCommand> supportCommand() {
 return CreateProductCommand.class;
 }
 
 @Override
 public Result<String> doHandle(CreateProductCommand command) {
 
 // do bussniess
 
 return Result.success(product.getProductId());
 }
 }
  • CommandInterceptor(命令拦截器)

用来拦截Command,支持多个CommandInterceptor处理同一个Command

@Component
@Order(1)
public class CreateProductInterceptor implements CommandInterceptor<CreateProductCommand, Result> {
 private static final Logger log = LoggerFactory.getLogger(CreateProductInterceptor.class);
 @Override
 public Class<CreateProductCommand> supportCommandType() {
 return CreateProductCommand.class;
 }
 @Override
 public void beforeHandle(CreateProductCommand command) {
 log.info("CreateProductInterceptor.preHandle");
 }
 @Override
 public void afterHandle(CreateProductCommand command, Result result) {
 log.info("CreateProductInterceptor.postHandle");
 }
}
  • CommandValidator(命令验证器)

用来验证Command参数完整性或者业务前置校验,默认支持Hibernate Validator

@Component
public class CreateProductCommandValidator implements CommandValidator<CreateProductCommand> {
 @Override
 public Class<CreateProductCommand> supportType() {
 return CreateProductCommand.class;
 }
 @Override
 public void validate(CreateProductCommand createProductCommand) throws IllegalArgumentException, BizException {
 Validate.notNull(createProductCommand);
 Validate.notNull(createProductCommand.getName());
 Validate.isTrue(createProductCommand.getName().length() <= 10);
 }
}
  • Assembler(组装器)

用来组装查询请求数据,将领域实体对象转换成DTO后返回给外部使用,将领域对象封装在内部

@Component
public class CreateProductAssembler implements Assembler<Product, ProductDTO> {
 @Override
 public ProductDTO assemble(Product product) {
 ProductDTO target = new ProductDTO();
 BeanUtils.copyProperties(product, target);
 return target;
 }
}
  • Converter(转换器)

实现领域实体对象和数据对象之间的转换

@Component
public class ProductConverter implements Converter<Product, ProductDO> {
 @Override
 public ProductDO serialize(Product product) {
 // todo 领域对象转换成数据对象
 ProductDO productDO = new ProductDO();
 productDO.setId(product.getProductId());
 return productDO;
 }
 @Override
 public Product deserialize(ProductDO productDO) {
 // todo 数据对象转换成领域对象
 return new Product(productDO.getId());
 }
}
  • ConcurrencyConflicts(并发校验工具)

用来判断修改数据时,是否产生了并发问题。

 @Override
 public void remove(Product product) throws ConcurrencyConflictException {
 
 // 方式1:
 int count = this.productDOMapper.deleteById(product.getId(), product.getOperator(), product.getConcurrencyVersion());
 ConcurrencyConflicts.check(count, "remove Product, id={}, concurrencyVersion={}", product.getId(), product.getConcurrencyVersion());
 
 // 方式2:
 ConcurrencyConflicts.check(() -> productMapper.removeProduct(product.getProductId(), product.getOperator(), product.getConcurrencyVersion()));
 }
 }

参考

About

实现领域驱动设计通用2方库和demo

Resources

Stars

Watchers

Forks

Packages

No packages published

Languages

AltStyle によって変換されたページ (->オリジナル) /