電子商務平台自動取消失效訂單


任務需求:

  關閉超時未支付的訂單,將訂單信息置為失效狀態

相關技術:

  quartz框架定時調度

實現思路:

  1.   在服務啟動時,查詢數據庫中的已下單未支付的訂單數據,按下單時間先后存入隊列中,先下單的存到頭不,后下單存入隊列尾部,取隊列的頭元素
  2.   檢測與現在的時間,如果超過40分鍾,則執行數據操作,即關閉訂單,但是只關閉未支付的訂單,之后在將頭元素從隊列移出,並取出下一個元素進行檢測,以此類推
  3.   如果檢測出時間未到40分鍾,則線程等待相應的時間差,之后在執行訂單操作

相關問題:

  1.   在執行時要防止輪詢任務追尾,即在上一個job未執行完畢時就開始下一次輪詢,解決方法是在job上加@DisallowConcurrentExecution注解,該注解的作用是讓下一次job要等待當前job執行完畢
  2.   設置的輪詢間隔是35分鍾一次,訂單超時是40分鍾,中間有5分鍾的時間差,為了防止訂單被多次加入隊列中,在加入訂單隊列時要注意去重

相關代碼

package com.ichunshen.dolook.module.trade.order.support;

import static org.quartz.CronScheduleBuilder.cronSchedule;
import static org.quartz.JobBuilder.newJob;
import static org.quartz.TriggerBuilder.newTrigger;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;

import org.apache.log4j.Logger;
import org.quartz.CronTrigger;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.SchedulerFactory;
import org.quartz.impl.StdSchedulerFactory;

import com.ichunshen.dolook.module.trade.order.job.CancelOrderJob;
import com.ichunshen.dolook.module.trade.order.model.Order;
import com.ichunshen.dolook.module.trade.order.web.OrderController;

public class CancelOrderTask {
    
    static Logger logger = Logger.getLogger(OrderController.class);
    
    public void cancelOrderTask() throws SchedulerException { // 獲得一個scheduler
        SchedulerFactory sh = new StdSchedulerFactory();
        Scheduler scheduler = sh.getScheduler();

        // 創建一個job 任務名,任務組,任務執行類
        JobDetail job = newJob(CancelOrderJob.class).withIdentity("cancelOrderJob", "orderJob").build();
        
        //創建一個觸發器
        CronTrigger trigger = newTrigger().withIdentity("cancelOrderTrigger", "orderTrigger")
                .withSchedule(cronSchedule("0 0/2 * * * ?")).build();
        //將job和觸發器綁定
        Date date=scheduler.scheduleJob(job, trigger);
        
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS");
        logger.info(job.getKey()+"取消訂單定時任務於"+sdf.format(date)+"開始執行");
        
        scheduler.start();
    }

}
package com.ichunshen.dolook.module.trade.order.job;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;

import org.apache.log4j.Logger;
import org.quartz.DisallowConcurrentExecution;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.quartz.PersistJobDataAfterExecution;
import org.quartz.StatefulJob;

import com.ichunshen.dolook.module.trade.order.model.Order;
import com.ichunshen.dolook.module.trade.order.service.OrderService;
import com.ichunshen.dolook.module.trade.order.support.OrderQueue;
import com.ichunshen.dolook.support.DoLookConstant.OrderCancelMethod;

import cn.joy.framework.plugin.quartz.ScheduleTask;
/**
 * quartz任務的job,用於檢測數據庫失效訂單並將其關閉
 * @author wangpeiqing
 *
 */
@DisallowConcurrentExecution
public class CancelOrderJob implements ScheduleTask {
    Logger logger=Logger.getLogger(CancelOrderJob.class);

    @Override
    public void execute(JobExecutionContext arg0) throws JobExecutionException {
        // TODO Auto-generated method stub
        System.out.println("失效訂單檢測任務開始執行!");
        Order order =new Order();
        OrderQueue queue = new OrderQueue();
        
        //在每次啟動Job時去數據庫查找失效訂單,並加入到隊列中
        List<Order> list=order.getInvalidOrder();
        if(!list.isEmpty()){
            for (Order o : list) {
                queue.offer(o);
            }
        }
        //獲取隊列的頭元素,開始檢測頭訂單是否失效
        Order element=queue.peek();
        while (element!=null) {
            Long time=this.checkOrder(element);
            if (time != null && time >=2400*1000) {
                System.out.println("開始關閉訂單"+element.getOcode()+"下單時間"+element.getOrderTime());
                element.cancelInvalidOrderStatus(element.getOcode(), OrderCancelMethod.INVALID_TIME);
                queue.poll();
                element=queue.peek();
            }else if(time<2400*1000){
                try {
                    System.out.println("等待檢測訂單"+element.getOcode()+"下單時間"+element.getOrderTime()+"已下單"+time/1000+"秒");
                    Thread.sleep(time);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                    logger.info("CancelOrderJob.checkOrder定時任務出現問題");
                }
            }
        }
    }
    /**
     * 獲取訂單的下單時間和現在的時間差
     * @author wangpeiqing
     * 2016年4月16日
     * @param order
     * @return
     *
     */
    public Long checkOrder(Order order) {
        Date date = new Date();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        OrderQueue queue = new OrderQueue();
        Long diff = null;
        if (order != null) {
            Date orderTime = order.getOrderTime();
            try {
                diff = sdf.parse(sdf.format(date)).getTime() - sdf.parse(sdf.format(orderTime)).getTime();
            } catch (ParseException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        //返回值為毫秒
        return diff;
    }

}
package com.ichunshen.dolook.module.trade.order.support;

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;

import org.quartz.SchedulerException;

public class CancelOrderListener implements ServletContextListener {

    @Override
    public void contextInitialized(ServletContextEvent sce) {
        // TODO Auto-generated method stub
        CancelOrderTask task = new CancelOrderTask();
        try {
            task.cancelOrderTask();
        } catch (SchedulerException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    @Override
    public void contextDestroyed(ServletContextEvent sce) {
        // TODO Auto-generated method stub

    }

}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM