debug error怎么解决_分布式事务的解决方案

037a2d842b17d176b95ee0598279ebf7.png

一. 跨库事务解决方案

使用 二阶段提交(try-commit/rollback) 的方式:

993cc34b8f0a38926c68575ad74a8910.png

二. 微服务解决方案

1. TCC(try - confirm/cancel)二阶段提交方案——追求强一致性方案

3252bff078fb1895a5f2c474cedb2c25.png

2. TCC 二阶段柔性方案

c135698952f23f08b8678d2aa6449b84.png

3. 使用日志轮询的方案

4aad96950c6e093daa3f0c64d901ea39.png

订单类 :

@Service(value = "orderServiceImpl")
public class OrderServiceImpl extends ServersManager<Order, OrderDao> implements
        OrderService {
	private static final org.slf4j.Logger logger = LoggerFactory
			.getLogger(OrderServiceImpl.class);
    @Resource(name="orderDaoFront")
    @Override
    public void setDao(OrderDao orderDao) {
        this.dao = orderDao;
    }

    @Autowired
	private OrderdetailDao orderdetailDao;
    @Autowired
	private OrderpayDao orderpayDao;
    @Autowired
	private OrdershipDao ordershipDao;
    @Autowired
	private OrderlogDao orderlogDao;
    @Autowired
	private ProductService productService;
    @Autowired
	private AccountService accountService;
   

	public void setAccountService(AccountService accountService) {
		this.accountService = accountService;
	}

	public void setProductService(ProductService productService) {
		this.productService = productService;
	}

	public void setOrderpayDao(OrderpayDao orderpayDao) {
		this.orderpayDao = orderpayDao;
	}

	public void setOrderlogDao(OrderlogDao orderlogDao) {
		this.orderlogDao = orderlogDao;
	}

	public void setOrdershipDao(OrdershipDao ordershipDao) {
		this.ordershipDao = ordershipDao;
	}

	public void setOrderdetailDao(OrderdetailDao orderdetailDao) {
		this.orderdetailDao = orderdetailDao;
	}

	public Order createOrder(Order order, List<Orderdetail> orderdetailList, Ordership ordership)
			throws Exception {
		if(order==null || orderdetailList==null || orderdetailList.size()==0 || ordership==null){
			throw new NullPointerException("参数不能为空!");
		}
		//创建订单
		int orderID = dao.insert(order);
		logger.debug("orderID=" + orderID);
		
		//创建订单项
		for (int i = 0; i < orderdetailList.size(); i++) {
			Orderdetail orderdetail = orderdetailList.get(i);
			orderdetail.setOrderID(orderID);
			orderdetailDao.insert(orderdetail);
		}
		
		//创建支付记录对象
		Orderpay orderpay = new Orderpay();
		orderpay.setOrderid(order.getId());
		orderpay.setPaystatus(Orderpay.orderpay_paystatus_n);
		orderpay.setPayamount(Double.valueOf(order.getAmount()));
		orderpay.setPaymethod(Orderpay.orderpay_paymethod_alipayescow);
		int orderpayID = orderpayDao.insert(orderpay);
		logger.error("orderpayID="+orderpayID);
		order.setOrderpayID(String.valueOf(orderpayID));
		
		//记录配送信息
		ordership.setOrderid(String.valueOf(orderID));
		ordershipDao.insert(ordership);
		
		//记录订单创建日志
		Orderlog orderlog = new Orderlog();
		orderlog.setOrderid(String.valueOf(orderID));
		orderlog.setAccount(order.getAccount());
		orderlog.setContent("【创建订单】用户创建订单。订单总金额:"+order.getAmount());
		orderlog.setAccountType(Orderlog.orderlog_accountType_w);
		orderlogDao.insert(orderlog);
		Order orderData=new Order();
		orderData.setId(String.valueOf(orderID));
		orderData.setOrderpayID(order.getOrderpayID());
		return orderData;
	}
    
    @Autowired
    public MessageService messageService;
	
	public Order createMiaoshaOrder(Order order) {
		if(order==null){
			throw new RuntimeException("订单参数不能为空!");
		}
		List<Orderdetail> orderdetailList = order.getOrderdetail();
		Ordership ordership = order.getOrdership();
		if(orderdetailList==null || orderdetailList.size()==0 || ordership==null){
			throw new RuntimeException("订单明细或地址参数不能为空!");
		}
		
		//创建订单
		int orderID  = dao.insert(order);
		logger.debug("orderID=" + orderID);
        
        //使用mq的方式解决分布式事务
        Message message = new Message(orderID,"",productId,"init");
        messageService.receiveMsg(message);
        
        
		
		//创建订单明细
		for (int i = 0; i < orderdetailList.size(); i++) {
			Orderdetail orderdetail = orderdetailList.get(i);
			orderdetail.setOrderID(orderID);
			orderdetailDao.insert(orderdetail);
		}
		
		//创建支付记录对象
		Orderpay orderpay = new Orderpay();
		orderpay.setOrderid(order.getId());
		orderpay.setPaystatus(Orderpay.orderpay_paystatus_n);
		orderpay.setPayamount(Double.valueOf(order.getAmount()));
		orderpay.setPaymethod(Orderpay.orderpay_paymethod_alipayescow);
		int orderpayID = orderpayDao.insert(orderpay);
		logger.error("orderpayID="+orderpayID);
		order.setOrderpayID(String.valueOf(orderpayID));
		
		//记录配送信息
		ordership.setOrderid(String.valueOf(orderID));
		ordershipDao.insert(ordership);
		
		//记录订单创建日志
		Orderlog orderlog = new Orderlog();
		orderlog.setOrderid(String.valueOf(orderID));
		orderlog.setAccount(order.getAccount());
		orderlog.setContent("【创建订单】用户创建订单。订单总金额:"+order.getAmount());
		orderlog.setAccountType(Orderlog.orderlog_accountType_w);
		orderlogDao.insert(orderlog);
		
        
        //TODO 插入日志 log(orderId,productId,deductStockCount,status)
        //定时任务 轮询执行程序,从日志里获取该订单信息,往库存库里操作,如果插入成功,定时任务就不需要继续执行,如果不成功,继续执行。
        
		//减库存,使用分布式事务后减库存逻辑需交给消息中心处理,这块逻辑需要注释掉
		for (int i = 0; i < orderdetailList.size(); i++) {
			String productID = String.valueOf(orderdetailList.get(i).getProductID());
			//数据库减库存
			Product product = new Product();
			product.setId(productID);
			//TODO 插入日志 log(orderId,productId,deductStockCount,status)
			int updateNums = productService.updateStockAfterMiaoshaSuccess(product);
			if (updateNums <= 0) {
				throw new ProductSoldOutException("更新库存失败");
			}
		}
		
		Order orderData=new Order();
		orderData.setId(String.valueOf(orderID));
		orderData.setOrderpayID(order.getOrderpayID());
        
        
        //发送确认消息
        //使用mq的方式解决分布式事务
        Message message = new Message(orderID,"",productId,"sent");
        messageService.receiveMsg(message);
        
        
		return orderData;
	}

	@Override
	public List<Order> selectOrderInfo(Order order) {
		return dao.selectOrderInfo(order);
	}

//	@Override
//	public boolean updateOrderStatus(Order order) {
//		if(order==null){
//			throw new NullPointerException("参数不能为空!");
//		}
//
//		Orderpay orderpay = orderpayDao.selectById(order.getOrderpayID());
//		if(orderpay==null){
//			throw new NullPointerException("根据支付记录号查询不到支付记录信息!");
//		}
//		String orderid = orderpay.getOrderid();//订单ID
//		
//		//更新支付记录为成功支付
//		Orderpay orderpay2 = new Orderpay();
//		orderpay2.setId(order.getOrderpayID());
//		orderpay2.setTradeNo(order.getTradeNo());
//		orderpay2.setPaystatus(Orderpay.orderpay_paystatus_y);
//		orderpayDao.update(orderpay2);
//		
//		//更新订单的支付状态为成功支付
//		order.setId(orderid);
//		order.setPaystatus(Order.order_paystatus_y);
//		dao.update(order);
//		return true;
//	}
	
	@Override
	public boolean alipayNotify(String trade_status,String refund_status,String out_trade_no,String trade_no) {
		try {
			return alipayNotify0(trade_status, refund_status, out_trade_no, trade_no);
		} catch (Exception e) {
			logger.error(">>>alipayNotify...Exception..");
			e.printStackTrace();
			return false;
		}
	}
	
	private boolean alipayNotify0(String trade_status,String refund_status,String out_trade_no,String trade_no) {
		synchronized (FrontContainer.alipay_notify_lock) {
			logger.error("trade_status = " + trade_status + ",refund_status = " + refund_status + ",out_trade_no = " + out_trade_no + ",trade_no = " + trade_no);
			if ((StringUtils.isBlank(trade_status)
					&& StringUtils.isBlank(refund_status)) || (StringUtils.isBlank(out_trade_no)
							&& StringUtils.isBlank(trade_no))) {
				logger.error("请求非法!");
				return false;
			}
			String orderpayID = null;
			if(out_trade_no.startsWith("test")){
				//此处做一个说明,localhost或127.0.0.1下的订单的请求发给支付宝的商户订单号都是test开头的,正式的都是非test开头的。
				//可以参见OrdersAction.createPayInfo()方法。
				orderpayID = out_trade_no.substring(4);
			}else{
				orderpayID = out_trade_no;
			}
			logger.error("orderpayID = " + orderpayID);
			Orderpay orderpay = orderpayDao.selectById(orderpayID);
			if(orderpay==null){
				throw new NullPointerException("根据支付记录号查询不到支付记录信息!");
			}
			String orderid = orderpay.getOrderid();//订单ID
			String content = null;
			
			if(StringUtils.isNotBlank(refund_status)){
				/**
				 * 退款流程
				 */
				if(refund_status.equals("WAIT_SELLER_AGREE")){//等待卖家同意退款	==>卖家需处理
					content = "【支付宝异步通知-->退款流程】等待卖家同意退款(WAIT_SELLER_AGREE)。";
					
				}else if(refund_status.equals("WAIT_BUYER_RETURN_GOODS")){//卖家同意退款,等待买家退货	==>通知买家退货,此 可以发站内信、短信、或邮件 通知对方
					content = "【支付宝异步通知-->退款流程】退款协议达成,等待买家退货(WAIT_BUYER_RETURN_GOODS)。";
					
				}else if(refund_status.equals("WAIT_SELLER_CONFIRM_GOODS")){//买家已退货,等待卖家收到退货	==>支付宝会通知卖家
					content = "【支付宝异步通知-->退款流程】等待卖家收货(WAIT_SELLER_CONFIRM_GOODS)。";
					
				}else if(refund_status.equals("REFUND_SUCCESS")){//卖家收到退货,退款成功,交易关闭	==>卖家登陆支付宝,确认OK。
					//http://club.alipay.com/simple/?t9978565.html
					content = "【支付宝异步通知-->退款流程】退款成功(REFUND_SUCCESS)。";
					
				}else if(refund_status.equals("REFUND_CLOSED")){//卖家收到退货,退款成功,交易关闭	==>卖家登陆支付宝,确认OK。
					//http://club.alipay.com/simple/?t9978565.html
					content = "【支付宝异步通知-->退款流程】退款关闭(REFUND_CLOSED)。";
					
				}else if(refund_status.equals("SELLER_REFUSE_BUYER")){//卖家收到退货,退款成功,交易关闭	==>卖家登陆支付宝,确认OK。
					//http://club.alipay.com/simple/?t9978565.html
					content = "【支付宝异步通知-->退款流程】卖家不同意协议,等待买家修改(SELLER_REFUSE_BUYER)。";
				}
				else{
					//一般不会出现
					content = "【支付宝异步通知-->退款流程】未知。refund_status = " + refund_status;
				}
				updateRefundStatus(orderid, refund_status);
			}else if(StringUtils.isNotBlank(trade_status)){
				/**
				 * 交易流程
				 */
				if(trade_status.equals("WAIT_BUYER_PAY")){//等待买家付款
					content = "【支付宝异步通知】等待买家付款(WAIT_BUYER_PAY)。";
					
				}else if(trade_status.equals("WAIT_SELLER_SEND_GOODS")){//已付款,等待卖家发货
					if(orderpay.getPaystatus().equals(Orderpay.orderpay_paystatus_y)){
						//由于支付宝的同步通知、异步通知,那么WAIT_SELLER_SEND_GOODS的时候会有2次通知,所以需要synchronized处理好,保证订单状态和日志的一致性。
						return true;
					}
					
					content = "【支付宝异步通知】已付款,等待卖家发货(WAIT_SELLER_SEND_GOODS)。";
					
					//更新支付记录为【成功支付】
					Orderpay orderpay2 = new Orderpay();
					orderpay2.setId(orderpayID);
					orderpay2.setTradeNo(trade_no);
					orderpay2.setPaystatus(Orderpay.orderpay_paystatus_y);
					orderpayDao.update(orderpay2);
					
					/**
					 * 真实砍库存,并同步减少内容库存数
					 */
					logger.error("真实砍库存,并同步减少内容库存数...");
					Orderdetail orderdetail = new Orderdetail();
					orderdetail.setOrderID(Integer.valueOf(orderid));
					List<Orderdetail> orderdetailList = orderdetailDao.selectList(orderdetail);
					logger.error("orderdetailList = " + orderdetailList.size());
					String lowStocks = null;//订单是否缺货记录
//					int score = 0;//商品积分汇总
					for (int i = 0; i < orderdetailList.size(); i++) {
						Orderdetail detailInfo = orderdetailList.get(i);
						String productID = String.valueOf(detailInfo.getProductID());
						//内存砍库存呢
						ProductStockInfo stockInfo = SystemManager.getInstance().getProductStockMap().get(productID);
						if(stockInfo.getStock() >= detailInfo.getNumber()){
							stockInfo.setStock(stockInfo.getStock() - detailInfo.getNumber());
							stockInfo.setChangeStock(true);
							//数据库砍库存
							Product product = new Product();
							product.setId(productID);
							product.setStock(stockInfo.getStock());
							product.setAddSellcount(detailInfo.getNumber());//增加销量
							productService.updateStockAfterPaySuccess(product);
						}else{
							lowStocks = Order.order_lowStocks_y;
							//记录库存不足
							Orderdetail od = new Orderdetail();
							od.setId(detailInfo.getId());
							od.setLowStocks(Orderdetail.orderdetail_lowstocks_y);
							orderdetailDao.update(od);
						}
//						score += stockInfo.getScore();
						logger.error("productID = " + productID + ",stockInfo.getStock() = " + stockInfo.getStock());
//						SystemManager.productStockMap.put(product.getId(),stockInfo);
					}
					
					//更新订单的支付状态为【已支付】
					Order order = new Order();
					order.setId(orderid);
					if (lowStocks != null) {
						order.setLowStocks(Order.order_lowStocks_y);
					}
					order.setPaystatus(Order.order_paystatus_y);
					dao.update(order);
					
				}else if(trade_status.equals("WAIT_BUYER_CONFIRM_GOODS")){//已发货,等待买家确认收货
					content = "【支付宝异步通知】已发货,等待买家确认收货(WAIT_BUYER_CONFIRM_GOODS)。";
					//更新订单状态为【已发货】
					Order order = dao.selectById(orderid);
					if(order==null){
						throw new NullPointerException("根据订单号查询不到订单信息,orderid="+orderid);
					}
					
					logger.error("order.getStatus()"+order.getStatus()+",trade_status=WAIT_BUYER_CONFIRM_GOODS");
					
					Orderlog orderlog = new Orderlog();
					orderlog.setContent(content);
					orderlog.setAccount(order.getAccount());
					//临时解决办法,防止此日志重复记录.
					if(orderlogDao.selectCount(orderlog) > 0){
						return true;
					}
					
//					if(order.getStatus().equals(Order.order_status_send)){
//						//当前订单状态已经是这个状态了,无需重复操作。
//						return true;
//					}
					
					//防止由于支付宝异步消息的先后顺序,导致把订单的状态更新混乱了。
					if(order.getStatus().equals(Order.order_status_pass)){
						order = new Order();
						order.setId(orderid);
						order.setStatus(Order.order_status_send);
						dao.update(order);
					}
				}else if(trade_status.equals("TRADE_FINISHED")){//交易完成
					content = "【支付宝异步通知】交易完成(TRADE_FINISHED)。";
					
					Order order = dao.selectById(orderid);
					if(order==null){
						throw new NullPointerException("根据订单号查询不到订单信息,orderid="+orderid);
					}
					
					//订单结束后,订单上面赠送的积分都成功转移到用户账户上。
					Account acc = new Account();
					acc.setAccount(order.getAccount());
					acc.setAddScore(order.getScore() - order.getAmountExchangeScore());//支付完成,扣除订单消耗的积分
					accountService.updateScore(acc);
					
					//更新订单状态为【已签收】
					order = new Order();
					order.setId(orderid);
					order.setStatus(Order.order_status_sign);
					dao.update(order);
				}else{
					//一般不会出现
					content = "【支付宝异步通知】未知。trade_status = " + trade_status;
				}
			}else{
				throw new RuntimeException("运行异常!");
			}
			
			/**
			 * 以上代码,如不可以返回都会走到此处,记录下日志.
			 */
			insertOrderlog(orderid, content);
			
			return true;
		}
	}
	
	/**
	 * 更新订单的退款状态
	 * @param orderid	订单ID
	 * @param refundStatus	退款状态
	 */
	private void updateRefundStatus(String orderid,String refundStatus){
		Order order = new Order();
		order.setId(orderid);
		order.setRefundStatus(refundStatus);
		dao.update(order);
	}
	
	/**
	 * 插入订单操作日志
	 * @param orderid	订单ID
	 * @param content	日志内容
	 */
	private void insertOrderlog(String orderid,String content) {
		Orderlog orderlog = new Orderlog();
		orderlog.setOrderid(orderid);//订单ID
		orderlog.setAccount("alipay_notify");//操作人账号
		orderlog.setContent(content);//日志内容
		orderlog.setAccountType(Orderlog.orderlog_accountType_p);
		orderlogDao.insert(orderlog);
	}

	@Override
	public OrderSimpleReport selectOrdersSimpleReport(String account) {
		return dao.selectOrdersSimpleReport(account);
	}
}

4. 使用mq消息队列的方式做补偿

ea163cf1ffa5441a50d750b8890f0d5d.png

消息中间件:

/**
 * 独立消息服务,目前只实现一个大框架,主要目的是给大家理清分布式事务的控制思路
 *
 */
@Service(value = "messageServiceImpl")
public class MessageServiceImpl implements MessageService {

	@Override
	@Transactional
	public void receiveMsg(Message message) {
		if (message == null) {
			throw new RuntimeException("消息为空");
		}

		switch (message.getStatus()) {
		case MessageStatus.INIT:
			// TODO save msg
			System.out.println("保存初始消息");
			break;
		case MessageStatus.SENT:
			// TODO update msg status 为sent
			// TODO 发送消息到订单减库存队列,这块待同学们自己实现
			System.out.println("更新消息状态为sent");
			break;
		case MessageStatus.END:
			// TODO update msg status 为end
			break;

		default:
			throw new RuntimeException("消息状态有误");
		}
	}

}

MessageService :

public interface MessageService {

	void receiveMsg(Message msg);
}

Message :

import java.io.Serializable;

public class Message  implements Serializable {

	private Integer id;
	private String bizId;
	private String bizType;
	private String bizData;
	private int status;
	
	public Message(String bizId, String bizType, String bizData, int status) {
		super();
		this.bizId = bizId;
		this.bizType = bizType;
		this.bizData = bizData;
		this.status = status;
	}
	
