微服务(八)—— 订单模块(backend-order)

上一篇: 微服务(七)—— 收货地址模块(backend-shipping).

一、创建项目

首先创建一个SpringBoot项目,具体创建过程和 微服务(三)—— 用户模块(backend-user).一样。

二、项目结构

1.目录结构

在这里插入图片描述
项目结构就是Controller、Service、Dao三层结构,由于订单和购物车耦合度比较高,所以我就将购物和订单业务放在一个模块了。

1.1购物车

(1)Controller层
主要是提供给前端的增删改查接口,完整的类如下:

package com.aiun.order.controller;
/**
 * 购物车控制层
 * @author lenovo
 */
@Api(tags = "购物车接口")
@RestController
@RequestMapping("/cart/")
public class CartController {
   
    @Autowired
    private ICartService iCartService;
    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    /**
     * 添加购物车功能
     * @param productId 产品id
     * @param count 产品个数
     * @return 封装好的购物车 VO
     */
    @GetMapping("add")
    @ApiOperation(value = "购物车添加商品功能")
    public ServerResponse<CartVO> add(HttpServletRequest request, Integer productId, Integer count) {
   
        ServerResponse hasLogin = loginHasExpired(request);

        if (hasLogin.isSuccess()) {
   
            User user = (User) hasLogin.getData();
            return iCartService.add(user.getId(), productId, count);
        }

        return hasLogin;
    }
    /**
     * 更新购物车商品功能
     * @param productId 产品 id
     * @param count 产品个数
     * @return 封装好的购物车 VO
     */
    @PostMapping("update")
    @ApiOperation(value = "更新购物车商品功能")
    public ServerResponse<CartVO> update(HttpServletRequest request, Integer productId, Integer count) {
   
        ServerResponse hasLogin = loginHasExpired(request);

        if (hasLogin.isSuccess()) {
   
            User user = (User) hasLogin.getData();
            return iCartService.update(user.getId(), productId, count);
        }

        return hasLogin;
    }

    /**
     * 删除购物车商品
     * @param productIds 多个产品的id
     * @return 封装好的购物车 VO
     */
    @DeleteMapping("delete_product")
    @ApiOperation(value = "删除购物车商品")
    public ServerResponse<CartVO> deleteProduct(HttpServletRequest request, String productIds) {
   
        ServerResponse hasLogin = loginHasExpired(request);

        if (hasLogin.isSuccess()) {
   
            User user = (User) hasLogin.getData();
            return iCartService.deleteProduct(user.getId(), productIds);
        }

        return hasLogin;
    }

    /**
     * 查询购物车商品列表
     * @return 封装好的购物车 VO
     */
    @PostMapping("list")
    @ApiOperation(value = "查询购物车商品列表")
    public ServerResponse<CartVO> list(HttpServletRequest request) {
   
        ServerResponse hasLogin = loginHasExpired(request);

        if (hasLogin.isSuccess()) {
   
            User user = (User) hasLogin.getData();
            return iCartService.list(user.getId());
        }

        return hasLogin;
    }

    /**
     * 全选
     * @return 封装好的购物车 VO
     */
    @PostMapping("select_all")
    @ApiOperation(value = "购物车全选")
    public ServerResponse<CartVO> selectAll(HttpServletRequest request) {
   
        ServerResponse hasLogin = loginHasExpired(request);

        if (hasLogin.isSuccess()) {
   
            User user = (User) hasLogin.getData();
            return iCartService.selectOrUnSelect(user.getId(), null, CartConst.Cart.CHECKED);
        }
        return hasLogin;
    }

    /**
     * 反选
     * @return 封装好的购物车 VO
     */
    @PostMapping("un_select_all")
    @ApiOperation(value = "反选")
    public ServerResponse<CartVO> unSelectAll(HttpServletRequest request) {
   
        ServerResponse hasLogin = loginHasExpired(request);

        if (hasLogin.isSuccess()) {
   
            User user = (User) hasLogin.getData();
            return iCartService.selectOrUnSelect(user.getId(), null, CartConst.Cart.UN_CHECKED);
        }
        return hasLogin;
    }

