订单取消和支付
RabbitConfig
package com. lagou. rabbitmq. ttlorder. config;
import org. springframework. amqp. core. *;
import org. springframework. amqp. rabbit. connection. ConnectionFactory;
import org. springframework. amqp. rabbit. core. RabbitAdmin;
import org. springframework. amqp. rabbit. listener. DirectMessageListenerContainer;
import org. springframework. amqp. support. converter. Jackson2JsonMessageConverter;
import org. springframework. amqp. support. converter. MessageConverter;
import org. springframework. context. annotation. Bean;
import org. springframework. context. annotation. Configuration;
import org. springframework. scheduling. concurrent. ThreadPoolTaskExecutor;
import java. util. HashMap;
import java. util. Map;
@Configuration
public class RabbitConfig {
@Bean ( name = "rabbitMessageListenerContainer" )
public DirectMessageListenerContainer listenerContainer ( ConnectionFactory connectionFactory) {
DirectMessageListenerContainer container = new DirectMessageListenerContainer ( connectionFactory) ;
container. setAcknowledgeMode ( AcknowledgeMode. MANUAL) ;
container. setPrefetchCount ( 5 ) ;
container. setConsumersPerQueue ( 5 ) ;
container. setMessagesPerAck ( 1 ) ;
ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor ( ) ;
taskExecutor. setCorePoolSize ( 10 ) ;
taskExecutor. setMaxPoolSize ( 20 ) ;
container. setTaskExecutor ( taskExecutor) ;
return container;
}
@Bean
public MessageConverter messageConverter ( ) {
return new Jackson2JsonMessageConverter ( ) ;
}
@Bean
public RabbitAdmin rabbitAdmin ( ConnectionFactory connectionFactory) {
return new RabbitAdmin ( connectionFactory) ;
}
@Bean
public Queue orderQueue ( ) {
return QueueBuilder. durable ( "q.order" ) . build ( ) ;
}
@Bean
public Queue ttlQueue ( ) {
Map< String, Object> args = new HashMap < > ( ) ;
args. put ( "x-message-ttl" , 10 _000) ;
args. put ( "x-dead-letter-exchange" , "x.dlx" ) ;
args. put ( "x-dead-letter-routing-key" , "k.dlx" ) ;
Queue queue = new Queue ( "q.ttl" , true , false , false , args) ;
return queue;
}
@Bean
public Queue dlxQueue ( ) {
Map< String, Object> args = new HashMap < > ( ) ;
Queue dlq = new Queue ( "q.dlx" , true , false , false , args) ;
return dlq;
}
@Bean
public Exchange orderExchange ( ) {
Map< String, Object> args = new HashMap < > ( ) ;
DirectExchange exchange = new DirectExchange ( "x.order" , true , false , args) ;
return exchange;
}
@Bean
public Exchange ttlExchange ( ) {
Map< String, Object> args = new HashMap < > ( ) ;
return new DirectExchange ( "x.ttl" , true , false , args) ;
}
@Bean
public Exchange dlxExchange ( ) {
Map< String, Object> args = new HashMap < > ( ) ;
DirectExchange exchange = new DirectExchange ( "x.dlx" , true , false , args) ;
return exchange;
}
@Bean
public Binding orderBinding ( ) {
return BindingBuilder. bind ( orderQueue ( ) )
. to ( orderExchange ( ) )
. with ( "k.order" )
. noargs ( ) ;
}
@Bean
public Binding ttlBinding ( ) {
return BindingBuilder. bind ( ttlQueue ( ) )
. to ( ttlExchange ( ) )
. with ( "k.ttl" )
. noargs ( ) ;
}
@Bean
public Binding dlxBinding ( ) {
return BindingBuilder. bind ( dlxQueue ( ) )
. to ( dlxExchange ( ) )
. with ( "k.dlx" )
. noargs ( ) ;
}
}
OrderController
package com. lagou. rabbitmq. ttlorder. controller;
import com. lagou. rabbitmq. ttlorder. entity. Order;
import com. lagou. rabbitmq. ttlorder. entity. OrderDetail;
import com. lagou. rabbitmq. ttlorder. entity. OrderStatus;
import com. lagou. rabbitmq. ttlorder. utils. Utils;
import org. springframework. amqp. rabbit. connection. CorrelationData;
import org. springframework. amqp. rabbit. core. RabbitTemplate;
import org. springframework. beans. factory. annotation. Autowired;
import org. springframework. stereotype. Controller;
import org. springframework. ui. Model;
import org. springframework. web. bind. annotation. PathVariable;
import org. springframework. web. bind. annotation. RequestMapping;
import java. util. ArrayList;
import java. util. List;
import java. util. concurrent. ExecutionException;
@Controller
public class OrderController {
@Autowired
private RabbitTemplate rabbitTemplate;
@RequestMapping ( "/order" )
public String order ( Model model) throws ExecutionException, InterruptedException {
List< OrderDetail> details = new ArrayList < > ( ) ;
OrderDetail od = new OrderDetail ( ) ;
od. setItemId ( Utils. generateItemId ( ) ) ;
od. setItemName ( "苹果" ) ;
od. setItemPrice ( 125 ) ;
od. setNum ( 5 ) ;
details. add ( od) ;
Order order = new Order ( ) ;
order. setUserId ( Utils. generateUserId ( ) ) ;
order. setOrderId ( Utils. generateOrderId ( ) ) ;
order. setStatus ( OrderStatus. TO_BE_PAYED. toString ( ) ) ;
order. setDetails ( details) ;
CorrelationData correlationData = new CorrelationData ( ) ;
rabbitTemplate. convertAndSend ( "x.order" , "k.order" , order, correlationData) ;
CorrelationData. Confirm confirm = correlationData. getFuture ( ) . get ( ) ;
boolean confirmAck = confirm. isAck ( ) ;
if ( ! confirmAck) {
return "failorder" ;
}
rabbitTemplate. convertAndSend ( "x.ttl" , "k.ttl" , order. getOrderId ( ) ) ;
model. addAttribute ( "orderId" , order. getOrderId ( ) ) ;
return "order" ;
}
@RequestMapping ( "/failorder/{orderId}" )
public String failOrder ( @PathVariable String orderId , Model model) {
model. addAttribute ( "orderId" , orderId) ;
return "fail" ;
}
}
PayController
package com. lagou. rabbitmq. ttlorder. controller;
import org. springframework. stereotype. Controller;
import org. springframework. ui. Model;
import org. springframework. web. bind. annotation. PathVariable;
import org. springframework. web. bind. annotation. RequestMapping;
@Controller
public class PayController {
@RequestMapping ( "/pay/{orderId}" )
public String pay ( @PathVariable String orderId, Model model) {
model. addAttribute ( "orderId" , orderId) ;
return "success" ;
}
}
MyCancelListener
package com. lagou. rabbitmq. ttlorder. listener;
import com. rabbitmq. client. Channel;
import org. springframework. amqp. core. Message;
import org. springframework. amqp. rabbit. annotation. RabbitListener;
import org. springframework. amqp. rabbit. listener. api. ChannelAwareMessageListener;
import org. springframework. stereotype. Component;
@Component
public class MyCancelListener implements ChannelAwareMessageListener {
@Override
@RabbitListener ( queues = "q.dlx" , ackMode = "MANUAL" )
public void onMessage ( Message message, Channel channel) throws Exception {
String orderId = new String ( message. getBody ( ) ) ;
System. out. println ( "取消订单:" + orderId) ;
channel. basicAck ( message. getMessageProperties ( ) . getDeliveryTag ( ) , false ) ;
}
}
MyOrderListener
package com. lagou. rabbitmq. ttlorder. listener;
import com. lagou. rabbitmq. ttlorder. entity. Order;
import com. lagou. rabbitmq. ttlorder. entity. OrderDetail;
import com. rabbitmq. client. Channel;
import org. springframework. amqp. core. Message;
import org. springframework. amqp. rabbit. annotation. RabbitListener;
import org. springframework. stereotype. Component;
import java. io. IOException;
@Component
public class MyOrderListener {
@RabbitListener ( queues = "q.order" , ackMode = "MANUAL" )
public void onMessage ( Order order , Channel channel , Message message) throws IOException {
System. out. println ( "写入数据库" ) ;
System. out. println ( order) ;
for ( OrderDetail detail : order. getDetails ( ) ) {
System. out. println ( detail) ;
}
channel. basicAck ( message. getMessageProperties ( ) . getDeliveryTag ( ) , false ) ;
}
}
Utils
package com. lagou. rabbitmq. ttlorder. utils;
import java. util. Random;
public class Utils {
private static final Random RANDOM = new Random ( ) ;
public static String generateUserId ( ) {
int i = RANDOM. nextInt ( 1000000 ) ;
String format = String. format ( "%06d" , i) ;
return "u00001-" + format;
}
public static String generateOrderId ( ) {
int i = RANDOM. nextInt ( 1000000 ) ;
String format = String. format ( "%06d" , i) ;
return "oid00001-" + format;
}
public static String generateItemId ( ) {
int i = RANDOM. nextInt ( 1000000 ) ;
String format = String. format ( "%06d" , i) ;
return "item00001-" + format;
}
}
TTLOrderApplication
package com. lagou. rabbitmq. ttlorder;
import org. springframework. boot. SpringApplication;
import org. springframework. boot. autoconfigure. SpringBootApplication;
@SpringBootApplication
public class TTLOrderApplication {
public static void main ( String[ ] args) {
SpringApplication. run ( TTLOrderApplication. class , args) ;
}
}
application.properties
server. port= 8080
# 设计rabbitmq连接
spring. rabbitmq. host= 192.168 .25 .128
spring. rabbitmq. username= admin
spring. rabbitmq. password= 123
# 设置虚拟主机
spring. rabbitmq. virtual- host= /
# 设置发布者确认机制, correlated发布消息成功到交换器后会触发回调方法
# NONE值是禁用发布确认模式,是默认值
spring. rabbitmq. publisher- confirm- type= correlated
spring. rabbitmq. publisher- returns= true
# 消息确认模式为手动确认
spring. rabbitmq. listener. direct. acknowledge- mode= manual