SpringBoot+RabbitMQ实现消息队列发邮件

在我的之前写的轻博客中,当用户注册时需要发送一封邮件到用户注册的邮箱来激活账号,因为是同步方法,所以响应很慢,得等到邮件发送成功才有响应,所以打算使用RabbiMQ来异步发送邮件,提高响应速度

本次是简单使用RabbitMQ作个简单的发送邮件Demo,告诉大家基本的使用方法

  • 首先使用IDEA创建两个模块
    在这里插入图片描述
    email-producer模拟注册功能,接收用户注册的邮箱地址,把邮箱地址存入到消息队列中,email-consumer模拟发送邮件功能,当消息队列有消息时,消费消息,根据消息中的邮箱地址发送邮件。
    创建的时候添加Web和RabbitMQ的依赖
    在这里插入图片描述
    发送邮件可以使用javamail,我选择的是使用Hutool的邮件工具,需要在email-consumer中引入下来两个依赖
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-extra</artifactId>
            <version>5.3.8</version>
        </dependency>
        <dependency>
            <groupId>javax.mail</groupId>
            <artifactId>mail</artifactId>
            <version>1.4.7</version>
        </dependency>

Email-Producer

  • 配置RabbitMQ
spring:
  rabbitmq:
    host: 一般为localhost,我是放在了服务器上所以是服务器地址
    username: guest
    password: guest
    port: 5672
server:
  port: 7777
  • 接着就是创建队列,交换器,路由键等
@Configuration
public class RabbitmqConfig {

    // 队列名称
    public static final String QUEUE_NAME = "email_queue";
    
    // 交换器名称
    public static final String EXCHANGE = "email_exchange";

    // 路由键名称
    public static final String ROUTEKEY = "email_routekey";

    @Autowired
    private Environment environment;

    /**
    * @Description: 创建队列
    * @Param: []
    * @return: org.springframework.amqp.rabbit.annotation.Queue
    * @Author: 林北
    * @Date: 2020-07-09
    */
    @Bean
    Queue queue(){
        // 是否持久化
        boolean durable = true;
        // 仅创建者可以使用的私有队列,断开后自动删除
        boolean exclusive = false;
        // 当所有消费客户端连接端库后,是否自动删除队列
        boolean autoDelete = false;
        return new Queue(QUEUE_NAME, durable,exclusive,autoDelete);
    }

    /**
    * @Description: 创建Topic交换器
    * @Param: []
    * @return: org.springframework.amqp.core.TopicExchange
    * @Author: 林北
    * @Date: 2020-07-10
    */
    @Bean
    TopicExchange exchange(){
        return new TopicExchange(EXCHANGE,true,false);
    }

    /**
    * @Description: 绑定交换器和队列通过路由键
    * @Param: []
    * @return: org.springframework.amqp.core.Binding
    * @Author: 林北
    * @Date: 2020-07-10
    */
    @Bean
    Binding binding(){
        return BindingBuilder.bind(queue()).to(exchange()).with(ROUTEKEY);
    }

    @Bean
    public MessageConverter messageConverter(){
        return new Jackson2JsonMessageConverter();
    }

}
  • 创建方法接口,和实现类,通过SpringBoot中自带的RabbitTemplate把消息存入消息队列中
public interface EmailService {

    /**
    * @Description: 发送邮箱地址到消息队列中
    * @Param: [message]
    * @return: void
    * @Author: 林北
    * @Date: 2020-07-09
    */
    void sendEmailMessage(String message);
}


@Service
@Slf4j
public class EmailServiceImpl implements EmailService {

    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Override
    public void sendEmailMessage(String message) {
        rabbitTemplate.convertAndSend(RabbitmqConfig.EXCHANGE,RabbitmqConfig.ROUTEKEY, message);
        log.info("邮件: "+message);
    }
}
  • 编写Controller类,模拟注册接口,接收用户注册的邮箱地址
@RestController
public class EmailController {

    @Autowired
    private EmailService emailService;

    @RequestMapping("/reg")
    public String reg(@RequestParam("email") String email){
        emailService.sendEmailMessage(email);
        return "邮件已经发送";
    }
}

Email-Consumer

  • 配置RabbitMQ和邮箱
spring:
  rabbitmq:
    host: 一般为localhost,我是放在了服务器上所以是服务器地址
    username: guest
    password: guest
    port: 5672
server:
  port: 7777

邮箱配置,可以查看Hutool如何配置邮箱

  • 配置RabbitMQ
@Configuration
public class RabbitmqConfig {