    /**
     * 单独选
     * @return 封装好的购物车 VO
     */
    @PostMapping("select")
    @ApiOperation(value = "单独选")
    public ServerResponse<CartVO> select(HttpServletRequest request, Integer productId) {
   
        ServerResponse hasLogin = loginHasExpired(request);

        if (hasLogin.isSuccess()) {
   
            User user = (User) hasLogin.getData();
            return iCartService.selectOrUnSelect(user.getId(), productId, CartConst.Cart.CHECKED);
        }
        return hasLogin;
    }

    /**
     * 单独反选
     * @return 封装好的购物车 VO
     */
    @PostMapping("un_select")
    @ResponseBody
    @ApiOperation(value = "单独反选")
    public ServerResponse<CartVO> unSelect(HttpServletRequest request, Integer productId) {
   
        ServerResponse hasLogin = loginHasExpired(request);

        if (hasLogin.isSuccess()) {
   
            User user = (User) hasLogin.getData();
            return iCartService.selectOrUnSelect(user.getId(), productId, CartConst.Cart.UN_CHECKED);
        }
        return hasLogin;
    }

    /**
     * 查询当前用户购物车里产品的数量
     * @return 返回产品的数量
     */
    @PostMapping("get_cart_product_count")
    @ResponseBody
    @ApiOperation(value = "查询当前用户购物车里产品的数量")
    public ServerResponse<Integer> getCartProductCount(HttpServletRequest request) {
   
        ServerResponse hasLogin = loginHasExpired(request);

        if (hasLogin.isSuccess()) {
   
            User user = (User) hasLogin.getData();
            return iCartService.getCartProductCount(user.getId());
        }
        return hasLogin;
    }

    /**
     * 判断用户登录是否过期
     */
    private ServerResponse<User> loginHasExpired(HttpServletRequest request) {
   
        String key = request.getHeader(UserConst.AUTHORITY);
        ValueOperations<String, String> valueOperations = redisTemplate.opsForValue();
        String value = valueOperations.get(key);
        if (StringUtils.isEmpty(value)) {
   
            return ServerResponse.createByErrorMessage(ResponseCode.NEED_LOGIN.getCode(), ResponseCode.NEED_LOGIN.getDesc());
        }
        User user = JsonUtils.jsonStr2Object(value, User.class);
        if (!key.equals(user.getUsername())) {
   
            return ServerResponse.createByErrorMessage(ResponseCode.NEED_LOGIN.getCode(), ResponseCode.NEED_LOGIN.getDesc());
        }
        valueOperations.set(key, value, 1, TimeUnit.HOURS);
        return ServerResponse.createBySuccess(user);
    }
}

该类里面有一个私有的方法,是用于用户权限验证的,具体看:微服务(十)—— 单点登录.
(2)Service层
该层是业务的主要实现,下面看一下Service的实现类:

package com.aiun.order.service.impl;
/**
 * @author lenovo
 */
@Service("iCartService")
public class CartServiceImpl implements ICartService {
   
    @Autowired
    private CartMapper cartMapper;
    @Autowired
    private ProductFeign productFeign;
    @Value("mageHost")
    private String mageHost;

    @Override
    public ServerResponse<CartVO> add(Integer userId, Integer productId, Integer count) {
   
        if (productId == null || count == null) {
   
            return ServerResponse.createByErrorMessage(ResponseCode.ILLEGAL_ARGUMENT.getCode(), ResponseCode.ILLEGAL_ARGUMENT.getDesc());
        }

        Cart cart = cartMapper.selectCartByUserIdProductId(userId, productId);
        if (cart == null) {
   
            //产品不在购物车里,需要新增一个这个产品的记录
            Cart cartItem = new Cart();
            cartItem.setQuantity(count)
                    .setChecked(CartConst.Cart.CHECKED)
                    .setProductId(productId)
                    .setUserId(userId);
            int resultCount = cartMapper.insert(cartItem);
            if (resultCount == 0){
   
                return ServerResponse.createByErrorMessage("添加购物车失败");
            }
        } else {
   
            //这个产品已经在购物车里了
            //需要将数量相加
            count = cart.getQuantity() + count;
            cart.setQuantity(count);
            cartMapper.updateByPrimaryKeySelective(cart);
        }
        return this.list(userId);
    }

