java实现7天未收货则自动收货

使用redis,延时队列完成7天自动收货

1:设置项目启动执行把redis中所有的订单状态为未收货的订单存入队列中(避免系统关闭启动队列中的数据丢失。队列中的数据丢失无法做到检测数据是否超时)

重要

@Service
public class OrderInitializingBean implements InitializingBean{

	public static OrderDelayQueueThread OrderDelayQueueThread = null;

	@Autowired
	private RedisTemplate redisTemplate;

	@Autowired
	private TbOrderMapper orderService;

	@SuppressWarnings("unchecked")
	@Override
	public void afterPropertiesSet() throws Exception {
		Map<String, Object> entries = redisTemplate.opsForHash().entries(CFSConfig.orderDelayBean);
		if (OrderDelayQueueThread == null) {
			OrderDelayQueueThread = new OrderDelayQueueThread(orderService, redisTemplate);
			Thread thread = new Thread(OrderDelayQueueThread);
			thread.start();
		}
		if (!StringUtils.isEmpty(entries) && entries.size()>0) {
			for (String key : entries.keySet()) {
				OrderDelayedTask delayQueueOrder = (OrderDelayedTask) entries.get(key);
				OrderDelayQueueThread.putDelayQueueForRedis(delayQueueOrder);
			}
		}
	}
}

2:正常逻辑卖家发货把订单数据存入redis和队列中进行检测

		/**
		 * 发货(卖家发货订单数据存入redis和延时队列中:延时队列设置时长为7天)
		 */
		@Override
		public Boolean deliverGoods(String[] ids) {
			for (String id : ids) {
				TbOrder tbOrder = orderMapper.selectByPrimaryKey(id);
				if("1".equals(tbOrder.getStatus())) {
					tbOrder.setStatus("2");
					tbOrder.setConsignTime(new Date());//发货时间
					orderMapper.updateByPrimaryKey(tbOrder);
					//调用线程,添加延时队列
					//项目启动自动执行
					OrderInitializingBean.OrderDelayQueueThread.add(id);//调用线程的add方法添加数据
				}else {
					return false;
				}
			}
			return true;
		}

3:队列中的方法:
add(卖家发货调用add方法吧订单存入redis和队列中并设置超时时间)
run(线程启动执行,此处是订单超时时做修改订单状态为收货状态,并删除redis中的订单信息)
removeDelay(用户在7天之内点击收货,调用次方法删除队列和redis中的订单信息,不再进行检测)
putDelayQueueForRedis(项目在自启动时取出redis中的订单信息调用此方法存入队列中继续进行检测[详细请看OrderInitializingBean.afterPropertiesSet方法])

		/**
		 * 使用线程吧订单数据存入redis和队列中并设置时间
		 */
public class OrderDelayQueueThread implements Runnable{
	
	private static TbOrderMapper orderService;
	
	private static RedisTemplate redisTemplate;
	
	private static AtomicBoolean isrun = new AtomicBoolean(true);
	
	private  static DelayQueue delayQueue  = new DelayQueue();
	
	public OrderDelayQueueThread(TbOrderMapper orderService,RedisTemplate redisTemplate) {
		super();
		this.orderService = orderService;
		this.redisTemplate=redisTemplate;
	}
	
	public static DelayQueue getDelayQueue() {
		return delayQueue;
	}

	public static void setDelayQueue(DelayQueue delayQueue) {
		OrderDelayQueueThread.delayQueue = delayQueue;
	}

	//订单数据存入redis和队列中并设置时间
	@SuppressWarnings("unchecked")
	public void add(String orderId) {
		Map<String, Object> map=new HashMap<String, Object>();
		TbOrder findOrderOne = orderService.selectByPrimaryKey(orderId);
		String jsonString = JSON.toJSONString(findOrderOne);
		OrderDelayedTask orderDelayedTask = new OrderDelayedTask(jsonString,604800000);//7天
		map.put(orderId, orderDelayedTask);
		redisTemplate.opsForHash().putAll(CFSConfig.orderDelayBean, map);//订单信息添加到redis中
		delayQueue.offer(orderDelayedTask);// 添加到队列中   5分种
	}
	