    // 队列名称
    public static final String QUENE_NAME="email_queue";

    /**
    * @Description: 创建队列
    * @Param: []
    * @return: org.springframework.amqp.core.Queue
    * @Author: 林北
    * @Date: 2020-07-10
    */
    @Bean
    Queue queue(){
        return new Queue(QUENE_NAME);
    }

    @Bean
    public MessageConverter messageConverter(){
        return new Jackson2JsonMessageConverter();
    }
}
  • 创建方法接口,和实现类,监听队列,当队列有消息时消费消息
public interface EmailService {

    void printEmail(String message);
}

@Service
@Slf4j
public class EmailServiceImpl implements EmailService{


    @Override
    public void printEmail(String message) {
        int result = (int) ((Math.random()*9+1)*1000);
        log.info("发送邮箱地址: "+message);
        MailUtil.send(message, "验证码", String.valueOf(result), false);
        log.info("验证码: "+result);
    }

    @RabbitListener(queues = RabbitmqConfig.QUENE_NAME)
    private void consumerEmail(String message){
        printEmail(message);
    }
}

@RabbitListener该注解用在方法上,当指定的队列有消息时,就会执行该方法。当接收到消息后,就会随机产生四位数字,作为邮件内容发送到接收到邮箱地址。发送邮件的发送可以看Hutool

使用Postman模拟调用接口

