1)先寫一個日志訂單的消費者;
OrderConsumer.java
package com.seecen.redis.rabbitmq; import lombok.extern.slf4j.Slf4j; import org.springframework.amqp.rabbit.annotation.RabbitListener; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.stereotype.Component; import java.util.Map; @Component @Slf4j public class OrderConsumer { @Autowired private RedisTemplate redisTemplate; @RabbitListener(queues = {"order.queue"}, containerFactory = "rabbitListenerContainerFactory") public void insertLog(Map<String,String> msg){ log.info("接收到超時消息:{}",msg); if (msg!=null){ String orderId=msg.get("orderId"); //獲取狀態 String status = (String) redisTemplate.opsForHash().get("order:" + orderId, "status"); if ("0".equals(status)){//如果還是未付款狀態,則取消訂單 redisTemplate.opsForHash().put("order:"+orderId,"status","-1"); log.warn("訂單:{},因超時未支付而取消",orderId); } } } }
2)在RabbitConfig.java中配置相關需要的配置文件;
RabbitConfig.java
//=========死信隊列實現訂單超時取消============= /** * 訂單延遲隊列的交換機(下單之后存入的交換機) * @return */ @Bean public DirectExchange orderTtlDirect(){ return (DirectExchange) ExchangeBuilder .directExchange("order.ttl.exchange") .durable(true).build(); } /** * 訂單延遲隊列() * @return */ @Bean public Queue orderTtlQueue(){ Map<String,Object> params=new HashMap<>(); //指定超時之后轉發到的交換機 params.put("x-dead-letter-exchange","order.exchange"); //指定超時之后的routing key params.put("x-dead-letter-routing-key","order.cancel"); //params.put("x-expires",1000*60*30);//設置隊列超時時間 params.put("x-message-ttl",30000);//設置隊列中的隊列的超時時間 return new Queue( "order.ttl.queue", true,//持久化 false, false, params ); } @Bean public Binding orderTtlBinding(){ return BindingBuilder.bind(orderTtlQueue())//綁定隊列 .to(orderTtlDirect())//指定交換機 .with("order.ttl.cancel");//路由規則 } /** * 訂單超時后處理的交換機(處理訂單取消的交換機) * @return */ @Bean public DirectExchange orderDirect(){ return (DirectExchange) ExchangeBuilder .directExchange("order.exchange") .durable(true).build(); } /** * 取消訂單處理隊列 * @return */ @Bean public Queue orderQueue(){ return new Queue("order.queue"); } /** * 綁定訂單取消隊列到交換機 * @return */ @Bean public Binding orderBinding(){ return BindingBuilder.bind(orderQueue())//綁定隊列 .to(orderDirect())//指定交換機 .with("order.cancel");//路由規則 }
3)控制層方法;
IndexController.java
package com.seecen.redis.controller; import com.seecen.redis.aop.Log; import com.seecen.redis.aop.LogType; import com.seecen.redis.entity.TAdmin; import com.seecen.redis.service.AdminService; import lombok.extern.slf4j.Slf4j; import org.springframework.amqp.rabbit.core.RabbitTemplate; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.stereotype.Controller; import org.springframework.ui.ModelMap; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.ResponseBody; import javax.annotation.Resource; import java.util.HashMap; import java.util.Map; import java.util.UUID; /** * @author bigpeng * @create 2020-07-21-16:18 */ @Controller @Slf4j public class IndexController { @Autowired private RedisTemplate redisTemplate; @Autowired private AdminService adminService; @Autowired private RabbitTemplate rabbitTemplate; @ResponseBody @GetMapping("/order/{product}") public String order(@PathVariable("product") String product){ //模擬一個訂單,使用map存儲數據 Map map = new HashMap<>(); map.put("product",product); String orderId=UUID.randomUUID().toString(); map.put("orderId",orderId); map.put("status","0");//只發狀態 0:未支付 1:已支付 -1:已取消 //todo 將訂單記錄插入數據庫 //redisTemplate.opsForValue().set("order:"+orderId,map); redisTemplate.opsForHash().putAll("order:"+orderId,map); //發送mq消息到超時隊列 rabbitTemplate.convertAndSend( "order.ttl.exchange", "order.ttl.cancel", map); log.info("下單成功,訂單號:"+orderId); return "下單成功,訂單號:"+orderId; } @ResponseBody @GetMapping("/order/pay/{orderId}") public String pay(@PathVariable("orderId") String orderId){ Boolean hasKey = redisTemplate.hasKey("order:" + orderId); if (hasKey){ redisTemplate.opsForHash().put("order:"+orderId,"status","1"); log.info("訂單:{}支付成功",orderId); } return "訂單:"+orderId+"支付成功!"; } }