	@Override
	public void run() {
		try {
			while (isrun.get()) {
				Delayed take = delayQueue.take();//从队列中取出
				if (!StringUtils.isEmpty(take)) {
					OrderDelayedTask orderDelayedTask = (OrderDelayedTask) take;
					String orderJson = orderDelayedTask.getOrderJson();
					TbOrder tbOrder = JSONObject.parseObject(orderJson, TbOrder.class);
					if ("2".equals(tbOrder.getStatus())) {// 判断订单是否是已经发货的订单
						TbOrder findOrderOne = orderService.selectByPrimaryKey(tbOrder.getOrderId());
						if ("2".equals(findOrderOne.getStatus())) {
							findOrderOne.setStatus("3");//修改订单状态为已经收获
							findOrderOne.setBuyerMessage("收货超时系统自动收货");
							orderService.updateByPrimaryKey(findOrderOne);//修改订单的状态
							redisTemplate.opsForHash().delete(CFSConfig.orderDelayBean, tbOrder.getOrderId());//删除redis中的数据
						}
					}
				}
			}
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * 删除队列中的数据(在7天内用户点击收货调用方法删除redis数据和队列中的数据不进行检测)
	 * @param tbOrder
	 * @return
	 */
	public static boolean removeDelay(TbOrder tbOrder) {
		//用户点击确认收货,取出队列中的数据,删除redis种的订单,修改订单的状态
		if (isrun.get()) {
			Object[] objectArray =  delayQueue.toArray();
			if (objectArray!=null && objectArray.length>0) {
				for (Object object: objectArray) {
					OrderDelayedTask orderDelayedTask=(OrderDelayedTask) object;
					String tbOrderJson = JSON.toJSONString(tbOrder);
					redisTemplate.opsForHash().delete(CFSConfig.orderDelayBean, tbOrder.getOrderId());
					boolean remove = delayQueue.remove(orderDelayedTask);
					return remove;
				}
			}
		}
		return false;
	}
	
	public void putDelayQueueForRedis(OrderDelayedTask orderDelayedTask) {
		delayQueue.offer(orderDelayedTask);
	}

3:使用延时队列必须实现Delayed接口,重写俩个方法getDelay和getDelay。OrderDelayedTask类是存入延时队列中的数据,包括开始时间(start:当前系统获取到的时间),订单信息(orderJson),延时时间(time)!!!
注意:OrderDelayedTask需要存入redis中一定要记得实现Serializable

重要

public class OrderDelayedTask implements Delayed,Serializable{
	
	private String orderJson ;
    private long start = System.currentTimeMillis();//开始时间
    private long time ;
    
    
    public OrderDelayedTask(String orderJson, long time) {
		super();
		this.orderJson = orderJson;
		this.time = time;
	}
    
	public String getOrderJson() {
		return orderJson;
	}
	
	public void setOrderJson(String orderJson) {
		this.orderJson = orderJson;
	}

	@Override
	public String toString() {
		return "OrderDelayedTask [orderJson=" + orderJson + ", start=" + start + ", time=" + time + "]";
	}



	/**
     * 需要实现的接口,获得延迟时间   用过期时间-当前时间
     * @param unit
     * @return
     */
    @Override
    public long getDelay(TimeUnit unit) {
        return unit.convert((start+time) - System.currentTimeMillis(),TimeUnit.MILLISECONDS);
    }

    /**
     * 用于延迟队列内部比较排序   当前时间的延迟时间 - 比较对象的延迟时间
     * @param o
     * @return
     */
    @Override
    public int compareTo(Delayed o) {
    	OrderDelayedTask o1 = (OrderDelayedTask) o;
        return (int) (this.getDelay(TimeUnit.MILLISECONDS) - o.getDelay(TimeUnit.MILLISECONDS));
    }
  • 1
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值