	public Integer getId() {
		return id;
	}
	public void setId(Integer id) {
		this.id = id;
	}
	public String getBizId() {
		return bizId;
	}
	public void setBizId(String bizId) {
		this.bizId = bizId;
	}
	public String getBizType() {
		return bizType;
	}
	public void setBizType(String bizType) {
		this.bizType = bizType;
	}
	public String getBizData() {
		return bizData;
	}
	public void setBizData(String bizData) {
		this.bizData = bizData;
	}
	public int getStatus() {
		return status;
	}
	public void setStatus(int status) {
		this.status = status;
	}	
}

三. 定时任务Quartz的使用

1. Quartz 概述

Quartz 是 OpenSymphony 开源组织在 Job Scheduling 领域又一个开源项目,它可以与 J2EE 与 J2SE 应用程序相结合也可以单独使用。Quartz 可以用来创建简单或为运行十个,百个,甚至是好几万个 Jobs 这样复杂的程序。Jobs 可以做成标准的 Java 组件或 EJBs。

2. 为什么使用 Quartz?

Quartz 是一个任务调度框架。比如你遇到这样的问题:

  • 每天 02:00 发送一份工作邮件给工作组成员并抄送给老板(假装自己很努力的工作到深夜)
  • 每月 2 号提醒自己还信用卡或自动还款
  • 每秒钟发 N 笔脏数据给竞争对手公司的服务器(!←_←)

