面试:订单模块技术要点
技术要点:
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 如果觉得本文对您有帮助,请点击顶支持一下,您的支持是我写作最大的动力,谢谢。