您好,登录后才能下订单哦!
密码登录
            
            
            
            
        登录注册
            
            
            
        点击 登录注册 即表示同意《亿速云用户服务条款》
        道无精粗,人之所见有精粗。如这一间房,人初进来,只见一个大规模如此。处久,便柱壁之类,一一看得明白。再久,如柱上有些文藻,细细都看出来。然只是一间房。
// 抢取订单函数
public synchronized void grabOrder(Long orderId, Long userId) {
    // 获取订单信息
    OrderDO order = orderDAO.get(orderId);
    if (Objects.isNull(order)) {
        throw new BizRuntimeException(String.format("订单(%s)不存在", orderId));
    }
    // 检查订单状态
    if (!Objects.equals(order.getStatus, OrderStatus.WAITING_TO_GRAB.getValue())) {
        throw new BizRuntimeException(String.format("订单(%s)已被抢", orderId));
    }
    
    // 设置订单被抢
    orderDAO.setGrabed(orderId, userId);
}
// 抢取订单函数
public void grabOrder(Long orderId, Long userId) {
    Long lockId = orderDistributedLock.lock(orderId);
    try {
        grabOrderWithoutLock(orderId, userId);
    } finally {
        orderDistributedLock.unlock(orderId, lockId);
    }
}
// 不带锁的抢取订单函数
private void grabOrderWithoutLock(Long orderId, Long userId) {
    // 获取订单信息
    OrderDO order = orderDAO.get(orderId);
    if (Objects.isNull(order)) {
        throw new BizRuntimeException(String.format("订单(%s)不存在", orderId));
    }
    // 检查订单状态
    if (!Objects.equals(order.getStatus, OrderStatus.WAITING_TO_GRAB.getValue())) {
        throw new BizRuntimeException(String.format("订单(%s)已被抢", orderId));
    }
    
    // 设置订单被抢
    orderDAO.setGrabed(orderId, userId);
}
// 登录函数(示意写法)
public UserVO login(String phoneNumber, String verifyCode) {
    // 检查验证码
    if (!checkVerifyCode(phoneNumber, verifyCode)) {
        throw new ExampleException("验证码错误");
    }
    // 检查用户存在
    UserDO user = userDAO.getByPhoneNumber(phoneNumber);
    if (Objects.nonNull(user)) {
        return transUser(user);
    }
    // 创建新用户
    return createNewUser(user);
}
// 创建新用户函数
private UserVO createNewUser(String phoneNumber) {
    // 创建新用户
    UserDO user = new UserDO();
    ...
    userDAO.insert(user);
    // 绑定优惠券
    couponService.bindCoupon(user.getId(), CouponType.NEW_USER);
    
    // 返回新用户
    return transUser(user);
}
// 创建新用户函数
private UserVO createNewUser(String phoneNumber) {
    // 创建新用户
    UserDO user = new UserDO();
    ...
    userDAO.insert(user);
    // 绑定优惠券
    executorService.execute(()->couponService.bindCoupon(user.getId(), CouponType.NEW_USER));
    
    // 返回新用户
    return transUser(user);
}
// 创建新用户函数
private UserVO createNewUser(String phoneNumber) {
    // 创建新用户
    UserDO user = new UserDO();
    ...
    userDAO.insert(user);
    // 发送优惠券消息
    Long userId = user.getId();
    CouponMessageDataVO data = new CouponMessageDataVO();
    data.setUserId(userId);
    data.setCouponType(CouponType.NEW_USER);
    Message message = new Message(TOPIC, TAG, userId, JSON.toJSONBytes(data));
    SendResult result = metaqTemplate.sendMessage(message);
    if (!Objects.equals(result, SendStatus.SEND_OK)) {
        log.error("发送用户({})绑定优惠券消息失败:{}", userId, JSON.toJSONString(result));
    }
    // 返回新用户
    return transUser(user);
}
// 优惠券服务类
@Slf4j
@Service
public class CouponService extends DefaultMessageListener<String> {
    // 消息处理函数
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void onReceiveMessages(MetaqMessage<String> message) {
        // 获取消息体
        String body = message.getBody();
        if (StringUtils.isBlank(body)) {
            log.warn("获取消息({})体为空", message.getId());
            return;
        }
        
        // 解析消息数据
        CouponMessageDataVO data = JSON.parseObject(body, CouponMessageDataVO.class);
        if (Objects.isNull(data)) {
            log.warn("解析消息({})体为空", message.getId());
            return;
        }
        // 绑定优惠券
        bindCoupon(data.getUserId(), data.getCouponType());
    }
}
/** 完成采购动作函数(此处省去获取采购单/验证状态/锁定采购单等逻辑) */
public void finishPurchase(PurchaseOrder order) {
    // 完成相关处理
    ......
    // 回流采购单(调用HTTP接口)
    backflowPurchaseOrder(order);
    
    // 设置完成状态
    purchaseOrderDAO.setStatus(order.getId(), PurchaseOrderStatus.FINISHED.getValue());
}
/** 完成采购动作函数(此处省去获取采购单/验证状态/锁定采购单等逻辑) */
public void finishPurchase(PurchaseOrder order) {
    // 完成相关处理
    ......
    
    // 设置完成状态
    purchaseOrderDAO.setStatus(order.getId(), PurchaseOrderStatus.FINISHED.getValue());
}
/** 执行回流动作函数(此处省去获取采购单/验证状态/锁定采购单等逻辑) */
public void executeBackflow(PurchaseOrder order) {
    // 回流采购单(调用HTTP接口)
    backflowPurchaseOrder(order);
    
    // 设置回流状态
    purchaseOrderDAO.setStatus(order.getId(), PurchaseOrderStatus.BACKFLOWED.getValue());
}
/** 执行回流动作函数(此处省去获取采购单/验证状态/锁定采购单等逻辑) */
public void executeBackflow(PurchaseOrder order) {
    // 完成原始采购单
    rawPurchaseOrderDAO.setStatus(order.getRawId(), RawPurchaseOrderStatus.FINISHED.getValue());
    
    // 设置回流状态
    purchaseOrderDAO.setStatus(order.getId(), PurchaseOrderStatus.BACKFLOWED.getValue());
}
/** 采购单服务接口 */
public interface PurchaseOrderService {
    /** 完成采购单函数 */
    public void finishPurchaseOrder(Long orderId);
}
/** 采购单服务实现 */
@Service("purchaseOrderService")
public class PurchaseOrderServiceImpl implements PurchaseOrderService {
    /** 完成采购单函数 */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void finishPurchaseOrder(Long orderId) {
        // 相关处理
        ...
        // 完成采购单
        purchaseOrderService.finishPurchaseOrder(order.getRawId());
    }
}
/** 执行回流动作函数(此处省去获取采购单/验证状态/锁定采购单等逻辑) */
public void executeBackflow(PurchaseOrder order) {
    // 完成采购单
    purchaseOrderService.finishPurchaseOrder(order.getRawId());
    
    // 设置回流状态
    purchaseOrderDAO.setStatus(order.getId(), PurchaseOrderStatus.BACKFLOWED.getValue());
}
/** 订单DAO接口 */
public interface OrderDAO {
    /** 查询过期订单函数 */
    @Select("select * from t_order where status = 5 and gmt_create < date_sub(current_timestamp, interval 30 day)")
    public List<OrderDO> queryTimeout();
}
/** 订单服务接口 */
public interface OrderService {
    /** 查询过期订单函数 */
    public List<OrderVO> queryTimeout();
}
/** 订单DAO接口 */
public interface OrderDAO {
    /** 查询过期订单函数 */
    @Select("select * from t_order where status = 5 and gmt_create < date_sub(current_timestamp, interval 30 day) limit 0, #{maxCount}")
    public List<OrderDO> queryTimeout(@Param("maxCount") Integer maxCount);
}
/** 订单服务接口 */
public interface OrderService {
    /** 查询过期订单函数 */
    public List<OrderVO> queryTimeout(Integer maxCount);
}
/** 订单DAO接口 */
public interface OrderDAO {
    /** 统计过期订单函数 */
    @Select("select count(*) from t_order where status = 5 and gmt_create < date_sub(current_timestamp, interval 30 day)")
    public Long countTimeout();
    /** 查询过期订单函数 */
    @Select("select * from t_order where status = 5 and gmt_create < date_sub(current_timestamp, interval 30 day) limit #{startIndex}, #{pageSize}")
    public List<OrderDO> queryTimeout(@Param("startIndex") Long startIndex, @Param("pageSize") Integer pageSize);
}
/** 订单服务接口 */
public interface OrderService {
    /** 查询过期订单函数 */
    public PageData<OrderVO> queryTimeout(Long startIndex, Integer pageSize);
}
/** 订单DAO接口 */
public interface OrderDAO {
    /** 查询过期订单函数 */
    @Select("select * from t_order where status = 5 and gmt_create < date_sub(current_timestamp, interval 30 day) limit #{startIndex}, #{pageSize}")
    public List<OrderDO> queryTimeout(@Param("startIndex") Long startIndex, @Param("pageSize") Integer pageSize);
    /** 设置订单超时关闭 */
    @Update("update t_order set status = 10 where id = #{orderId} and status = 5")
    public Long setTimeoutClosed(@Param("orderId") Long orderId)
}
/** 关闭过期订单作业类 */
public class CloseTimeoutOrderJob extends Job {
    /** 分页数量 */
    private static final int PAGE_COUNT = 100;
    /** 分页大小 */
    private static final int PAGE_SIZE = 1000;
    /** 作业执行函数 */
    @Override
    public void execute() {
        for (int i = 0; i < PAGE_COUNT; i++) {
            // 查询处理订单
            List<OrderDO> orderList = orderDAO.queryTimeout(i * PAGE_COUNT, PAGE_SIZE);
            for (OrderDO order : orderList) {
                // 进行超时关闭
                ......
                orderDAO.setTimeoutClosed(order.getId());
            }
            // 检查处理完毕
            if(orderList.size() < PAGE_SIZE) {
                break;
            }
        }
    }
}
当满足查询条件的数据,在操作中不再满足查询条件时,会导致后续分页查询中前startIndex(开始序号)条满足条件的数据被跳过。
/** 订单DAO接口 */
public interface OrderDAO {
    /** 查询过期订单函数 */
    @Select("select * from t_order where status = 5 and gmt_create < date_sub(current_timestamp, interval 30 day) limit 0, #{maxCount}")
    public List<OrderDO> queryTimeout(@Param("maxCount") Integer maxCount);
    /** 设置订单超时关闭 */
    @Update("update t_order set status = 10 where id = #{orderId} and status = 5")
    public Long setTimeoutClosed(@Param("orderId") Long orderId)
}
/** 关闭过期订单作业(定时作业) */
public class CloseTimeoutOrderJob extends Job {
    /** 分页数量 */
    private static final int PAGE_COUNT = 100;
    /** 分页大小 */
    private static final int PAGE_SIZE = 1000;
    /** 作业执行函数 */
    @Override
    public void execute() {
        for (int i = 0; i < PAGE_COUNT; i++) {
            // 查询处理订单
            List<OrderDO> orderList = orderDAO.queryTimeout(PAGE_SIZE);
            for (OrderDO order : orderList) {
                // 进行超时关闭
                ......
                orderDAO.setTimeoutClosed(order.getId());
            }
            // 检查处理完毕
            if(orderList.size() < PAGE_SIZE) {
                break;
            }
        }
    }
}
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。