Java电商项目面试--订单模块

面试:订单模块技术要点
技术要点:
1、安全漏洞解决方案
2、订单号生成规则
3、强大的常量、枚举设计

一、前台创建订单
Controller层:

//创建订单
@RequestMapping("create.do")
@ResponseBody
public ServerResponse create(HttpSession session, Integer shippingId){
    User user = (User)session.getAttribute(Const.CURRENT_USER);
    if(user ==null)
        return ServerResponse.createByErrorCodeMessage(ResponseCode.NEED_LOGIN.getCode(),ResponseCode.NEED_LOGIN.getDesc());
    return iOrderService.createOrder(user.getId(),shippingId);
}

Service层:

//创建订单
public  ServerResponse createOrder(Integer userId,Integer shippingId){
    //从购物车中获取已经被勾选的商品
    List cartList = cartMapper.selectCheckedCartByUserId(userId);
    //校验并封装一下
    ServerResponse serverResponse = this.getCartOrderItem(userId,cartList);
    if(!serverResponse.isSuccess())
        return serverResponse;
    List orderItemList = (List)serverResponse.getData();
    //计算这个订单的总价
    BigDecimal payment = this.getOrderTotalPrice(orderItemList);
    //生成订单
    Order order = this.assembleOrder(userId,shippingId,payment);
    if(order == null)
        return ServerResponse.createByErrorMessage("生成订单错误");
    if(CollectionUtils.isEmpty(orderItemList))
        return ServerResponse.createByErrorMessage("购物车为空");
    //每一项都生成订单号
    for(OrderItem orderItem : orderItemList)
        //设置订单号
        orderItem.setOrderNo(order.getOrderNo());

    //mybatis 批量插入
    orderItemMapper.batchInsert(orderItemList);
    //生成成功,我们要减少我们产品的库存
    this.reduceProductStock(orderItemList);
    //清空一下购物车
    this.cleanCart(cartList);
    //返回给前端数据
    OrderVo orderVo = assembleOrderVo(order,orderItemList);
    return ServerResponse.createBySuccess(orderVo);
}
//校验并且封装一下
private ServerResponse getCartOrderItem(Integer userId,List cartList){
    List orderItemList = Lists.newArrayList();
    //购物车中已经勾选的商品是空的
    if(CollectionUtils.isEmpty(cartList))
        return ServerResponse.createByErrorMessage("购物车为空");
    /*********校验购物车的数据,包括产品的状态和数量********/
    for(Cart cartItem : cartList){
        OrderItem orderItem = new OrderItem();
        //查出商品
        Product product = productMapper.selectByPrimaryKey(cartItem.getProductId());
        //查看产品销售状态
        if(Const.ProductStatusEnum.ON_SALE.getCode() != product.getStatus()){
            return ServerResponse.createByErrorMessage("产品"+product.getName()+"不是在线售卖状态");
        }
        //校验库存
        if(cartItem.getQuantity() > product.getStock()){
            return ServerResponse.createByErrorMessage("产品"+product.getName()+"库存不足");
        }
        /**********将已经勾选的购物车中的商品组装一下***********/
        orderItem.setUserId(userId);
        orderItem.setProductId(product.getId());
        orderItem.setProductName(product.getName());
        orderItem.setProductImage(product.getMainImage());
        orderItem.setCurrentUnitPrice(product.getPrice());
        orderItem.setQuantity(cartItem.getQuantity());
        //此项商品的总价
        orderItem.setTotalPrice(BigDecimalUtil.mul(product.getPrice().doubleValue(),cartItem.getQuantity()));
        orderItemList.add(orderItem);
    }
    return ServerResponse.createBySuccess(orderItemList);
}
//此函数用于计算订单总价
private BigDecimal getOrderTotalPrice(List orderItemList){
    BigDecimal payment = new BigDecimal("0");
    for(OrderItem orderItem : orderItemList)
        payment = BigDecimalUtil.add(payment.doubleValue(),orderItem.getTotalPrice().doubleValue());  //每一项的总价都加进来
    return payment;
}
//此函数用于生成订单号
private long generateOrderNo(){
    long currentTime = System.currentTimeMillis();
    return currentTime + new Random().nextInt(100);
}
//此函数用于生成订单
private Order assembleOrder(Integer userId,Integer shippingId,BigDecimal payment){
    Order order = new Order();
    //生成订单号
    long orderNo = this.generateOrderNo();
    order.setOrderNo(orderNo);
    //支付状态,未付款
    order.setStatus(Const.OrderStatusEnum.NO_PAY.getCode());
    order.setPostage(0);        //运费设置为0
    //支付方式,在线支付
    order.setPaymentType(Const.PaymentTypeEnum.ONLINE_PAY.getCode());
    order.setPayment(payment);

    order.setUserId(userId);    //购买的用户的ID
    order.setShippingId(shippingId);   //发货地址的ID
    //发货时间等等
    //付款时间等等
    //插入订单
    int rowCount = orderMapper.insert(order);
    if(rowCount > 0)
        return order;
    return null;
} 
//减少商品的库存
private void reduceProductStock(List orderItemList){
    for(OrderItem orderItem : orderItemList){
        Product product = productMapper.selectByPrimaryKey(orderItem.getProductId());
        product.setStock(product.getStock()-orderItem.getQuantity());
        productMapper.updateByPrimaryKeySelective(product);
    }
}
//清空购物车
private void cleanCart(List cartList){
    for(Cart cart : cartList)
        cartMapper.deleteByPrimaryKey(cart.getId());
}
//将订单包装一下
private OrderVo assembleOrderVo(Order order,List orderItemList){   //order:订单,orderItemList:订单明细
    OrderVo orderVo = new OrderVo();
    orderVo.setOrderNo(order.getOrderNo());
    orderVo.setPayment(order.getPayment());
    orderVo.setPaymentType(order.getPaymentType());
    orderVo.setPaymentTypeDesc(Const.PaymentTypeEnum.codeOf(order.getPaymentType()).getValue());
    orderVo.setPostage(order.getPostage());
    orderVo.setStatus(order.getStatus());
    orderVo.setStatusDesc(Const.OrderStatusEnum.codeOf(order.getStatus()).getValue());

    orderVo.setShippingId(order.getShippingId());
    Shipping shipping = shippingMapper.selectByPrimaryKey(order.getShippingId());
    if(shipping != null){
        orderVo.setReceiverName(shipping.getReceiverName());
        orderVo.setShippingVo(assembleShippingVo(shipping));
    }

    orderVo.setPaymentTime(DateTimeUtil.dateToStr(order.getPaymentTime()));
    orderVo.setSendTime(DateTimeUtil.dateToStr(order.getSendTime()));
    orderVo.setEndTime(DateTimeUtil.dateToStr(order.getEndTime()));
    orderVo.setCreateTime(DateTimeUtil.dateToStr(order.getCreateTime()));
    orderVo.setCloseTime(DateTimeUtil.dateToStr(order.getCloseTime()));
    orderVo.setImageHost(PropertiesUtil.getProperty("ftp.server.http.prefix"));

    List orderItemVoList = Lists.newArrayList();

    for(OrderItem orderItem : orderItemList){
        OrderItemVo orderItemVo = assembleOrderItemVo(orderItem);
        orderItemVoList.add(orderItemVo);
    }
    orderVo.setOrderItemVoList(orderItemVoList);   //订单的明细
    return orderVo;
}
//封装收货地址
private ShippingVo assembleShippingVo(Shipping shipping){
    ShippingVo shippingVo = new ShippingVo();
    shippingVo.setReceiverName(shipping.getReceiverName());
    shippingVo.setReceiverAddress(shipping.getReceiverAddress());
    shippingVo.setReceiverProvince(shipping.getReceiverProvince());
    shippingVo.setReceiverCity(shipping.getReceiverCity());
    shippingVo.setReceiverDistrict(shipping.getReceiverDistrict());
    shippingVo.setReceiverMobile(shipping.getReceiverMobile());
    shippingVo.setReceiverZip(shipping.getReceiverZip());
    shippingVo.setReceiverPhone(shippingVo.getReceiverPhone());
    return shippingVo;
}