    @Override
    public ServerResponse<CartVO> update(Integer userId, Integer productId, Integer count) {
   
        if (productId == null || count == null) {
   
            return ServerResponse.createByErrorMessage(ResponseCode.ILLEGAL_ARGUMENT.getCode(), ResponseCode.ILLEGAL_ARGUMENT.getDesc());
        }
        Cart cart = cartMapper.selectCartByUserIdProductId(userId, productId);
        if (cart != null) {
   
            cart.setQuantity(count);
        }
        int resoultCount = cartMapper.updateByPrimaryKeySelective(cart);
        if (resoultCount == 0) {
   
            return ServerResponse.createByErrorMessage("更新购物车失败");
        }
        return this.list(userId);
    }

    @Override
    public ServerResponse<CartVO> deleteProduct(Integer userId, String productIds) {
   
        List<String> productList = new ArrayList<>();
        String[] productIdStrings = productIds.split(",");
        for(String id : productIdStrings) {
   
            productList.add(id);
        }
        if (productList.isEmpty()) {
   
            return ServerResponse.createByErrorMessage(ResponseCode.ILLEGAL_ARGUMENT.getCode(), ResponseCode.ILLEGAL_ARGUMENT.getDesc());
        }
        cartMapper.deleteByUserIdProductIds(userId, productList);
        return this.list(userId);
    }

    @Override
    public ServerResponse<CartVO> list(Integer userId) {
   
        CartVO cartVo = this.getCartVoLimit(userId);
        return ServerResponse.createBySuccess(cartVo);
    }

    @Override
    public ServerResponse<CartVO> selectOrUnSelect(Integer userId, Integer productId, Integer checked) {
   
        cartMapper.checkedOrUnCheckedProduct(userId, productId, checked);
        return this.list(userId);
    }

    @Override
    public ServerResponse<Integer> getCartProductCount(Integer userId) {
   
        if (userId == null) {
   
            return ServerResponse.createBySuccess(0);
        }

        return ServerResponse.createBySuccess(cartMapper.selectCartProductCount(userId));
    }

    /**
     * 封装前端用到的购物车数据
     * @param userId 用户 id
     * @return 封装的购物车 VO
     */
    private CartVO getCartVoLimit(Integer userId) {
   
        CartVO cartVo = new CartVO();
        List<Cart> cartList = cartMapper.selectCartByUserId(userId);
        List<CartProductVO> cartProductVOList = Lists.newArrayList();

        BigDecimal cartTotalPrice = new BigDecimal("0");
        if (!cartList.isEmpty()) {
   
            for (Cart cartItem : cartList) {
   
                CartProductVO cartProductVo = new CartProductVO();
                cartProductVo.setId(cartItem.getId())
                             .setProductId(cartItem.getProductId())
                             .setUserId(cartItem.getUserId());

                Product product = productFeign.findById(cartItem.getProductId());
                if (product != null) {
   
                    cartProductVo.setProductMainImage(product.getMainImage())
                                 .setProductName(product.getName())
                                 .setProductPrice(product.getPrice())
                                 .setProductStatus(product.getStatus())
                                 .setProductSubtitle(product.getSubtitle())
                                 .setProductStock(product.getStock());
                    //判断库存
                    int buyLimitCount = 0;
                    if (product.getStock() >= cartItem.getQuantity()) {
   
                        buyLimitCount = cartItem.getQuantity();
                        cartProductVo.setLimitQuantity(CartConst.LIMIT_NUM_SUCCESS);
                    } else {
   
                        buyLimitCount = product.getStock();
                        cartProductVo.setLimitQuantity(CartConst.LIMIT_NUM_FAIL);
                        //购物车中更新有效库存
                        Cart cartForQuantity = new Cart();
                        cartForQuantity.setId(cartItem.getId())
                                       .setQuantity(buyLimitCount);
                        cartMapper.updateByPrimaryKeySelective(cartForQuantity);
                    }
                    cartProductVo.setQuantity(buyLimitCount);
                    //计算总价
                    cartProductVo.setProductTotalPrice(BigDecimalUtils.mul(product.getPrice().doubleValue(), cartProductVo.getQuantity()))
                                 .setProductChecked(cartItem.getChecked());
                }
                if (cartItem.getChecked() == CartConst.Cart.CHECKED) {
   
                    //如果已经勾选,增加到整个购物车的总价中
                    cartTotalPrice = BigDecimalUtils.add(cartTotalPrice.doubleValue(), cartProductVo.getProductTotalPrice().doubleValue());

                }
                cartProductVOList.add(cartProductVo);
            }
        }
        cartVo.setCartTotalPrice(cartTotalPrice)
              .setCartProductVOList(cartProductVOList)
              .setAllChecked(this.getAllCheckedStatus(userId))
              .setImageHost(mageHost);

        return cartVo;
    }

