基于 pipeline 的订单模块设计
模块划分
- callback 回调
- context 上下文信息
- convert 上下文转换
- factory 工厂用于构建pipeline
- handler 具体业务处理
factory
import com.gpmall.order.biz.handler.*;
import com.gpmall.order.biz.context.CreateOrderContext;
import com.gpmall.order.biz.context.TransHandlerContext;
import com.gpmall.order.biz.convert.CreateOrderConvert;
import com.gpmall.order.biz.convert.TransConvert;
import com.gpmall.order.dto.CreateOrderRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/**
*
* 构建订单处理链
*/
@Slf4j
@Service
public class OrderProcessPipelineFactory extends AbstranctTransPipelineFactory<CreateOrderRequest> {
@Autowired
private InitOrderHandler initOrderHandler;
@Autowired
private ValidateHandler validateHandler;
@Autowired
private LogisticalHandler logisticalHandler;
@Autowired
private ClearCartItemHandler clearCartItemHandler;
@Autowired
private SubStockHandler subStockHandler;
@Autowired
private SendMessageHandler sendMessageHandler;
@Override
protected TransHandlerContext createContext() {
CreateOrderContext createOrderContext=new CreateOrderContext();
return createOrderContext;
}
@Override
protected void doBuild(TransPipeline pipeline) {
pipeline.addLast(validateHandler);
pipeline.addLast(subStockHandler);
pipeline.addLast(initOrderHandler);
pipeline.addLast(logisticalHandler);
pipeline.addLast(clearCartItemHandler);
pipeline.addLast(sendMessageHandler);
}
@Override
protected TransConvert createConvert() { //构建转换器
return new CreateOrderConvert();
}
}
handler
package com.gpmall.order.biz.handler;/**
* Created by mic on 2019/8/1.
*/
import com.gpmall.commons.tool.exception.BizException;
import com.gpmall.order.biz.callback.TransCallback;
import com.gpmall.order.biz.context.CreateOrderContext;
import com.gpmall.order.biz.context.TransHandlerContext;
import com.gpmall.order.constant.OrderRetCode;
import com.gpmall.shopping.ICartService;
import com.gpmall.shopping.dto.ClearCartItemRequest;
import com.gpmall.shopping.dto.ClearCartItemResponse;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.Reference;
import org.springframework.stereotype.Component;
/**
* 将购物车中的缓存失效
*/
@Slf4j
@Component
public class ClearCartItemHandler extends AbstractTransHandler {
@Reference(check = false,mock = "com.gpmall.order.biz.mock.MockCartService")
ICartService cartService;
//是否采用异步方式执行
@Override
public boolean isAsync() {
return false;
}
@Override
public boolean handle(TransHandlerContext context) {
log.info("begin - ClearCartItemHandler-context:"+context);
//TODO 缓存失效和下单是属于两个事物操作,需要保证成功,后续可以改造成消息队列的形式来实现
ClearCartItemRequest request=new ClearCartItemRequest();
CreateOrderContext createOrderContext=(CreateOrderContext)context;
request.setProductIds(createOrderContext.getBuyProductIds());
request.setUserId(createOrderContext.getUserId());
ClearCartItemResponse response=cartService.clearCartItemByUserID(request);
if(OrderRetCode.SUCCESS.getCode().equals(response.getCode())){
return true;
}else{
throw new BizException(response.getCode(),response.getMsg());
}
}
}
service 的调用
package com.gpmall.order.services;/**
* Created by mic on 2019/7/30.
*/
import com.gpmall.order.OrderCoreService;
import com.gpmall.order.biz.TransOutboundInvoker;
import com.gpmall.order.biz.context.AbsTransHandlerContext;
import com.gpmall.order.biz.factory.OrderProcessPipelineFactory;
import com.gpmall.order.constant.OrderRetCode;
import com.gpmall.order.constants.OrderConstants;
import com.gpmall.order.dal.entitys.Order;
import com.gpmall.order.dal.persistence.OrderItemMapper;
import com.gpmall.order.dal.persistence.OrderMapper;
import com.gpmall.order.dal.persistence.OrderShippingMapper;
import com.gpmall.order.dto.*;
import com.gpmall.order.utils.ExceptionProcessorUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.Service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import tk.mybatis.mapper.entity.Example;
import java.util.Date;
/**
*
*/
@Slf4j
@Service(cluster = "failfast")
public class OrderCoreServiceImpl implements OrderCoreService {
@Autowired
OrderMapper orderMapper;
@Autowired
OrderItemMapper orderItemMapper;
@Autowired
OrderShippingMapper orderShippingMapper;
@Autowired
OrderProcessPipelineFactory orderProcessPipelineFactory;
@Autowired
OrderCoreService orderCoreService;
/**
* 创建订单的处理流程
*
* @param request
* @return
*/
@Override
public CreateOrderResponse createOrder(CreateOrderRequest request) {
CreateOrderResponse response = new CreateOrderResponse();
try {
TransOutboundInvoker invoker = orderProcessPipelineFactory.build(request);
invoker.start(); //启动流程(pipeline来处理)
AbsTransHandlerContext context = invoker.getContext();
response = (CreateOrderResponse) context.getConvert().convertCtx2Respond(context);
} catch (Exception e) {
log.error("OrderCoreServiceImpl.createOrder Occur Exception :" + e);
ExceptionProcessorUtils.wrapperHandlerException(response, e);
}
return response;
}
/**
* 取消订单
*
* @param request
* @return
*/
@Override
public CancelOrderResponse cancelOrder(CancelOrderRequest request) {
CancelOrderResponse response = new CancelOrderResponse();
try {
Order order = new Order();
order.setOrderId(request.getOrderId());
order.setStatus(OrderConstants.ORDER_STATUS_TRANSACTION_CANCEL);
order.setCloseTime(new Date());
int num = orderMapper.updateByPrimaryKey(order);
log.info("cancelOrder,effect Row:" + num);
response.setCode(OrderRetCode.SUCCESS.getCode());
response.setMsg(OrderRetCode.SUCCESS.getMessage());
} catch (Exception e) {
log.error("OrderCoreServiceImpl.cancelOrder Occur Exception :" + e);
ExceptionProcessorUtils.wrapperHandlerException(response, e);
}
return response;
}
/**
* 删除订单
*
* @param request
* @return
*/
@Override
public DeleteOrderResponse deleteOrder(DeleteOrderRequest request) {
DeleteOrderResponse response = new DeleteOrderResponse();
try {
request.requestCheck();
deleteOrderWithTransaction(request);
response.setCode(OrderRetCode.SUCCESS.getCode());
response.setMsg(OrderRetCode.SUCCESS.getMessage());
} catch (Exception e) {
log.error("OrderCoreServiceImpl.deleteOrder Occur Exception :" + e);
ExceptionProcessorUtils.wrapperHandlerException(response, e);
}
return response;
}
@Override
public void updateOrder(Integer status, String orderId) {
Order order = new Order();
order.setOrderId(orderId);
order.setStatus(status);
orderMapper.updateByPrimaryKey(order);
}
@Transactional(rollbackFor = Exception.class)
@Override
public void deleteOrderWithTransaction(DeleteOrderRequest request){
orderMapper.deleteByPrimaryKey(request.getOrderId());
Example example = new Example(Order.class);
example.createCriteria().andEqualTo("orderId",request.getOrderId());
orderItemMapper.deleteByExample(example);
orderShippingMapper.deleteByPrimaryKey(request.getOrderId());
}
}
思考
- Netty springmvc 都有类似实现
Netty的Pipeline机制解决了什么问题?
一是提供了ChannelHandler的编程模型,基于ChannelHandler开发业务逻辑,基本不需要关心网络通讯方面的事情,专注于编码/解码/逻辑处理就可以了。Handler也是比较方便的开发模式,在很多框架中都有用到。
二是实现了所谓的”Universal Asynchronous API”。这也是Netty官方标榜的一个功能。用过OIO和NIO的都知道,这两套API风格相差极大,要从一个迁移到另一个成本是很大的。即使是NIO,异步和同步编程差距也很大。而Netty屏蔽了OIO和NIO的API差异,通过Channel提供对外接口,并通过ChannelPipeline将其连接起来,因此替换起来非常简单。
universal API
2 springmvc 的责任链模式
参考资料:
Sink http://en.wikipedia.org/wiki/Sink_(computing)
https://ifeve.com/channel-pipeline/