Java实现商城订单超时取消功能

大多数的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<Order> orderList = new DelayQueue<Order>();
  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());
     }
   }
  }
}

总结

以上所述是小编给大家介绍的Java实现商城订单超时取消功能,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对我们网站的支持!
如果你觉得本文对你有帮助,欢迎转载,烦请注明出处,谢谢!

(0)

相关推荐

  • java后台实现支付宝支付接口和支付宝订单查询接口(前端为APP)

    最近项目APP需要接入微信.支付宝支付功能,在分配开发任务时,听说微信支付接口比支付宝支付接口要难实现,由于我开发经验不是那么丰富(现工作经验1年半)且未接触过支付接口开发,组里刚好又有支付接口的老司机,所以很自然把简单的支付宝接口开发任务交给了我,看来开发组的组长还是很好人的嘛.....,废话就不多说了,我们开始吧! 实现支付宝接口详细过程 1.去支付宝官网申请公司企业账号并开通一个应用,在应用里签约APP支付功能 具体的申请截图步骤,在这里我就不详细说了,因为这不是文章的重点,可参考支付宝官

  • java web在高并发和分布式下实现订单号生成唯一的解决方案

    方案一: 如果没有并发,订单号只在一个线程内产生,那么由于程序是顺序执行的,不同订单的生成时间戳正常不同,因此用时间戳+随机数(或自增数)就可以区分各个订单.如果存在并发,且订单号是由一个进程中的多个线程产生的,那么只要把线程ID添加到序列号中就可以保证订单号唯一.如果存在并发,且订单号是由同一台主机中的多个进程产生的,那么只要把进程ID添加到序列号中就可以保证订单号唯一.如果存在并发,且订单号是由不同台主机产生的,那么MAC地址.IP地址或CPU序列号等能够区分主机的号码添加到序列号中就可以保

  • javaweb图书商城设计之订单模块(5)

    这篇文章是针对javaweb图书商城中订单模块的研究, 1.创建相关类 domain: Order OrderItem dao:OrderDao service:OrderService web.servlete:OrderServlet /** * 订单条目类 */ public class OrderItem { private String iid; private int count;// 数量 private double subtotal;// 小计 private Order or

  • java网上图书商城(7)订单模块2

    本文实例为大家分享了java网上图书商城订单模块的具体代码,供大家参考,具体内容如下 1.我的订单---查 按用户查询订单 分页查询 PageBean<Order> <div class="divMain"> <div class="divTitle"> <span style="margin-left: 150px;margin-right: 280px;">商品信息</span> &

  • 微信支付java版本之查询订单

    本文实例为大家分享了微信支付订单的查询接口,供大家参考,具体内容如下 1.接口简介 2.代码实现 package com.zhrd.bussinss.platform.controller.shop; import java.io.File; import java.io.FileInputStream; import java.security.KeyStore; import java.text.SimpleDateFormat; import java.util.Date; import

  • java网上图书商城(6)订单模块1

    先看看效果图: 1.sql ①t_orderitem一个外键 bname:方便后期book删除 CREATE TABLE `t_orderitem` ( `orderItemId` char(32) NOT NULL, `quantity` int(11) DEFAULT NULL, `subtotal` decimal(8,2) DEFAULT NULL, `bid` char(32) DEFAULT NULL, `bname` varchar(200) DEFAULT NULL, `curr

  • Java实现商城订单超时取消功能

    大多数的B2C商城项目都会有限时活动,当用户下单后都会有支付超时时间,当订单超时后订单的状态就会自动变成已取消 ,这个功能的实现有很多种方法,本文的实现方法适合大多数比较小的商城使用. 实现原理: 利用 jdk 的 DelayQueue的阻塞队列的特性实现.在项目启动时开启一个线程处理 DelayQueue 队列里弹出的超时订单对象,订单未超时该线程处于等待中. DelayQueue的简单介绍: DelayQueue类的主要作用:是一个无界的BlockingQueue,用于放置实现了Delaye

  • python使用celery实现订单超时取消

    本文实例为大家分享了celery实现订单超时取消的具体代码,供大家参考,具体内容如下 Celery官方文档中关于定时任务使用的说明 项目目录结构 我们需要新增一个任务目录,例如order: celey_tasks/      ├── config.py      ├── __init__.py      ├── main.py      ├── order/             ├── __init__.py            └── tasks.py 在main.py中,注册任务目录[

  • 基于Redis过期事件实现订单超时取消

    订单超时取消的实现,首先想到的是定时任务,但是这种实现方式在订单量较大的情况下是有问题的,而且时间也会有误差,最大时间差就是定时任务的执行间隔时间. 使用redis的过期监听事件可以比较好的解决这个问题.实现的方式是订单创建后向redus中存一记录,一般就以订单号为key.设置过期时间(订单超时时间),一旦时间超时会触发监听事件,这时候就可以通过key判断这个订单是否支付,未支付时取消订单. redis过期监听的实现: 1.修改redis.windows.conf配置文件中notify-keys

  • Java 实现订单未支付超时自动取消功能(京东商城为例)

    目录 创建 TimerTask Timer 定时器调用 TimerTask 总结 源码 在电商上购买商品后,如果在下单而又没有支付的情况下,一般提示30分钟完成支付,否则订单自动.比如在京东下单为完成支付: 超过24小时,就会自动取消订单,下面使用 Java 定时器实现超时取消订单功能. Timer 定时器 Timer 是一个调度任务的执行的工具,任务可以一次性定时执行或者定时重复执行,系统会启动一个线程来执行所有的定时任务. TimerTask 定时任务 TimerTask 是一个抽象类,它实

  • Java实现订单超时未支付自动取消的8种方法总结

    目录 定时轮询 惰性取消 JDK延迟队列 时间轮 Redis过期回调 Redis有序集合 任务调度 消息队列 定时轮询 数据库定时轮询方式,实现思路比较简单.启动一个定时任务,每隔一定时间扫描订单表,查询到超时订单就取消. 优点:实现简单. 缺点:轮询时间间隔不好确定,占用服务器资源,影响数据库性能. 惰性取消 当查询订单信息时,先判断该订单是否超时,如果超时就先取消. 优点:实现简单. 缺点:影响查询之外的业务(如:统计.库存),影响查询效率. JDK延迟队列 JDK延时队列DelayQueu

  • Springboot整合微信支付(订单过期取消及商户主动查单)

    目录 一:问题引入 二:处理流程 三:代码实现 一:问题引入 前面讲到用户支付完成之后微信支付服务器会发送回调通知给商户,商户要能够正常处理这个回调通知并返回正确的状态码给微信支付后台服务器,不然微信支付后台服务器就会在一段时间之内重复发送回调通知给商户.具体流程见下图: 那么这时候问题就来了,微信后台发送回调通知次数也是有限制的,而且,微信支付开发文档中这样说到:对后台通知交互时,如果微信收到商户的应答不符合规范或超时,微信认为通知失败,微信会通过一定的策略定期重新发起通知,尽可能提高通知的成

  • Java+Ajax实现的用户名重复检验功能实例详解

    本文实例讲述了Java+Ajax实现的用户名重复检验功能.分享给大家供大家参考,具体如下: 今天,我来教大家怎么实现Java+Ajax实现用户名重复检验. 实体类代码: /** * */ package com.hqj.dao; /** * @author HuangQinJian 下午9:12:19 2017年4月23日 */ public class User { private int id; private String name; private String password; /*

  • Java spring boot 实现支付宝支付功能的示例代码

    一.准备工作: 1.登陆支付宝开发者中心,申请一个开发者账号. 地址:https://openhome.alipay.com/ 2.进入研发服务: 3.点击链接进入工具下载页面: 4.点击下载对应版本的RSA公钥生成器: 5.生成公钥密钥(记录你的应用私钥): 6.在支付宝配置公钥(点击保存): 二.搭建demo 1.引入jia包: <dependency> <groupId>com.alipay.sdk</groupId> <artifactId>alip

  • Java女装商城系统的实现流程

    一.项目简述功能 javaweb 网上商城系统,前台+后台管理,用户注册,登录,上哦展示,分组展示,搜索,收货地址管理,购物车管理,添加,购买,个人信息修改.订单查询等等,后台商品管理,分类管理,库存管理,订单管理,用户管理,信息修改等等. 二.项目运行 环境配置: Jdk1.8 + Tomcats . 5 + mysql + Eclispe ( IntelliJ IDEA ,Eclispe , MyEclispe , sts 都支持) 项目技术: JSP + Spring + SpringMV

  • FasfDFS整合Java实现文件上传下载功能实例详解

    在上篇文章给大家介绍了FastDFS安装和配置整合Nginx-1.13.3的方法,大家可以点击查看下. 今天使用Java代码实现文件的上传和下载.对此作者提供了Java API支持,下载fastdfs-client-java将源码添加到项目中.或者在Maven项目pom.xml文件中添加依赖 <dependency> <groupId>org.csource</groupId> <artifactId>fastdfs-client-java</arti

随机推荐