这些问题总结起来就是:在某一个有规律的时间点干某件事。并且时间的触发的条件可以非常复杂,复杂到需要一个专门的框架来干这个事。Quartz 就是来干这样的事,你给它一个触发条件的定义,它负责到了时间点,触发相应的 Job 起来干活(睡 NMB 起来嗨!)。

3. 什么是 cron 表达式?

一个 cron 表达式具体表现就是一个字符串,这个字符串中包含 6~7 个字段,字段之间是由空格分割的,每个字段可以由任何允许的值以及允许的特殊字符所构成,下面表格列出了每个字段所允许的值和特殊字符

501983ec3e7b1ebe61c22f2b274afa2d.png
  • * 字符被用来指定所有的值。如:* 在分钟的字段域里表示“每分钟”。
  • - 字符被用来指定一个范围。如:10-12 在小时域意味着“10点、11点、12点”
  • , 字符被用来指定另外的值。如:MON,WED,FRI 在星期域里表示“星期一、星期三、星期五”.
  • ? 字符只在日期域和星期域中使用。它被用来指定“非明确的值”。当你需要通过在这两个域中的一个来指定一些东西的时候,它是有用的。
  • L 字符指定在月或者星期中的某天(最后一天)。即 “Last” 的缩写。但是在星期和月中 “L” 表示不同的意思,如:在月字段中 “L” 指月份的最后一天 “1月31日,2月28日”,如果在星期字段中则简单的表示为“7”或者“SAT”。如果在星期字段中在某个 value 值得后面,则表示 “某月的最后一个星期 value” ,如 “6L” 表示某月的最后一个星期五。
  • W 字符只能用在月份字段中,该字段指定了离指定日期最近的那个星期日。
  • # 字符只能用在星期字段,该字段指定了第几个星期 value 在某月中

