基于责任链模式进行订单参数的校验

发布于:2025-06-06 ⋅ 阅读:(18) ⋅ 点赞:(0)

目录

概念

总体分为三步

我们定义责任链模式接口

各个节点的具体逻辑

用户校验器

库存校验器

商品校验器

把责任链编排在一起


概念

责任链模式 是一种行为设计模式

可以通过将一系列处理器按照顺序连接起来

使每个处理器都有机会处理请求

我理解的责任链的实现类似于链表

每个节点跑向下一个节点 执行逻辑后

总体分为三步

  1. 定义责任链接口validator
  2. 实现责任链接口后写不同责任链实现类
  3. 使用一个validatorConfig把不同责任链编排在一起

我们定义责任链模式接口

我们接口中有三个方法

设置下一个校验器

返回下一个校验器

校验逻辑接口

package cn.hollis.nft.turbo.order.validator;

import cn.hollis.nft.turbo.api.order.request.OrderCreateRequest;
import cn.hollis.nft.turbo.order.OrderException;

/**
 * 订单校验
 * 责任链模式
 * @author Hollis
 */
public interface OrderCreateValidator {
    /**
     * 设置下一个校验器
     *
     * @param nextValidator
     */
    public void setNext(OrderCreateValidator nextValidator);

    /**
     * 返回下一个校验器
     *
     * @return
     */
    public OrderCreateValidator getNext();

    /**
     * 校验
     *
     * @param request
     * @throws OrderException 订单异常
     */
    public void validate(OrderCreateRequest request) throws OrderException;
}

这边使用了模版方法的设计模式进行了二次封装

package cn.hollis.nft.turbo.order.validator;

import cn.hollis.nft.turbo.api.order.request.OrderCreateRequest;
import cn.hollis.nft.turbo.order.OrderException;

/**
 * 订单校验
 *
 * @author Hollis
 */
public abstract class BaseOrderCreateValidator implements OrderCreateValidator {

    protected OrderCreateValidator nextValidator;

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

    @Override
    public OrderCreateValidator getNext() {
        return nextValidator;
    }

    /**
     * 校验
     *
     * @param request
     * @throws Exception
     */
    @Override
    public void validate(OrderCreateRequest request) throws OrderException {
        doValidate(request);

        if (nextValidator != null) {
            nextValidator.validate(request);
        }
    }

    /**
     * 校验方法的具体实现
     *
     * @param request
     * @throws OrderException
     */
    protected abstract void doValidate(OrderCreateRequest request) throws OrderException;
}

各个节点的具体逻辑

用户校验器

package cn.hollis.nft.turbo.order.validator;

import cn.hollis.nft.turbo.api.order.request.OrderCreateRequest;
import cn.hollis.nft.turbo.api.user.constant.UserRole;
import cn.hollis.nft.turbo.api.user.constant.UserStateEnum;
import cn.hollis.nft.turbo.api.user.request.UserQueryRequest;
import cn.hollis.nft.turbo.api.user.response.UserQueryResponse;
import cn.hollis.nft.turbo.api.user.response.data.UserInfo;
import cn.hollis.nft.turbo.api.user.service.UserFacadeService;
import cn.hollis.nft.turbo.order.OrderException;

import static cn.hollis.nft.turbo.api.order.constant.OrderErrorCode.*;

/**
 * 用户校验器,继承自 BaseOrderCreateValidator,用于校验订单创建请求中的买家信息。
 * 主要校验买家的角色、状态以及认证情况,若不符合要求则抛出相应的订单异常。
 *
 * @author hollis
 */
public class UserValidator extends BaseOrderCreateValidator {

    /**
     * 用户服务接口,用于查询用户信息。
     */
    private UserFacadeService userFacadeService;

