7天自動收貨,30分鐘不支付訂單自動取消是如何實現的?

1.我們以支付以後7天自動收貨爲例來說明下:

(1)用戶支付完成以後,把訂單ID插入到內存的一個DelayQueue中,同時插入到Redis中。

(2)7天之內,用戶點擊了確認收貨,則從DelayQueue中刪除,從Redis中刪除。

(3)超過7天,DelayQueue中的訂單ID出隊,查詢數據庫,改狀態爲自動收貨,刪除redis。

(4)如果7天之內,web服務器重啓過,則web服務器啓動以後,從redis中讀取待收貨的訂單,插入到DelayQueue。

看下具體的代碼:

[java] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. @Controller  
  2. @RequestMapping(value = "")  
  3. public class OrderController {  
  4.     @Autowired  
  5.     DelayService delayService;  
  6.     @Autowired  
  7.     RedisService redisServie;  
  8.     @Autowired  
  9.     ConfigService configService;  
  10.     //模擬數據庫  
  11.     private List<Long> ordeIds = new ArrayList<Long>();  
  12.     private static final Logger log = Logger.getLogger(OrderController.class);  
  13.     @RequestMapping(value = "/order", method = RequestMethod.GET)  
  14.     public String order(final HttpServletRequest request, final Model model) {  
  15.         return "order";  
  16.     }  
  17.     @RequestMapping(value = "/pay", method = RequestMethod.GET)  
  18.     @ResponseBody  
  19.     public Response<Void> pay(final HttpServletRequest request, final Model model) {  
  20.         final long orderId = Long.parseLong(request.getParameter("orderId"));  
  21.         ordeIds.add(orderId);  
  22.         log.error("訂單已支付:"+orderId);  
  23.         //把訂單插入到待收貨的隊列和redis  
  24.         ThreadPoolUtil.execute(new Runnable(){  
  25.             @Override  
  26.             public void run() {  
  27.                 //1 插入到待收貨隊列  
  28.                 DSHOrder dshOrder = new DSHOrder(orderId, configService.getDshTimeOut());  
  29.                 delayService.add(dshOrder);  
  30.                 log.error("訂單入隊:"+orderId);  
  31.                 //2插入到redis  
  32.                 redisServie.set(Constants.RedisKey.DSH_PREFIX+orderId, dshOrder, RedisService.DB.DSH);  
  33.                 log.error("訂單入redis:"+orderId);  
  34.             }  
  35.         });  
  36.         return new Response<Void>(0,"成功");  
  37.     }  
  38.     @RequestMapping(value = "/confirm_delivery", method = RequestMethod.GET)  
  39.     @ResponseBody  
  40.     public Response<Void> confirm_delivery(final HttpServletRequest request, final Model model) {  
  41.         final long orderId = Long.parseLong(request.getParameter("orderId"));  
  42.         ordeIds.remove(orderId);  
  43.         log.error("訂單已確認收貨:"+orderId);  
  44.         //從delay隊列刪除,從redis刪除  
  45.         ThreadPoolUtil.execute(new Runnable(){  
  46.             public void run(){  
  47.                 //從delay隊列刪除  
  48.                 delayService.remove(orderId);  
  49.                 log.error("訂單手動出隊:"+orderId);  
  50.                 //從redis刪除  
  51.                 redisServie.delete(Constants.RedisKey.DSH_PREFIX+orderId, RedisService.DB.DSH);  
  52.                 log.error("訂單手動出redis:"+orderId);  
  53.             }  
  54.         });  
  55.         return new Response<Void>(0,"成功");  
  56.     }  
  57. }  

