责任链模式
-
使用场景,在创建订单的前置,需要对订单的数据进行校验,校验有先后且校验的代码较多。为了解耦避免多个校验直接相互环关联影响。同时使用注解@PostConstruct把对应的校验处理器在bean创建阶段就直接交给spring容器进行管理。
-
package com.evatmaster.biz.center.order.service.impl; import cn.hutool.core.collection.CollectionUtil; import com.evatmaster.biz.center.order.service.IOrderCheckBizService; import com.evatmaster.biz.center.order.handler.OrderCheckHandler; import com.evatmaster.biz.center.order.handler.impl.*; import com.evatmaster.biz.center.utils.WhiteListUtil; import com.evatmaster.core.enums.order.OrderSourceEnum; import com.evatmaster.core.enums.order.OrderTypeEnum; import com.evatmaster.core.enums.payment.PayBizTypeEnum; import com.evatmaster.core.enums.payment.PayReceivingTypeEnum; import com.evatmaster.core.enums.product.ProductTypeEnum; import com.evatmaster.core.exception.ValidateException; import com.evatmaster.core.utils.CommonUtils; import com.evatmaster.core.utils.StringUtils; import com.evatmaster.order.api.dto.BuyCartRequestDTO; import com.evatmaster.biz.center.order.dto.CreateOrderBizDTO; import com.evatmaster.order.api.dto.CreateBuyCartBaseDTO; import com.evatmaster.order.api.dto.OrderRequestDTO; import com.evatmaster.order.api.enums.OrderPaymentMethodEnum; import lombok.RequiredArgsConstructor; import org.springframework.beans.BeanUtils; import org.springframework.stereotype.Service; import javax.annotation.PostConstruct; import java.util.ArrayList; import java.util.List; /** * 订单校验接口 * @author li */ @Service @RequiredArgsConstructor public class OrderCheckBizServiceImpl implements IOrderCheckBizService { private final OrderCheckParamHandler checkParamHandler; private final OrderCheckProductHandler checkProductHandler; private final OrderCheckSetMealHandler checkSetMealHandler; private final OrderCheckActivityHandler checkActivityHandler; private final OrderCheckVoucherHandler checkVoucherHandler; private final OrderCheckPackVoucherHandler checkPackVoucherHandler; private final OrderCheckScoreHandler orderCheckScoreHandler; private final OrderCheckBizHandler orderCheckBizHandler; private final OrderCheckActivityGroupHandler orderCheckActivityGroupHandler; private final OrderCheckAfterPayHandler orderCheckAfterPayHandler; private final OrderCheckNewUserZoneHandler orderCheckNewUserZoneHandler; private final WhiteListUtil whiteListUtil; private final OrderCheckVipUpgradeHandler orderCheckVipUpgradeHandler; private final OrderCheckVipHandler orderCheckVipHandler; /** * 订单检查链路 */ private final List<OrderCheckHandler> chain = new ArrayList<>(8); @PostConstruct public void initChain(){ //校验订单参数 chain.add(checkParamHandler); //校验商品信息 chain.add(checkProductHandler); //校验业务 chain.add(orderCheckBizHandler); // 套餐校验 chain.add(checkSetMealHandler); // 校验先用后付 chain.add(orderCheckAfterPayHandler); // 校验新人专区 chain.add(orderCheckNewUserZoneHandler); //校验活动 // chain.add(checkActivityHandler); // 校验拼团 chain.add(orderCheckActivityGroupHandler); //校验优惠券 chain.add(checkVoucherHandler); //校验服务兑换券 chain.add(checkPackVoucherHandler); //校验积分 chain.add(orderCheckScoreHandler); // 校验VIP升级商品 chain.add(orderCheckVipUpgradeHandler); // 校验会员商品 chain.add(orderCheckVipHandler); } @Override public CreateOrderBizDTO checkOrder(OrderRequestDTO order) { if(CollectionUtil.isEmpty(order.getDetailDTOList())){ throw new ValidateException("请选择购买的商品"); } CreateOrderBizDTO dto = CreateOrderBizDTO.of(order); String payWay = dto.getPayWay() + ""; // 大客户批量创单,未指定支付方式,则默认微信支付 if(StringUtils.isBlank(payWay) && OrderSourceEnum.BATCH_CREATE.is(String.valueOf(order.getOrderSource()))) { payWay = PayReceivingTypeEnum.WECHAT.getCode(); } // 支付宝扫码支付、微信扫码支付、小程序微信支付 if(PayReceivingTypeEnum.ALIPAY.is(payWay) || PayReceivingTypeEnum.WECHAT.is(payWay) || PayReceivingTypeEnum.APPLET.is(payWay)) { Integer payChannel = whiteListUtil.getPayChannel(order.getMercName(), dto.getSystemType(), PayBizTypeEnum.BUY.name()); Integer payMethod = OrderPaymentMethodEnum.parsePayChannel(payChannel, payWay); dto.setPaymentMethod(payMethod); } // 对公转账 if(PayReceivingTypeEnum.OFFLINE.is(payWay)) { dto.setPaymentMethod(OrderPaymentMethodEnum.OFFLINE.getValue()); } // 余额支付 if(PayReceivingTypeEnum.BALANCE_RECHARGE_PAY.is(payWay)) { dto.setPaymentMethod(OrderPaymentMethodEnum.BALANCE_RECHARGE_PAY.getValue()); } //券包兑换 if (null != order.getPackageId()){ dto.setPaymentMethod(OrderPaymentMethodEnum.VOUCHER_SERVICE.getValue()); } //余额充值要标记为官费商品 if (OrderTypeEnum.BALANCE_RECHARGE_ORDER.getCode().equals(order.getOrderType())){ dto.setProductType(ProductTypeEnum.OFFICIAL.getValue()); } //将请求参数对象转换成业务对象 return checkOrder(dto); } @Override public CreateBuyCartBaseDTO checkBuyCart(BuyCartRequestDTO dto) { CreateOrderBizDTO createOrderBizDTO = checkOrder(dto); CreateBuyCartBaseDTO result = new CreateBuyCartBaseDTO(); BeanUtils.copyProperties(createOrderBizDTO,result); result.setCartType(dto.getCartType()); return result; } /** * 执行检查 * @param dto * @return */ private CreateOrderBizDTO checkOrder(CreateOrderBizDTO dto){ for (OrderCheckHandler orderCheckHandler : chain) { orderCheckHandler.check(dto); } return dto; } } --------------------------------------------执行器------------------------------------------ package com.evatmaster.biz.center.order.handler.impl; import com.evatmaster.biz.center.order.dto.CreateOrderDetailBizDTO; import com.evatmaster.biz.center.order.handler.OrderCheckHandler; import com.evatmaster.biz.center.order.dto.CreateOrderBizDTO; import com.evatmaster.core.enums.order.OrderTypeEnum; import com.evatmaster.core.exception.ValidateException; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; /** * 订单商品校验,并且填充商品数据 * @author li */ @Service("orderParamCheckHandler") @Slf4j public class OrderCheckParamHandler implements OrderCheckHandler { @Override public void check(CreateOrderBizDTO vo) { for (CreateOrderDetailBizDTO dto : vo.getDetailDTOList()) { if (dto.getSkuId() == null) { throw new ValidateException("请选择够买的服务"); } //最大服务数量校验 增值服务不校验 if (dto.getPurchaseQuantity() > 99 && !dto.isAttachOrder()) { throw new ValidateException("单个服务数量不能超过99"); } //官费订单 if(vo.getOrderType() != null && vo.getOrderType().intValue() == OrderTypeEnum.OFFICIAL_ORDER.getCodeInt() && dto.getPurchaseQuantity() > 1){ throw new ValidateException("官费订单数量不能大于1"); } } } }
使用
@Override
public R<CreateOrderResultVo> createOrder(OrderRequestDTO order) {
String orderNumber = RedisSequence.getOrderSeq(order.getOrderType());
//合规帮手下单来源
if("captain".equals(this.getLoginFrom())){
order.setOrderSource(OrderSourceEnum.COMPLIANCE_HRLPER.getIntValue());
}
//2.校验订单数据、填充订单中的业务商品、活动等数据数据
CreateOrderBizDTO bizDTO = orderCheckBizService.checkOrder(order);
}
---------------------------------------------------
package com.evatmaster.biz.center.order.service;
import com.evatmaster.biz.center.order.dto.CreateOrderBizDTO;
import com.evatmaster.order.api.dto.BuyCartRequestDTO;
import com.evatmaster.order.api.dto.CreateBuyCartBaseDTO;
import com.evatmaster.order.api.dto.OrderRequestDTO;
/**
* 订单校验接口
* @author li
*/
public interface IOrderCheckBizService {
/**
* 创建订单校验
* @param order
* @return
*/
CreateOrderBizDTO checkOrder(OrderRequestDTO order);
/**
* 创建订单校验
* @param dto
* @return
*/
CreateBuyCartBaseDTO checkBuyCart(BuyCartRequestDTO dto);
}
1