    /**
     * 实现父类的抽象方法,对订单创建请求中的买家信息进行校验。
     *
     * @param request 订单创建请求对象,包含买家信息。
     * @throws OrderException 当买家信息不符合要求时,抛出相应的订单异常。
     */
    @Override
    public void doValidate(OrderCreateRequest request) throws OrderException {
        // 从订单创建请求中获取买家 ID
        String buyerId = request.getBuyerId();
        // 创建用户查询请求对象,将买家 ID 转换为 Long 类型
        UserQueryRequest userQueryRequest = new UserQueryRequest(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 OrderException(BUYER_IS_PLATFORM_USER);
            }

            // 判断买家状态,若买家状态不为激活状态,则抛出买家状态异常
            if (userInfo.getState() != null && !userInfo.getState().equals(UserStateEnum.ACTIVE.name())) {
                throw new OrderException(BUYER_STATUS_ABNORMAL);
            }

            // 判断买家认证情况,若买家未认证,则抛出买家未认证异常
            if (userInfo.getState() != null && !userInfo.getCertification()) {
                throw new OrderException(BUYER_NOT_AUTH);
            }
        }
    }

    /**
     * 有参构造函数,用于注入用户服务接口。
     *
     * @param userFacadeService 用户服务接口实例,用于查询用户信息。
     */
    public UserValidator(UserFacadeService userFacadeService) {
        this.userFacadeService = userFacadeService;
    }

    /**
     * 无参构造函数。
     * 注意:此构造函数未被使用,若后续无使用需求可考虑移除。
     */
    public UserValidator() {
    }
}

库存校验器

package cn.hollis.nft.turbo.order.validator;

import cn.hollis.nft.turbo.api.inventory.request.InventoryRequest;
import cn.hollis.nft.turbo.api.inventory.service.InventoryFacadeService;
import cn.hollis.nft.turbo.api.order.request.OrderCreateRequest;
import cn.hollis.nft.turbo.base.response.SingleResponse;
import cn.hollis.nft.turbo.order.OrderException;

import static cn.hollis.nft.turbo.api.order.constant.OrderErrorCode.INVENTORY_NOT_ENOUGH;

/**
 * 库存校验器,继承自 BaseOrderCreateValidator,用于在订单创建时校验商品库存是否充足。
 * 如果库存不足,将抛出相应的订单异常。
 *
 * @author hollis
 */
public class StockValidator extends BaseOrderCreateValidator {

    /**
     * 库存服务接口,用于查询商品库存信息。
     */
    private InventoryFacadeService inventoryFacadeService;

    /**
     * 实现父类的抽象方法,对订单创建请求进行库存校验。
     *
     * @param request 订单创建请求对象,包含商品相关信息。
     * @throws OrderException 当库存不足时,抛出库存不足的订单异常。
     */
    @Override
    public void doValidate(OrderCreateRequest request) throws OrderException {
        // 创建库存查询请求对象
        InventoryRequest inventoryRequest = new InventoryRequest();
        // 设置要查询的商品 ID
        inventoryRequest.setGoodsId(request.getGoodsId());
        // 设置要查询的商品类型
        inventoryRequest.setGoodsType(request.getGoodsType());
        // 设置要查询的商品标识
        inventoryRequest.setIdentifier(request.getIdentifier());
        // 设置要查询的商品数量,即订单中请求的商品数量
        inventoryRequest.setInventory(request.getItemCount());

        // 调用库存服务接口查询商品库存
        SingleResponse<Integer> response = inventoryFacadeService.queryInventory(inventoryRequest);

        // 如果库存查询失败
        if (!response.getSuccess()) {
            // 抛出库存不足的订单异常
            throw new OrderException(INVENTORY_NOT_ENOUGH);
        }

        // 获取查询到的商品库存数量
        Integer inventory = response.getData();

        // 如果库存数量为 0
        if (inventory == 0) {
            // 抛出库存不足的订单异常
            throw new OrderException(INVENTORY_NOT_ENOUGH);
        }

        // 如果库存数量小于订单请求的商品数量
        if (inventory < request.getItemCount()) {
            // 抛出库存不足的订单异常
            throw new OrderException(INVENTORY_NOT_ENOUGH);
        }
    }

    /**
     * 有参构造函数,用于注入库存服务接口。
     *
     * @param inventoryFacadeService 库存服务接口实例,用于查询商品库存信息。
     */
    public StockValidator(InventoryFacadeService inventoryFacadeService) {
        this.inventoryFacadeService = inventoryFacadeService;
    }

