背景

在我们的项目中,我们通过责任链模式实现订单下单时的各种前置校验。

责任链设计模式介绍

责任链模式(Chain of Responsibility Pattern)是一种行为设计模式,可以通过将一系列处理器按顺序链接起来,使得每个处理器都有机会处理请求,从而实现请求的传递和处理。

代码实现

抽象接口

先定义一个接口,其中定义两个方法:

/**
 * 订单校验
 *
 */
public interface OrderCreateValidator {
    /**
     * 设置下一个校验器
     *
     * @param nextValidator
     */
    void setNext(OrderCreateValidator nextValidator);

    /**
     * 校验
     *
     * @param request
     * @throws Exception
     */
    void validate(OrderCreateRequest request) throws Exception;
}


setNext用于设置下一个处理器,validate 方法用于做请求检验。接下来实现三个具体的校验器:

具体实现类

用户校验器

主要判断用户状态是否正常:

@Component
public class UserValidator implements OrderCreateValidator {

    private OrderCreateValidator nextValidator;

    @Autowired
    private UserFacadeService userFacadeService;

    @Override
    public void setNext(OrderCreateValidator nextValidator) {
        this.nextValidator = nextValidator;
    }

    @Override
    public void validate(OrderCreateRequest request) throws Exception {
        String buyerId = request.getBuyerId();
        UserQueryRequest userQueryRequest = new UserQueryRequest();
        userQueryRequest.setUserId(Long.valueOf(buyerId));
        UserQueryResponse<UserInfo> userQueryResponse = userFacadeService.query(userQueryRequest);
        if (userQueryResponse.getSuccess() && userQueryResponse.getData() != null) {
            UserInfo userInfo = userQueryResponse.getData();
            if (userInfo.getUserRole() != null && userInfo.getUserRole().equals(UserRole.CUSTOMER)) {
                throw new Exception("买家不能是平台用户");
            }
            //判断买家状态
            if (userInfo.getState() != null && !userInfo.getState().equals(UserStateEnum.ACTIVE.name())) {
                throw new Exception("买家状态异常");
            }
            //判断买家状态
            if (userInfo.getState() != null && !userInfo.getCertification()) {
                throw new Exception("买家未完成实名认证");
            }
        }
    }
}

库存校验器

主要校验库存情况:

@Component
public class StockValidator extends BaseOrderCreateValidator {

    @Autowired
    private InventoryWrapperService inventoryWrapperService;

    @Override
    public void doValidate(OrderCreateRequest request) throws OrderException {
        BaseGoodsInventoryVO goodsInventoryVO = inventoryWrapperService.queryInventory(request);

        if (goodsInventoryVO == null) {
            throw new OrderException(INVENTORY_NOT_ENOUGH);
        }

        if (goodsInventoryVO.getInventory() == 0) {
            throw new OrderException(INVENTORY_NOT_ENOUGH);
        }

        if (goodsInventoryVO.getQuantity() < request.getItemCount()) {
            throw new OrderException(INVENTORY_NOT_ENOUGH);
        }

        if (goodsInventoryVO.getInventory() < request.getItemCount()) {
            throw new OrderException(INVENTORY_NOT_ENOUGH);
        }
    }
}

商品校验器

主要校验商品可售情况:

@Component
public class GoodsValidator extends BaseOrderCreateValidator {

    @Autowired
    private GoodsFacadeService goodsFacadeService;

    @Override
    protected void doValidate(OrderCreateRequest request) throws OrderException {
        BaseGoodsVO baseGoodsVO = goodsFacadeService.getGoods(request.getGoodsId(), request.getGoodsType());

        if (!baseGoodsVO.available()) {
            throw new OrderException(GOODS_NOT_AVAILABLE);
        }

        if (baseGoodsVO.getPrice().compareTo(request.getItemPrice()) != 0) {
            throw new OrderException(GOODS_PRICE_CHANGED);
        }
    }
}


 

分别实现了商品、用户以及库存的校验,每一个校验器只关心自己要校验的数据即可,如果有需要更多的东西需要校验,可以扩展出更多的校验器即可。

编排责任链

接下来就是把他们编排到一起:

@Configuration
public class OrderCreateValidatorConfig {

    @Autowired
    private StockValidator stockValidator;

    @Autowired
    private GoodsValidator goodsValidator;

    @Autowired
    private UserValidator userValidator;

    @Bean
    public OrderCreateValidator orderValidatorChain() {
        userValidator.setNext(goodsValidator);
        goodsValidator.setNext(stockValidator);
        return userValidator;
    }

}

通过定义一个OrderCreateValidator的 bean,把他们连在一起,即先进行用户的校验、其次进行商品和库存的校验。

调用

接下来,就可以在我们想要做校验的地方调用orderValidatorChain.validate进行校验了:

@Override
@DistributeLock(keyExpression = "#request.identifier", scene = "ORDER_CREATE")
@Facade
public OrderResponse create(OrderCreateRequest request) {
    try {
        orderValidatorChain.validate(request);
    } catch (Exception e) {
        return new OrderResponse.OrderResponseBuilder().buildFail(ORDER_CREATE_VALID_FAILED.getCode(), e.getMessage());
    }

    Boolean preDeductResult = inventoryWrapperService.preDeduct(request);
    if (preDeductResult) {
        return orderService.create(request);
    }
    throw new OrderException(OrderErrorCode.INVENTORY_DEDUCT_FAILED);
}

更多推荐