一个简单的商城订单超时取消功能的实现

    大多数的B2C商城项目都会有限时活动,当用户下单后都会有支付超时时间,当订单超时后订单的状态就会自动变成已取消 ,这个功能的实现有很多种方法,本文的实现方法适合大多数比较小的商城使用。

实现原理:

     利用 jdk 的 DelayQueue的阻塞队列的特性实现。在项目启动时开启一个线程处理 DelayQueue 队列里弹出的超时订单对象,订单未超时该线程处于等待中。

DelayQueue的简单介绍:

    DelayQueue类的主要作用:是一个无界的BlockingQueue,用于放置实现了Delayed接口的对象,其中的对象只能在其到期时才能从队列中取走。这种队列是有序的,即队头对象的延迟到期时间最长。注意:不能将null元素放置到这种队列中。

实现方式 :

  1.创建一个实现Delayed接口的 order 类并重写compareTo和 getDelay方法

  2.创建一个帮助类OrderCollection(订单的增删查)

  3. 创建CancellOrder类

  在生成订单时将订单号创建时间和过期时间封装成一个实现Delayed接口的对象存入DelayQueue队列中,当该订单支付完成后将该对象从队列中移除,(为了保证不丢失订单建议在项目启动时将数据库中的符合条件的订单初始化到DelayQueue队列中 )
 

实现代码如下:

/**
 * 类说明
 *
 * @author grl
 * @date 2019年12月16日 新建
 */
public class Order implements Delayed {

   private String orderShopNum;
   /**
    * 1-普通活动 2-限时活动 3-拼购活动
    */
   private int orderType;
   private long orderCreateTime;
   private long expTime;

   public Order(String orderShopNum, int orderType, Date createTime) {
      if (StringUtils.isNotBlank(orderShopNum)) {
         this.orderShopNum = orderShopNum.trim();
      }
      if (createTime == null) {
         this.orderCreateTime = System.currentTimeMillis();
      } else {
         this.orderCreateTime = createTime.getTime();
      }
      this.orderType = orderType;
      if (orderType == 2) {
         this.expTime = TimeUnit.MILLISECONDS.convert(Const.LIMIT_ACTIVITY_EXPIRATION_TIME, TimeUnit.MINUTES)
               + createTime.getTime();
      }if(orderType == 3){
         this.expTime = TimeUnit.MILLISECONDS.convert(Const.LIMIT_GROUP_BUY_EXPIRATION_TIME, TimeUnit.MINUTES)
               + createTime.getTime();
      } else {
         this.expTime = TimeUnit.MILLISECONDS.convert(Const.ORDER_PAYMENT_DEADLINE, TimeUnit.DAYS)
               + createTime.getTime();
      }
   }

   public String getOrderShopNum() {
      return orderShopNum;
   }

   public long getOrderCreateTime() {
      return orderCreateTime;
   }

   public long getExpTime() {
      return expTime;
   }

   public int getOrderType() {
      return orderType;
   }

   @Override
   public int compareTo(Delayed o) {
      return Long.valueOf(this.expTime).compareTo(Long.valueOf(((Order) o).expTime));
   }

   @Override
   public long getDelay(TimeUnit unit) {
      return unit.convert(this.expTime - System.currentTimeMillis(), TimeUnit.MILLISECONDS);
   }

}

 

/**
 * 类说明
 *
 * @author grl
 * @date 2019年12月16日 新建
 */
public class OrderCollection {
   /**
    * 订单管理集合
    */
   private static DelayQueue orderList = new DelayQueue();

   private OrderCollection() {

   }
   /**
    * 获取订单集合
    * @author grl
    * @return
    */
   protected static DelayQueue getOrderCollection() {
      
      return orderList;
   } 
   /**
    * 向集合中添加订单
    * 
    * @author grl
    * @param order
    * @return
    */
   public static boolean add(Order order) {
      boolean flag = false;
      if (order != null && StringUtils.isNotBlank(order.getOrderShopNum())) {
         flag = orderList.offer(order);
      }
      return flag;
   }

   /**
    * 从集合中删除订单
    * 
    * @author grl
    * @param orderShopNum
    * @return
    */
   public static boolean remove(String orderShopNum) {
      boolean flag = false;
      Order thisOrder = null;
      if (StringUtils.isNotBlank(orderShopNum)) {
         orderShopNum = orderShopNum.trim();
         for (Order order : orderList) {
            String orderNum = order.getOrderShopNum();
            if (orderNum.equals(orderShopNum)) {
               thisOrder = order;
            }
         }
         if (thisOrder != null) {
            flag = orderList.remove(thisOrder);
         }
      }
      return flag;
   }

   /**
    * 获取订单的过期剩余时间
    * 
    * @author grl
    * @param orderShopNum
    * @param unit
    * @return -1 已经过期
    */
   public static long getDelay(String orderShopNum) {
      long time = -1;
      if (StringUtils.isNotBlank(orderShopNum)) {
         orderShopNum = orderShopNum.trim();
         for (Order order : orderList) {
            String orderNum = order.getOrderShopNum();
            if (orderNum.equals(orderShopNum)) {
               time = order.getDelay(TimeUnit.MILLISECONDS);
               if(time<5000) {
                  time = -1;
               }
            }
         }
      }
      return time;
   }
}

 

/**
 * 类说明
 *
 * @author grl
 * @date 2019年12月16日 新建
 */
@Component
public class CancellOrder implements Runnable {

   private static final Logger log = LoggerFactory.getLogger(CancellOrder.class);

   
   @Override
   public void run() {
      while (true) {
         try {
            Order take = OrderCollection.getOrderCollection().take();
            String orderShopNum = take.getOrderShopNum();
            int orderType = take.getOrderType();
            // 业务逻辑操作
           
         } catch (InterruptedException e) {
            e.printStackTrace();
            log.error("CancellOrder DelayQueue 错误 {}", e.getMessage());
         }
      }
   }

}

你可能感兴趣的:(SpringBoot)