在这里插入图片描述
参数带上指定的邮箱地址
RabbitMQ中已经有存有对应的邮箱地址
在这里插入图片描述
当消息队列中有消息时,email-consumer就会消息该消息,并发送邮件
在这里插入图片描述

  • 3
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论
### 回答1: 在 Spring Boot 中,你可以通过 RabbitMQ 的 `x-delayed-message` 插件来实现延时队列,而不需要使用额外的插件或库。下面是实现步骤: 1. 添加依赖 在 `pom.xml` 文件中添加 RabbitMQ 的依赖: ```xml <dependency> <groupId>org.springframework.amqp</groupId> <artifactId>spring-rabbit</artifactId> <version>2.3.12.RELEASE</version> </dependency> ``` 2. 配置 RabbitMQ 的 `x-delayed-message` 插件 在 RabbitMQ 中,你需要先安装 `x-delayed-message` 插件。你可以通过 `rabbitmq-plugins` 命令来安装插件: ``` rabbitmq-plugins enable rabbitmq_delayed_message_exchange ``` 或者,你可以在 `rabbitmq.conf` 文件中添加以下配置,然后重启 RabbitMQ: ``` plugins.rabbitmq_delayed_message_exchange = {git, "https://github.com/rabbitmq/rabbitmq-delayed-message-exchange", {branch, "master"}} ``` 3. 配置 RabbitMQ 的连接信息 在 `application.properties` 中添加 RabbitMQ 的连接信息: ```properties spring.rabbitmq.host=your-rabbitmq-host spring.rabbitmq.port=5672 spring.rabbitmq.username=your-rabbitmq-username spring.rabbitmq.password=your-rabbitmq-password ``` 4. 定义队列和交换器 在 Spring Boot 中,你可以使用 `@Configuration` 和 `@Bean` 注解来定义队列和交换器。下面是一个例子: ```java @Configuration public class RabbitConfig { @Bean public Queue delayedQueue() { return QueueBuilder.durable("delayed.queue") .withArgument("x-dead-letter-exchange", "normal.exchange") .withArgument("x-dead-letter-routing-key", "normal.routingkey") .build(); } @Bean public CustomExchange delayedExchange() { Map<String, Object> args = new HashMap<>(); args.put("x-delayed-type", "direct"); return new CustomExchange("delayed.exchange", "x-delayed-message", true, false, args); } @Bean public Binding binding() { return BindingBuilder.bind(delayedQueue()) .to(delayedExchange()) .with("delayed.routingkey") .noargs(); } } ``` 在上面的例子中,我们定义了一个 `delayedQueue` 队列,它的死信交换器是 `normal.exchange`,死信路由键是 `normal.routingkey`。我们还定义了一个 `delayedExchange` 交换器,它的类型是 `x-delayed-message`,并将 `x-delayed-type` 属性设置为 `direct`。最后,我们将 `delayedQueue` 队列绑定到 `delayedExchange` 交换器上,并使用路由键 `delayed.routingkey`。 5. 发送延时消息 你可以使用 `RabbitTemplate` 类来发送消息到 `delayedQueue` 队列。在发送消息时,你需要将消息的 `headers` 属性设置为 `x-delay`,并将值设置为消息的延时时间(单位为毫秒)。 ```java @Autowired private RabbitTemplate ### 回答2: 在Spring Boot实现RabbitMQ延时队列需要以下几个步骤: 1. 首先,我们需要定义一个交换机(Exchange),用于将消息发送到延时队列中。可以使用DirectExchange、TopicExchange或FanoutExchange等不同类型的交换机。交换机的类型根据具体的业务需求而定。 2. 接下来,我们需要定义两个队列,一个为延时队列,另一个为业务队列。延时队列用于接收需要延时处理的消息,业务队列用于接收延时队列中处理完成的消息。 3. 创建并配置消息发送和接收的相关组件。使用RabbitTemplate来发送消息到延时队列,创建一个消费者来接收延时队列中的消息并处理。 4. 在消息发送时,可以通过给消息设置不同的过期时间来实现延时功能。在发送消息时,将消息携带的延时时间设置为过期时间,然后发送到延时队列中。 5. 在消费者中,监听业务队列,当接收到延时队列中的消息时,进行相应的处理,例如发送邮件、生成报表等。 这样就实现RabbitMQ延时队列的功能。通过设置消息的过期时间,可以控制消息何时被消费。延时队列可以在某个特定的时间点将消息转发到业务队列,完成后续处理。Spring Boot提供了简单而强大的集成,可以轻松实现延时队列的功能。 ### 回答3: 实现RabbitMQ延时队列的核心思想是利用RabbitMQ的插件(x-delayed-message)和Spring Boot的消息中间件(RabbitTemplate)结合使用。 首先,确保在RabbitMQ服务中安装了插件。在RabbitMQ的安装目录下,执行以下命令: ``` rabbitmq-plugins enable rabbitmq_delayed_message_exchange ``` 接下来,在Spring Boot项目的pom.xml文件中添加RabbitMQ的依赖: ```xml <dependencies> <!-- RabbitMQ --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-amqp</artifactId> </dependency> </dependencies> ``` 然后,创建一个配置类,用于连接RabbitMQ服务和创建延时队列: ```java @Configuration public class RabbitMQConfig { @Autowired private Environment env; @Bean public ConnectionFactory connectionFactory() { CachingConnectionFactory connectionFactory = new CachingConnectionFactory(); connectionFactory.setAddresses(env.getProperty("spring.rabbitmq.addresses")); connectionFactory.setUsername(env.getProperty("spring.rabbitmq.username")); connectionFactory.setPassword(env.getProperty("spring.rabbitmq.password")); return connectionFactory; } @Bean public RabbitTemplate rabbitTemplate() { RabbitTemplate rabbitTemplate = new RabbitTemplate(connectionFactory()); rabbitTemplate.setMessageConverter(jsonMessageConverter()); return rabbitTemplate; } @Bean public MessageConverter jsonMessageConverter() { return new Jackson2JsonMessageConverter(); } @Bean public Exchange delayedExchange() { Map<String, Object> args = new HashMap<>(); args.put("x-delayed-type", "direct"); return new CustomExchange("delayed-exchange", "x-delayed-message", true, false, args); } @Bean public Queue delayedQueue() { return new Queue("delayed-queue", true); } @Bean public Binding delayedBinding() { return BindingBuilder.bind(delayedQueue()).to(delayedExchange()).with("delayed-routing-key").noargs(); } } ``` 在上述代码中,我们创建了一个自定义的Exchange,将其类型设置为"x-delayed-message",并创建了一个延时队列,将其绑定在这个Exchange上。这样,消息发送到这个Exchange时,会根据消息中的延时时间属性进行延时处理。 最后,我们可以通过RabbitTemplate发送延时消息: ```java @Service public class RabbitMQService { @Autowired private RabbitTemplate rabbitTemplate; public void sendDelayedMessage(String message, int delayTime) { rabbitTemplate.convertAndSend("delayed-exchange", "delayed-routing-key", message, new MessagePostProcessor() { @Override public Message postProcessMessage(Message message) throws AmqpException { message.getMessageProperties().setHeader("x-delay", delayTime); return message; } }); } } ``` 在上述代码中,我们通过rabbitTemplate将消息发送到名为"delayed-exchange"的Exchange上,并设置消息的延时时间属性"x-delay"。最后,通过"convertAndSend"方法发送消息。 以上就是使用Spring Boot实现RabbitMQ延时队列的简单示例。通过这种方式,我们可以轻松地实现消息的延时处理,使得系统更加灵活和高效。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Lpepsi

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值