我们用 注册成功 → 通过 MQ 异步打印日志 来模拟"发邮件"的场景,这样你就能清晰掌握 MQ 的核心用法了。
1. 生产者(注册成功时发消息)
@Service
public class UserService {
@Autowired
private RabbitTemplate rabbitTemplate;
@Autowired
private UserRepository userRepository;
public void register(User user) {
// 1. 保存数据库
userRepository.save(user);
// 2. 构造消息
Map<String, String> msg = new HashMap<>();
msg.put("email", user.getEmail());
// 3. 发消息到交换机
rabbitTemplate.convertAndSend("userExchange", "user.register", msg);
System.out.println("✅ 用户注册成功,消息已发送到MQ: " + msg);
}
}
2. 消费者(监听 MQ,打印日志)
@Component
public class MailConsumer {
@RabbitListener(queues = "user.register.queue")
public void handleRegisterMessage(Map<String, String> msg) {
String email = msg.get("email");
// 模拟发送邮件,这里改为打印日志
System.out.println("📩 异步任务:给 " + email + " 发送欢迎邮件(模拟)");
}
}
3. 配置(队列 + 交换机绑定)
@Configuration
public class RabbitConfig {
@Bean
public TopicExchange userExchange() {
return new TopicExchange("userExchange");
}
@Bean
public Queue userRegisterQueue() {
return new Queue("user.register.queue");
}
@Bean
public Binding bindingRegisterQueue(Queue userRegisterQueue, TopicExchange userExchange) {
return BindingBuilder.bind(userRegisterQueue)
.to(userExchange)
.with("user.register");
}
}
🚀 运行流程
-
调用注册接口 → 用户入库成功
-
register()
方法发 MQ 消息 → 控制台打印✅ 用户注册成功,消息已发送到MQ: {email=xxx@qq.com}
-
消费者监听到消息 → 异步打印
📩 异步任务:给 xxx@qq.com 发送欢迎邮件(模拟)
这样整个流程就跑通了:接口快速返回 ,异步处理打印日志,跟发邮件一样的逻辑。
如果出现以下异常:
html
Caused by: java.lang.SecurityException: Attempt to deserialize unauthorized class java.util.HashMap; add allowed class name patterns to the message converter or, if you trust the message originator, set environment variable 'SPRING_AMQP_DESERIALIZATION_TRUST_ALL' or system property 'spring.amqp.deserialization.trust.all' to true······
意思是:Spring AMQP 的消息转换器在反序列化消息时,默认启用了 安全白名单机制 ,不允许随便反序列化任意类,防止反序列化攻击。而你现在收到了一个 HashMap
类型的消息,但 HashMap
不在允许反序列化的白名单里,所以直接报错。
在RabbitConfig类里面加上:
java
@Bean
public MessageConverter jacksonMessageConverter() {
return new Jackson2JsonMessageConverter();
}
即可。