    /**
     * 查询是否是全选中状态
     * @param userId 用户 id
     * @return 产品是否是选中状态
     */
    private boolean getAllCheckedStatus(Integer userId) {
   
        if (userId == null) {
   
            return false;
        }
        return cartMapper.selectCartProductCheckedStatusByUserId(userId) == 0;
    }
}

这个类主要是订单的创建,以及查询商品的选中状态,然后计算价格。
计算价格的时候需要注意精度丢失问题,这里选用BigDecimal类,通过字符串的方式构造对象可以防止精度丢失。
(3)Dao层
首先是Mapper接口层

package com.aiun.order.mapper;
@Mapper
@Component
public interface CartMapper {
   
    /**
     * 通过主键删除购物车
     * @param id 主键
     * @return 影响的记录行
     */
    int deleteByPrimaryKey(Integer id);

    /**
     * 插入购物车信息
     * @param record 购物车信息
     * @return 影响的记录行
     */
    int insert(@Param("record") Cart record);

    /**
     * 有选择的插入购物车信息
     * @param record 购物车信息
     * @return 影响的记录行
     */
    int insertSelective(@Param("record") Cart record);

    /**
     * 通过主键有选择的插入
     * @param id 主键
     * @return 购物车信息
     */
    Cart selectByPrimaryKey(Integer id);

    /**
     * 通过主键有选择的更新购物车数据
     * @param record 购物车
     * @return 影响的记录行
     */
    int updateByPrimaryKeySelective(@Param("record") Cart record);

    /**
     * 通过主键更新购物车数据
     * @param record 购物车信息
     * @return 影响的记录行
     */
    int updateByPrimaryKey(@Param("record") Cart record);

    /**
     * 根据用户Id查询商品选中状态
     * @param userId 用户 id
     * @return 所有购物车信息
     */
    List<Cart> selectCheckedCartByUserId(Integer userId);

    /**
     * 通过用户id和产品id查询购物车
     * @param userId 用户 id
     * @param productId 产品 id
     * @return 购物车信息
     */
    Cart selectCartByUserIdProductId(@Param("userId") Integer userId, @Param("productId") Integer productId);

    /**
     * 通过用户id查询购物车
     * @param userId 用户 id
     * @return 购物车信息
     */
    List<Cart> selectCartByUserId(Integer userId);

    /**
     * 根据用户id和产品id删除
     * @param userId 用户 id
     * @param productIds 需要删除的产品 id
     * @return 影响的记录行
     */
    int deleteByUserIdProductIds(@Param("userId") Integer userId, @Param("productIds") List<String> productIds);

    /**
     * 更新购物车产品的选中状态
     * @param userId 用户 id
     * @param productId 需要选中的产品 id
     * @param checked 选中状态
     * @return 影响的记录行
     */
    int checkedOrUnCheckedProduct(@Param("userId") Integer userId, @Param("productId") Integer productId, @Param("checked") Integer checked);

    /**
     * 获取购物车产品数量
     * @param userId 用户 id
     * @return 影响的记录行
     */<
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值