每一个元素都可以显式地规定一个值(如 6),一个区间(如 9-12 ),一个列表(如 9,11,13 )或一个通配符(如 *)。“月份中的日期”和“星期中的日期”这两个元素是互斥的,因此应该通过设置一个问号(?)来表明你不想设置的那个字段。

de80df70b03daee4439ad4041191ca0e.png

cron在线编辑器 : 在线Cron表达式生成器

4. Spring Boot 集成 Quartz

(1). 创建项目

创建一个名为 hello-quartz 的项目

(2). pom文件

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.funtl</groupId>
    <artifactId>hello-quartz</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>

    <name>hello-quartz</name>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.4.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-quartz</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

主要增加了 org.springframework.boot:spring-boot-starter-quartz 依赖

(3). Application

package com.duo.hello.quatrz;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableScheduling;

@EnableScheduling
@SpringBootApplication
public class HelloQuatrzApplication {
    public static void main(String[] args) {
        SpringApplication.run(HelloQuatrzApplication.class, args);
    }
}

使用 @EnableScheduling 注解来开启计划任务功能

(4). 创建任务

我们创建一个每 5 秒钟打印当前时间的任务来测试 Quartz

package com.duo.hello.quatrz.tasks;

import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

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

@Component
public class PrintCurrentTimeTask {
    @Scheduled(cron = "0/5 * * * * ? ")
    public void printCurrentTime() {
        System.out.println("Current Time is:" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
    }
}

5. 定时任务

@Component  
public class AnnotationQuartz {  
	
	
    @Scheduled(cron = "0/30 * * * * ?")
    public void processInitMsg() { 
    	//TODO 回调消息发送服务中心接口用消息业务id查找对应的业务数据是否生成,如果生成则直接将消息改成已发送状态并投递消息到mq
    }  
    
    @Scheduled(cron = "0/60 * * * * ?")
    public void processSentMsg() {  
    	//TODO 定时处理未完成的消息,如果已经几次查找消息都还是处于未完成状态,则很可能消息没有被消费者接收成功,由于消费者有幂等性实现,则可重发消息给mq
    }  
} 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值