[java] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. @Service  
  2. public class DelayService {  
  3.       
  4.     private static final Logger log = Logger.getLogger(DelayService.class);  
  5.       
  6.     @Autowired  
  7.     ConfigService configService;  
  8.       
  9.     private boolean start ;    
  10.     private OnDelayedListener listener;  
  11.     private DelayQueue<DSHOrder> delayQueue = new DelayQueue<DSHOrder>();  
  12.       
  13.     public static interface OnDelayedListener{  
  14.         public void onDelayedArrived(DSHOrder order);  
  15.     }  
  16.   
  17.     public void start(OnDelayedListener listener){  
  18.         if(start){  
  19.             return;  
  20.         }  
  21.         log.error("DelayService 啓動");  
  22.         start = true;  
  23.         this.listener = listener;  
  24.         new Thread(new Runnable(){  
  25.             public void run(){  
  26.                 try{  
  27.                     while(true){  
  28.                         DSHOrder order = delayQueue.take();  
  29.                         if(DelayService.this.listener != null){  
  30.                             DelayService.this.listener.onDelayedArrived(order);  
  31.                         }  
  32.                     }  
  33.                 }catch(Exception e){  
  34.                     e.printStackTrace();  
  35.                 }  
  36.             }  
  37.         }).start();;  
  38.     }  
  39.       
  40.     public void add(DSHOrder order){  
  41.         delayQueue.put(order);  
  42.     }  
  43.   
  44.     public boolean remove(DSHOrder order){  
  45.         return delayQueue.remove(order);  
  46.     }  
  47.       
  48.     public void add(long orderId){  
  49.         delayQueue.put(new DSHOrder(orderId, configService.getDshTimeOut()));  
  50.     }  
  51.       
  52.     public void remove(long orderId){  
  53.         DSHOrder[] array = delayQueue.toArray(new DSHOrder[]{});  
  54.         if(array == null || array.length <= 0){  
  55.             return;  
  56.         }  
  57.         DSHOrder target = null;  
  58.         for(DSHOrder order : array){  
  59.             if(order.getOrderId() == orderId){  
  60.                 target = order;  
  61.                 break;  
  62.             }  
  63.         }  
  64.         if(target != null){  
  65.             delayQueue.remove(target);  
  66.         }  
  67.     }  
  68. }  

[java] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. public class DSHOrder implements Delayed {  
  2.       
  3.     private long orderId;  
  4.     private long startTime;  
  5.       
  6.     public DSHOrder(){  
  7.           
  8.     }  
  9.       
  10.     /** 
  11.      * orderId:訂單id 
  12.      * timeout:自動收貨的超時時間,秒 
  13.      * */  
  14.     public DSHOrder(long orderId, int timeout){  
  15.         this.orderId = orderId;  
  16.         this.startTime = System.currentTimeMillis() + timeout*1000L;  
  17.     }  
  18.     @Override  
  19.     public int compareTo(Delayed other) {  
  20.         if (other == this){  
  21.             return 0;  
  22.         }  
  23.         if(other instanceof DSHOrder){  
  24.             DSHOrder otherRequest = (DSHOrder)other;  
  25.             long otherStartTime = otherRequest.getStartTime();  
  26.             return (int)(this.startTime - otherStartTime);  
  27.         }  
  28.         return 0;  
  29.     }  
  30.   
  31.     @Override  
  32.     public long getDelay(TimeUnit unit) {  
  33.         return unit.convert(startTime - System.currentTimeMillis(), TimeUnit.MILLISECONDS);  
  34.     }  
  35.   
  36.     @Override  
  37.     public int hashCode() {  
  38.         final int prime = 31;  
  39.         int result = 1;  
  40.         result = prime * result + (int) (orderId ^ (orderId >>> 32));  
  41.         result = prime * result + (int) (startTime ^ (startTime >>> 32));  
  42.         return result;  
  43.     }  
  44.   
  45.     @Override  
  46.     public boolean equals(Object obj) {  
  47.         if (this == obj)  
  48.             return true;  
  49.         if (obj == null)  
  50.             return false;  
  51.         if (getClass() != obj.getClass())  
  52.             return false;  
  53.         DSHOrder other = (DSHOrder) obj;  
  54.         if (orderId != other.orderId)  
  55.             return false;  
  56.         if (startTime != other.startTime)  
  57.             return false;  
  58.         return true;  
  59.     }  
  60.   
  61.     public long getStartTime() {  
  62.         return startTime;  
  63.     }  
  64.   
  65.     public long getOrderId() {  
  66.         return orderId;  
  67.     }  
  68.   
  69.     public void setOrderId(long orderId) {  
  70.         this.orderId = orderId;  
  71.     }  
  72.   
  73.     public void setStartTime(long startTime) {  
  74.         this.startTime = startTime;  
  75.     }  
  76.   
  77.     @Override  
  78.     public String toString() {  
  79.         return "DSHOrder [orderId=" + orderId + ", startTime=" + startTime + "]";  
  80.     }  
  81. }  

