购物车微服务远程调用商品微服务编码实践

按照上述步骤对购物车微服务进行编码后,代码中依然会被标红。被标红的代码及注释如下:

@Override
/**
 * 添加商品至购物车
 */
public String saveNewBeeMallCartItem(SaveCartItemParam saveCartItemParam, Long userId) {
    NewBeeMallShoppingCartItem temp = newBeeMallShoppingCartItemMapper.selectByUserIdAndGoodsId(userId, saveCartItemParam.getGoodsId());
    if (temp != null) {
        //若已存在,则修改改记录
        //NewBeeMallException.fail(ServiceResultEnum.SHOPPING_CART_ITEM_EXIST_ERROR.getResult());
    }
    //根据 goodsId 参数查询数据库中对应的商品数据
    NewBeeMallGoods newBeeMallGoods = newBeeMallGoodsMapper.selectByPrimaryKey(saveCartItemParam.getGoodsId());
    //商品为空
    if (newBeeMallGoods == null) {
        return ServiceResultEnum.GOODS_NOT_EXIST.getResult();
    }
    //省略部分代码

    //保存记录
    if (newBeeMallShoppingCartItemMapper.insertSelective(newBeeMallShoppingCartItem) > 0) {
        return ServiceResultEnum.SUCCESS.getResult();
    }
    return ServiceResultEnum.DB_ERROR.getResult();
}

/**
 * VO 实体封装
 */
private List<NewBeeMallShoppingCartItemVO> getNewBeeMallShoppingCartItemVOS(List<NewBeeMallShoppingCartItemVO> newBeeMallShoppingCartItemVOS, List<NewBeeMallShoppingCartItem> newBeeMallShoppingCartItems) {
    if (!CollectionUtils.isEmpty(newBeeMallShoppingCartItems)) {
        // 查询商品信息并进行数据转换
        List<Long> newBeeMallGoodsIds = newBeeMallShoppingCartItems.stream()
                .map(NewBeeMallShoppingCartItem::getGoodsId).collect(Collectors.toList());
        // 根据 goodsIds 列表查询数据库中对应的商品列表数据
        List<NewBeeMallGoods> newBeeMallGoods = newBeeMallGoodsMapper.selectByPrimaryKeys(newBeeMallGoodsIds);
        Map<Long, NewBeeMallGoods> newBeeMallGoodsMap = new HashMap<>();
        // 省略部分代码
    }
    return newBeeMallShoppingCartItemVOS;
}

在添加商品至购物车和查询购物车列表数据时,需要根据 goodId 参数或 goodsIds 链表查询数据库中的一条或多条商品数据,之后才能执行后续的业务逻辑。而购物车微服务未连接商品表所在的数据库,无法直接通过 GoodsMapper 去查询对应的商品数据,所以这部分代码会被标红。

因此,这里必须进行商品数据查询代码的改造,由原本直接查询商品表改为远程调用商品微服务中的接口来完成这个逻辑。购物车微服务不仅要与用户微服务通信,还要与商品微服务通信。这里的代码改造步骤如下。

第一步,引入 goods-api 依赖。

打开 newbee-mall-cloud-shop-cart-web 工程下的 pom.xml 文件,增加与商品微服务远程通信所需的 newbee-mall-cloud-goods-api 模块,新增依赖配置如下:

<dependency>
    <groupId>ltd.goods.newbee.cloud</groupId>
    <artifactId>newbee-mall-cloud-goods-api</artifactId>
    <version>0.0.1-SNAPSHOT</version>
</dependency>

第二步,增加关于商品微服务中 FeignClient 类的配置。

打开 newbee-mall-cloud-shop-cart-web 工程,对启动类 NewBeeMallCloudShopCartServiceApplication 中的 @EnableFeignClients 注解进行修改,增加对 NewBeeCloudGoodsServiceFeign 类的声明,代码如下:

@EnableFeignClients(basePackageClasses={ltd.user.cloud.newbee.openfeign.NewBeeCloudUserServiceFeign.class, ltd.goods.cloud.newbee.openfeign.NewBeeCloudGoodsServiceFeign.class})

接下来就可以直接使用 NewBeeCloudGoodsServiceFeign 类与商品微服务进行远程通信了。

第三步,修改商品数据判断逻辑的代码。

打开 newbee-mall-cloud-shop-cart-web 工程,修改 NewBeeMallIndexConfigServiceImpl 类中商品数据判断的逻辑代码。删除原本直接查询商品数据的代码,之后注入 NewBeeCloudGoodsServiceFeign 类,并通过调用商品微服务来获取商品数据,代码如下:

@Autowired
private NewBeeCloudGoodsServiceFeign goodsService;

@Override
/**
 * 添加商品至购物车
 */
public String saveNewBeeMallCartItem(SaveCartItemParam saveCartItemParam, Long userId) {
    NewBeeMallShoppingCartItem temp = newBeeMallShoppingCartItemMapper.selectByUserIdAndGoodsId(userId, saveCartItemParam.getGoodsId());
    if (temp != null) {
        // 已经存在,则修改该记录
        NewBeeMallException.fail(ServiceResultEnum.SHOPPING_CART_ITEM_EXIST_ERROR.getResult());
    }
    // 根据goodsId参数调用商品微服务的接口,查询对应的商品数据
    Result<NewBeeMallGoodsDTO> goodsDetailResult = goodsService.getGoodsDetail(saveCartItemParam.getGoodsId());
    // 商品为空
    if (goodsDetailResult == null || goodsDetailResult.getResultCode() != 200) {
        return ServiceResultEnum.GOODS_NOT_EXIST.getResult();
    }
    // 省略部分代码

    // 保存记录
    if (newBeeMallShoppingCartItemMapper.insertSelective(newBeeMallShoppingCartItem) > 0) {
        return ServiceResultEnum.SUCCESS.getResult();
    }
    return ServiceResultEnum.DB_ERROR.getResult();
}

/**
 * VO 实体封装
 */
private List<NewBeeMallShoppingCartItemVO> getNewBeeMallShoppingCartItemVOS(
        List<NewBeeMallShoppingCartItem> newBeeMallShoppingCartItems,
        List<NewBeeMallShoppingCartItem> newBeeMallShoppingCartItems) {
    if (!CollectionUtils.isEmpty(newBeeMallShoppingCartItems)) {
        List<Long> newBeeMallGoodsIds = newBeeMallShoppingCartItems.stream().
                map(NewBeeMallShoppingCartItem::getGoodsId).collect(Collectors.toList());
        // 根据goodsIds 批量调用商品微服务中的接口,查询对应的商品列表数据
        Result<List<NewBeeMallGoodsDTO>> newBeeMallGoodsDTOResult =
                goodsService.listByGoodsIds(newBeeMallGoodsIds);
        // 远程调用,返回的数据为空
        if (newBeeMallGoodsDTOResult == null || newBeeMallGoodsDTOResult.getResultCode() != 200) {
            NewBeeMallException.fail(ServiceResultEnum.GOODS_NOT_EXIST.getResult());
        }
        Map<Long, NewBeeMallGoodsDTO> newBeeMallGoodsDTOMap = new HashMap<>();
        List<NewBeeMallGoodsDTO> newBeeMallGoodsDTOs = newBeeMallGoodsDTOResult.getData();
        getData();
        // 省略部分代码
    }
    return newBeeMallShoppingCartItemVOS;
}

这里调用的就是在商品微服务中暴露的 /goods/admin/goodsDetail 接口和 /goods/admin/listByGoodsIds 接口,根据参数或链表查询对应的一条或多条商品数据。