自动取消失效订单(spring整合quartz)

来源:互联网 发布:印度it为何这么强 知乎 编辑:程序博客网 时间:2024/05/17 09:02

转载:http://www.cnblogs.com/qingxinshujuan/p/5403878.html
CronTrigger最详细的Cron表达式范例参考:http://blog.csdn.net/zixiao217/article/details/53075009

任务需求:

  关闭超时未支付的订单,将订单信息置为失效状态

相关技术:
spring框架
  quartz框架定时调度

实现思路:

1.在服务启动时,查询数据库中的已下单未支付的订单数据,按下单时间先后存入队列中,先下单的存到头不,后下单存入队列尾部,取队列的头元素
2.检测与现在的时间,如果超过40分钟,则执行数据操作,即关闭订单,但是只关闭未支付的订单,之后在将头元素从队列移出,并取出下一个元素进行检测,以此类推
3.如果检测出时间未到40分钟,则线程等待相应的时间差,之后在执行订单操作
相关问题:

1.在执行时要防止轮询任务追尾,即在上一个job未执行完毕时就开始下一次轮询,解决方法是在job上加@DisallowConcurrentExecution注解,该注解的作用是让下一次job要等待当前job执行完毕
2.设置的轮询间隔是35分钟一次,订单超时是40分钟,中间有5分钟的时间差,为了防止订单被多次加入队列中,在加入订单队列时要注意去重
相关代码

quartz任务的job,用于检测数据库失效订单并将其关闭,代码如下:

package com.taotao.order.scheduler;import java.text.ParseException;import java.text.SimpleDateFormat;import java.util.ArrayList;import java.util.Date;import java.util.LinkedList;import java.util.List;import java.util.Queue;import org.apache.log4j.Logger;import org.quartz.DisallowConcurrentExecution;import org.quartz.JobExecutionException;import com.taotao.order.pojo.Order;/** * quartz任务的job,用于检测数据库失效订单并将其关闭 * @DisallowConcurrentExecution 这个注解标明上个任务没有执行完毕不会执行下个任务 */@DisallowConcurrentExecutionpublic class CancelOrderJob1 {    //订单有效时间40分钟40 * 60 *    public static final long EFFTIVE_TIME = 1000;    private Logger logger = Logger.getLogger(CancelOrderJob1.class);    public void execute() throws JobExecutionException {        System.out.println("失效订单检测任务开始执行!");        Queue<Order> queue = new LinkedList<>();        // 在每次启动Job时去数据库查找失效订单,并加入到队列中(从数据库中查询,此处使用假数据)        List<Order> list = getInvalidOrder();        if (!list.isEmpty()) {            for (Order o : list) {                queue.offer(o);            }        }        // 获取队列的头元素,开始检测头订单是否失效        Order element = queue.peek();        while (element != null) {            //时间差值            Long diff = this.checkOrder(element);            if (diff != null && diff >= EFFTIVE_TIME) {                System.out.println("开始关闭订单" + element.getOrderId() + "下单时间" + element.getCreateTime());                // 弹出队列                queue.poll();                // 取下一个元素                element = queue.peek();            } else if (diff < EFFTIVE_TIME) {                try {                    System.out.println("等待检测订单" + element.getOrderId() + "下单时间" + element.getCreateTime() + "已下单"                            + diff / 1000 + "秒");                    //线程等待                    Thread.sleep(EFFTIVE_TIME - diff);                } catch (InterruptedException e) {                    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");        Long diff = null;        if (order != null) {            Date createTime = order.getCreateTime();            try {                diff = sdf.parse(sdf.format(date)).getTime() - sdf.parse(sdf.format(createTime)).getTime();            } catch (ParseException e) {                e.printStackTrace();            }        }        // 返回值为毫秒        return diff;    }    /**     *      * @Title: getInvalidOrder     * @Description: TODO(生产订单假数据用于测试)     * @return List<Order> 返回类型     * @return     */    private List<Order> getInvalidOrder() {        List<Order> invalidOrders = new ArrayList<>();        for (int i = 0; i < 50; i++) {            Order order = new Order();            order.setOrderId(String.valueOf(i));            order.setCreateTime(new Date());            invalidOrders.add(order);        }        return invalidOrders;    }}

spring整合quartz配置方式
spring的配置文件如下:

<!-- 配置取消订单job类  -->    <bean id="cancelOrderJob1" class="com.taotao.order.scheduler.CancelOrderJob1"/>    <!-- 配置取消订单JobDetail 使用MethodInvokingJobDetailFactoryBean这种方式job类不需要实现Job接口-->    <bean id="cancelOrderJobDetail1"        class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">        <property name="targetObject">            <ref bean="cancelOrderJob1" />        </property>        <property name="targetMethod">  <!-- 要执行的方法名称 -->            <value>execute</value>        </property>    </bean>    <!-- 配置取消订单简单触发器trigger,启动项目立即执行 -->    <bean id="simpleTrigger1" class="org.springframework.scheduling.quartz.SimpleTriggerFactoryBean">        <property name="jobDetail" ref="cancelOrderJobDetail1"></property>        <property name="startDelay" value="500" />          <property name="repeatInterval" value="0" />          <property name="repeatCount" value="0" />    </bean>    <!-- 配置取消订单触发器trigger -->    <bean id="cancelOrderTrigger1" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean ">        <property name="jobDetail" ref="cancelOrderJobDetail1"></property>        <property name="cronExpression" value="0 0/2 * * * ?"></property>    </bean>    <!-- 配置调度工厂 -->    <bean id="SpringJobSchedulerFactoryBean"        class="org.springframework.scheduling.quartz.SchedulerFactoryBean">        <property name="triggers">            <list>                <!-- 取消订单的两个触发器 -->                <ref bean="simpleTrigger1" />                <ref bean="cancelOrderTrigger1" />            </list>        </property>    </bean>

订单实体类:

package com.taotao.pojo;import java.util.Date;public class TbOrder {    private String orderId;    private String payment;    private Integer paymentType;    private String postFee;    private Integer status;    private Date createTime;    private Date updateTime;    private Date paymentTime;    private Date consignTime;    private Date endTime;    private Date closeTime;    private String shippingName;    private String shippingCode;    private Long userId;    private String buyerMessage;    private String buyerNick;    private Integer buyerRate;    public String getOrderId() {        return orderId;    }    public void setOrderId(String orderId) {        this.orderId = orderId == null ? null : orderId.trim();    }    public String getPayment() {        return payment;    }    public void setPayment(String payment) {        this.payment = payment == null ? null : payment.trim();    }    public Integer getPaymentType() {        return paymentType;    }    public void setPaymentType(Integer paymentType) {        this.paymentType = paymentType;    }    public String getPostFee() {        return postFee;    }    public void setPostFee(String postFee) {        this.postFee = postFee == null ? null : postFee.trim();    }    public Integer getStatus() {        return status;    }    public void setStatus(Integer status) {        this.status = status;    }    public Date getCreateTime() {        return createTime;    }    public void setCreateTime(Date createTime) {        this.createTime = createTime;    }    public Date getUpdateTime() {        return updateTime;    }    public void setUpdateTime(Date updateTime) {        this.updateTime = updateTime;    }    public Date getPaymentTime() {        return paymentTime;    }    public void setPaymentTime(Date paymentTime) {        this.paymentTime = paymentTime;    }    public Date getConsignTime() {        return consignTime;    }    public void setConsignTime(Date consignTime) {        this.consignTime = consignTime;    }    public Date getEndTime() {        return endTime;    }    public void setEndTime(Date endTime) {        this.endTime = endTime;    }    public Date getCloseTime() {        return closeTime;    }    public void setCloseTime(Date closeTime) {        this.closeTime = closeTime;    }    public String getShippingName() {        return shippingName;    }    public void setShippingName(String shippingName) {        this.shippingName = shippingName == null ? null : shippingName.trim();    }    public String getShippingCode() {        return shippingCode;    }    public void setShippingCode(String shippingCode) {        this.shippingCode = shippingCode == null ? null : shippingCode.trim();    }    public Long getUserId() {        return userId;    }    public void setUserId(Long userId) {        this.userId = userId;    }    public String getBuyerMessage() {        return buyerMessage;    }    public void setBuyerMessage(String buyerMessage) {        this.buyerMessage = buyerMessage == null ? null : buyerMessage.trim();    }    public String getBuyerNick() {        return buyerNick;    }    public void setBuyerNick(String buyerNick) {        this.buyerNick = buyerNick == null ? null : buyerNick.trim();    }    public Integer getBuyerRate() {        return buyerRate;    }    public void setBuyerRate(Integer buyerRate) {        this.buyerRate = buyerRate;    }}
package com.taotao.order.pojo;import java.util.List;import com.taotao.pojo.TbOrder;import com.taotao.pojo.TbOrderItem;import com.taotao.pojo.TbOrderShipping;public class Order extends TbOrder{    private List<TbOrderItem> orderItems;    private TbOrderShipping orderShipping;    public List<TbOrderItem> getOrderItems() {        return orderItems;    }    public void setOrderItems(List<TbOrderItem> orderItems) {        this.orderItems = orderItems;    }    public TbOrderShipping getOrderShipping() {        return orderShipping;    }    public void setOrderShipping(TbOrderShipping orderShipping) {        this.orderShipping = orderShipping;    }}
阅读全文
1 0
原创粉丝点击