[java] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. @Service  
  2. public class StartupListener implements ApplicationListener<ContextRefreshedEvent> {  
  3.       
  4.     private static final Logger log = Logger.getLogger(StartupListener.class);  
  5.   
  6.     @Autowired  
  7.     DelayService delayService;  
  8.     @Autowired  
  9.     RedisService redisService;  
  10.       
  11.       
  12.     @Override  
  13.     public void onApplicationEvent(ContextRefreshedEvent evt) {  
  14.         log.error(">>>>>>>>>>>>系統啓動完成,onApplicationEvent()");  
  15.         if (evt.getApplicationContext().getParent() == null) {  
  16.             return;  
  17.         }  
  18.         //自動收貨  
  19.         delayService.start(new OnDelayedListener(){  
  20.             @Override  
  21.             public void onDelayedArrived(final DSHOrder order) {  
  22.                 //異步來做  
  23.                 ThreadPoolUtil.execute(new Runnable(){  
  24.                     public void run(){  
  25.                         long orderId = order.getOrderId();  
  26.                         //查庫判斷是否需要自動收貨  
  27.                         log.error("自動確認收貨,onDelayedArrived():"+orderId);  
  28.                         //從redis刪除  
  29.                         redisService.delete(Constants.RedisKey.DSH_PREFIX+orderId, RedisService.DB.DSH);  
  30.                         log.error("自動確認收貨,刪除redis:"+orderId);  
  31.                     }  
  32.                 });  
  33.             }  
  34.         });  
  35.         //查找需要入隊的訂單  
  36.         ThreadPoolUtil.execute(new Runnable(){  
  37.             @Override  
  38.             public void run() {  
  39.                 log.error("查找需要入隊的訂單");  
  40.                 //掃描redis,找到所有可能的orderId  
  41.                 List<String> keys = redisService.scan(RedisService.DB.DSH);  
  42.                 if(keys == null || keys.size() <= 0){  
  43.                     return;  
  44.                 }  
  45.                 log.error("需要入隊的訂單keys:"+keys);  
  46.                 //寫到DelayQueue  
  47.                 for(String key : keys){  
  48.                     DSHOrder order = redisService.get(key, DSHOrder.class, RedisService.DB.DSH);  
  49.                     log.error("讀redis,key:"+key);  
  50.                     if(order != null){  
  51.                         delayService.add(order);      
  52.                         log.error("訂單自動入隊:"+order.getOrderId());  
  53.                     }  
  54.                 }   
  55.             }  
  56.         });   
  57.     }  
  58. }  
public class ThreadPoolUtil {
    private static int count = Runtime.getRuntime().availableProcessors();
    
    public static SimpleThreadPool threadPool = new SimpleThreadPool(count, count , 10);


    public static void execute(Runnable task){
           threadPool.execute(task);
    }
}

import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;


public class SimpleThreadPool extends ThreadPoolExecutor{
 
    public SimpleThreadPool (int corePoolSize, int maximumPoolSize, long keepAliveSecond) {
           super(corePoolSize, maximumPoolSize, keepAliveSecond, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>());
    }


}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章