Mapper.xml:

<select id="selectCheckedCartByUserId" parameterType="int" resultMap="BaseResultMap">
    SELECT
    <include refid="Base_Column_List"/>
    from mmall_cart
    where user_id = #{userId}
    and checked = 1
select>


<insert id="batchInsert" parameterType="list">
  insert into mmall_order_item (id, order_no,user_id, product_id,
  product_name, product_image, current_unit_price,
  quantity, total_price, create_time,
  update_time)
  values
  <foreach collection="orderItemList" index="index" item="item" separator=",">
  (
    #{item.id},#{item.orderNo},#{item.userId},#{item.productId},#{item.productName},#{item.productImage},#{item.currentUnitPrice},#{item.quantity},#{item.totalPrice},now(),now()
  )
  foreach>
insert>

强大的常量、枚举设计
用接口定义常量最大的好处是有一个group的概念,很简单,我们相关的常量放在一个interface里,以后维护的成本会低很多。例如课程里的一些具有组概念的,就放在一个interface里,而相对独立的常量就用类常量。
枚举的话,key-value,有状态码,还有对应的中文说明,例如我们的订单状态。

public class Const {
    public enum OrderStatusEnum{
        CANCELED(0,"已取消"),
        NO_PAY(10,"未支付"),
        PAID(20,"已付款"),
        SHIPPED(40,"已发货"),
        ORDER_SUCCESS(50,"订单完成"),
        ORDER_CLOSE(60,"订单关闭");

        OrderStatusEnum(int code,String value){
            this.code = code;
            this.value = value;
        }
        private String value;
        private int code;

        public String getValue() {
            return value;
        }

        public int getCode() {
            return code;
        }

        public static OrderStatusEnum codeOf(int code){
            for(OrderStatusEnum orderStatusEnum : values()){
                if(orderStatusEnum.getCode() == code){
                    return orderStatusEnum;
                }
            }
            throw new RuntimeException("么有找到对应的枚举");
        }
    }
}

订单号生成规则
1.订单号无重复性;
2.如果方便客服的话,最好是“日期+自增数”样式的订单号,客服一看便知道订单是否在退货保障期限内容;
3.订单号长度尽量保持短(10位以内),方便用户,尤其电话投诉时,长的号码报错几率高,影响客服效率;

//此函数用于生成订单号
private long generateOrderNo(){
    long currentTime = System.currentTimeMillis();
    return currentTime + new Random().nextInt(100);
}

Java面试的完整博客目录如下:Java笔试面试目录

转载请标明出处,原文地址:https://blog.csdn.net/weixin_41835916 如果觉得本文对您有帮助,请点击支持一下,您的支持是我写作最大的动力,谢谢。

你可能感兴趣的:(Java笔试面试,Java笔试面试)