    /**
     * 无参构造函数。
     * 注意:此构造函数未初始化 inventoryFacadeService,若使用可能会导致空指针异常,建议根据实际情况移除或完善。
     */
    public StockValidator() {
    }
}

商品校验器

package cn.hollis.nft.turbo.order.validator;

import cn.hollis.nft.turbo.api.goods.constant.GoodsState;
import cn.hollis.nft.turbo.api.goods.model.BaseGoodsVO;
import cn.hollis.nft.turbo.api.goods.service.GoodsFacadeService;
import cn.hollis.nft.turbo.api.order.request.OrderCreateRequest;
import cn.hollis.nft.turbo.order.OrderException;

import static cn.hollis.nft.turbo.api.order.constant.OrderErrorCode.GOODS_NOT_AVAILABLE;
import static cn.hollis.nft.turbo.api.order.constant.OrderErrorCode.GOODS_PRICE_CHANGED;

/**
 * 商品校验器,继承自 BaseOrderCreateValidator,用于在订单创建时校验商品状态和价格。
 * 若商品不可售或价格发生变化,则抛出相应的订单异常。
 *
 * @author hollis
 */
public class GoodsValidator extends BaseOrderCreateValidator {

    /**
     * 商品服务接口,用于获取商品信息。
     */
    private GoodsFacadeService goodsFacadeService;

    /**
     * 实现父类的抽象方法,对订单创建请求中的商品信息进行校验。
     *
     * @param request 订单创建请求对象,包含商品 ID、商品类型和商品价格等信息。
     * @throws OrderException 当商品不可售或商品价格发生变化时,抛出相应的订单异常。
     */
    @Override
    protected void doValidate(OrderCreateRequest request) throws OrderException {
        // 调用商品服务接口,根据订单请求中的商品 ID 和商品类型获取商品信息
        BaseGoodsVO baseGoodsVO = goodsFacadeService.getGoods(request.getGoodsId(), request.getGoodsType());

        // 如果商品状态既不是在售状态,也不是已售罄状态,则认为商品不可售
        // 说明:包含 SOLD_OUT 状态是因为商品查询接口会获取 Redis 中的最新库存,
        // 下单时 Redis 库存可能已扣减至 0
        if (baseGoodsVO.getState() != GoodsState.SELLING && baseGoodsVO.getState() != GoodsState.SOLD_OUT) {
            // 抛出商品不可售的订单异常
            throw new OrderException(GOODS_NOT_AVAILABLE);
        }

        // 比较商品的实际价格和订单请求中的商品价格
        if (baseGoodsVO.getPrice().compareTo(request.getItemPrice()) != 0) {
            // 若价格不一致,抛出商品价格已变更的订单异常
            throw new OrderException(GOODS_PRICE_CHANGED);
        }
    }

    /**
     * 有参构造函数,用于注入商品服务接口。
     *
     * @param goodsFacadeService 商品服务接口实例,用于获取商品信息。
     */
    public GoodsValidator(GoodsFacadeService goodsFacadeService) {
        this.goodsFacadeService = goodsFacadeService;
    }

    /**
     * 无参构造函数。
     * 注意:此构造函数未初始化 goodsFacadeService,使用时可能会导致空指针异常,
     * 若后续无使用需求,可考虑移除。
     */
    public GoodsValidator() {
    }
}

把责任链编排在一起

调用每一个责任链节点的setNext方法

把下一个责任链节点对象放进去

类似于调用链表的set方法

package cn.hollis.nft.turbo.order.domain.validator;

import cn.hollis.nft.turbo.order.validator.GoodsBookValidator;
import cn.hollis.nft.turbo.order.validator.GoodsValidator;
import cn.hollis.nft.turbo.order.validator.OrderCreateValidator;
import cn.hollis.nft.turbo.order.validator.UserValidator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * 订单创建校验器配置
 *
 * @author hollis
 */
@Configuration
public class OrderCreateValidatorConfig {

    @Autowired
    private GoodsValidator goodsValidator;

    @Autowired
    private UserValidator userValidator;

    @Autowired
    private GoodsBookValidator goodsBookValidator;

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