Java 电商项⽬⾯试--订单模块
⾯试:订单模块技术要点
技术要点: 1、安全漏洞解决⽅案 2、订单号⽣成规则 3、强⼤的常量、枚举设计
⼀、前台创建订单
Controller层:Service层:
//创建订单
@RequestMapping ("create.do")
@ResponBody
public ServerRespon create (HttpSession ssion, Integer shippingId){
Ur ur = (Attribute(Const.CURRENT_USER);
if (ur ==null )
return ateByErrorCodeMessage(ResponCode.Code(),ResponCode.Desc()); return Id(),shippingId);}
//创建订单
public ServerRespon createOrder(Integer urId,Integer shippingId){
//从购物车中获取已经被勾选的商品散学的近义词
List<Cart> cartList = cartMapper .lectCheckedCartByUrId (urId);
//校验并封装⼀下
ServerRespon rverRespon = this .getCartOrderItem (urId,cartList);
if(!rverRespon .isSuccess ())
return rverRespon ;
List<OrderItem> orderItemList = (List<OrderItem>)rverRespon .getData ();
//计算这个订单的总价
BigDecimal payment = this .getOrderTotalPrice (orderItemList);
//⽣成订单
Order order = this .asmbleOrder (urId,shippingId,payment);
if(order == null)
return ServerRespon .createByErrorMessage ("⽣成订单错误");
if(CollectionUtils .isEmpty (orderItemList))
return ServerRespon .createByErrorMessage ("购物车为空");
艺术活动图片//每⼀项都⽣成订单号
for(OrderItem orderItem : orderItemList)
//设置订单号
orderItem .tOrderNo (order .getOrderNo ());
游戏精神//mybatis 批量插⼊
orderItemMapper .batchInrt (orderItemList);
//⽣成成功,我们要减少我们产品的库存
this .reduceProductStock (orderItemList);
//清空⼀下购物车
this .cleanCart (cartList);
//返回给前端数据
OrderVo orderVo = asmbleOrderVo(order,orderItemList);
return ServerRespon .createBySuccess (orderVo);
}
/
/校验并且封装⼀下
private ServerRespon getCartOrderItem(Integer urId,List<Cart> cartList){
List<OrderItem> orderItemList = Lists .newArrayList ();
//购物车中已经勾选的商品是空的
if(CollectionUtils .isEmpty (cartList))
return ServerRespon .createByErrorMessage ("购物车为空");
/*********校验购物车的数据,包括产品的状态和数量********/
/*********校验购物车的数据,包括产品的状态和数量********/
for(Cart cartItem : cartList){
OrderItem orderItem = new OrderItem();
//查出商品
Product product = productMapper.ProductId());
//查看产品销售状态
if(Const.ProductStatusEnum.Code() != Status()){
ateByErrorMessage("产品"+Name()+"不是在线售卖状态");
}
//校验库存
结构化面谈
Quantity() > Stock()){
ateByErrorMessage("产品"+Name()+"库存不⾜");
}
/**********将已经勾选的购物车中的商品组装⼀下***********/
orderItem.tUrId(urId);
orderItem.Id());
orderItem.Name());
orderItem.MainImage());
orderItem.Price());
orderItem.Quantity());
//此项商品的总价
orderItem.tTotalPrice(BigDecimalUtil.Price().doubleValue(),Quantity()));
orderItemList.add(orderItem);
}
ateBySuccess(orderItemList);
}
/
/此函数⽤于计算订单总价
private BigDecimal getOrderTotalPrice(List<OrderItem> orderItemList){
BigDecimal payment = new BigDecimal("0");
for(OrderItem orderItem : orderItemList)
payment = BigDecimalUtil.add(payment.doubleValue(),TotalPrice().doubleValue()); //每⼀项的总价都加进来 return payment;
}
//此函数⽤于⽣成订单号
private long generateOrderNo(){
long currentTime = System.currentTimeMillis();
return currentTime + new Random().nextInt(100);
}
香葱豆腐//此函数⽤于⽣成订单
private Order asmbleOrder(Integer urId,Integer shippingId,BigDecimal payment){
Order order = new Order();
//⽣成订单号
long orderNo = ateOrderNo();
order.tOrderNo(orderNo);
//⽀付状态,未付款
order.tStatus(Const.OrderStatusEnum.Code());
order.tPostage(0); //运费设置为0
//⽀付⽅式,在线⽀付
order.tPaymentType(Const.PaymentTypeEnum.Code());
order.tPayment(payment);
order.tUrId(urId); //购买的⽤户的ID
order.tShippingId(shippingId); //发货地址的ID
//发货时间等等
//付款时间等等
//插⼊订单
int rowCount = orderMapper.inrt(order);
if(rowCount > 0)
return order;
return null;
}
/
/减少商品的库存
private void reduceProductStock(List<OrderItem> orderItemList){
for(OrderItem orderItem : orderItemList){
Product product = productMapper.ProductId());
product.Stock()-Quantity());
product.Stock()-Quantity());
productMapper.updateByPrimaryKeySelective(product);
}
}
//清空购物车
private void cleanCart(List<Cart> cartList){
for(Cart cart : cartList)
cartMapper.Id());
}
//将订单包装⼀下
private OrderVo asmbleOrderVo(Order order,List<OrderItem> orderItemList){ //order:订单,orderItemList:订单明细 OrderVo orderVo = new OrderVo();
orderVo.OrderNo());
orderVo.Payment());
orderVo.PaymentType());
orderVo.tPaymentTypeDesc(PaymentType()).getValue());
orderVo.Postage());
orderVo.Status());
orderVo.tStatusDesc(Status()).getValue());
orderVo.ShippingId());
Shipping shipping = shippingMapper.ShippingId());
if(shipping != null){
orderVo.ReceiverName());
orderVo.tShippingVo(asmbleShippingVo(shipping));
}
orderVo.tPaymentTime(DateTimeUtil.PaymentTime()));
orderVo.tSendTime(DateTimeUtil.SendTime()));
orderVo.tEndTime(DateTimeUtil.EndTime()));
orderVo.tCreateTime(DateTimeUtil.CreateTime()));
orderVo.tCloTime(DateTimeUtil.CloTime()));
orderVo.Property("ftp.rver.http.prefix"));
List<OrderItemVo> orderItemVoList = wArrayList();
for(OrderItem orderItem : orderItemList){
OrderItemVo orderItemVo = asmbleOrderItemVo(orderItem);
orderItemVoList.add(orderItemVo);
}
orderVo.tOrderItemVoList(orderItemVoList); //订单的明细
return orderVo;
}
//封装收货地址
private ShippingVo asmbleShippingVo(Shipping shipping){
ShippingVo shippingVo = new ShippingVo();
shippingVo.ReceiverName());
shippingVo.ReceiverAddress());
shippingVo.ReceiverProvince());
shippingVo.ReceiverCity());
shippingVo.ReceiverDistrict());
shippingVo.ReceiverMobile());
shippingVo.ReceiverZip());
shippingVo.ReceiverPhone());
return shippingVo;
}
<lect id="lectCheckedCartByUrId"parameterType="int"resultMap="BaResultMap">蘑菇炒牛肉
SELECT
<include refid="Ba_Column_List"/>
from mmall_cart
where ur_id = #{urId}
and checked = 1
</lect>
<!--
批量插⼊接⼝:void batchInrt(@Param("orderItemList") List<OrderItem> orderItemList);
-
->
<inrt id="batchInrt"parameterType="list">
inrt into mmall_order_item (id, order_no,ur_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"parator=",">
(
#{item.id},#{derNo},#{item.urId},#{item.productId},#{item.productName},#{item.productImage},#{item.currentUnitPrice},#{item.quantity},#{item.t )
</foreach>
</inrt>
强⼤的常量、枚举设计
⽤接⼝定义常量最⼤的好处是有⼀个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.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()){
Code() == code){
return orderStatusEnum;
}
}
throw new RuntimeException("么有找到对应的枚举");
}
}
报关证
}
订单号⽣成规则
1.订单号⽆重复性;
2.如果⽅便客服的话,最好是“⽇期+⾃增数”样式的订单号,客服⼀看便知道订单是否在退货保障期限内容;
3.订单号长度尽量保持短(10位以内),⽅便⽤户,尤其电话投诉时,长的号码报错⼏率⾼,影响客服效率;
//此函数⽤于⽣成订单号
private long generateOrderNo(){
long currentTime = System.currentTimeMillis();
return currentTime + new Random().nextInt(100);
}
Java⾯试的完整博客⽬录如下: