3.RabbitMQ结合发送邮件的场景

RabbitMQ结合发送邮件的场景

主要内容

  1. 了解如何实现发送邮件
  2. 通过RabbitMQ实现异步发送邮件(避免主要业务进行阻塞)

正文

maven依赖

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

    <slf4j.version>1.7.13</slf4j.version>
    <log4j.version>1.2.17</log4j.version>
    <mybatis-spring-boot.version>1.1.1</mybatis-spring-boot.version>
    <mybatis-pagehelper.version>4.1.2</mybatis-pagehelper.version>
    <druid.version>1.0.16</druid.version>
    <mysql.version>5.1.37</mysql.version>
    <okhttp.version>3.1.2</okhttp.version>
    <retrofit.version>2.1.0</retrofit.version>
    <guava.version>19.0</guava.version>
    <java-mail.version>1.6.0</java-mail.version>
</properties>

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <!--log start-->
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-api</artifactId>
        <version>${slf4j.version}</version>
    </dependency>
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-log4j12</artifactId>
        <version>${slf4j.version}</version>
    </dependency>
    <dependency>
        <groupId>log4j</groupId>
        <artifactId>log4j</artifactId>
        <version>${log4j.version}</version>
    </dependency>
    <!--log end-->
    <!--spring-mybatis-->
    <dependency>
        <groupId>org.mybatis.spring.boot</groupId>
        <artifactId>mybatis-spring-boot-starter</artifactId>
        <version>${mybatis-spring-boot.version}</version>
    </dependency>
    <!--for page-->
    <dependency>
        <groupId>com.github.pagehelper</groupId>
        <artifactId>pagehelper</artifactId>
        <version>${mybatis-pagehelper.version}</version>
    </dependency>
    <!--druid-->
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>druid</artifactId>
        <version>${druid.version}</version>
    </dependency>
    <!--mysql-->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>${mysql.version}</version>
    </dependency>
    <!--rabbitmq-->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-amqp</artifactId>
        <version>${parent.version}</version>
    </dependency>
    <!-- okhttp -->
    <dependency>
        <groupId>com.squareup.okhttp3</groupId>
        <artifactId>okhttp</artifactId>
        <version>${okhttp.version}</version>
    </dependency>
    <dependency>
        <groupId>com.squareup.retrofit2</groupId>
        <artifactId>retrofit</artifactId>
        <version>${retrofit.version}</version>
    </dependency>
    <dependency>
        <groupId>com.squareup.retrofit2</groupId>
        <artifactId>converter-jackson</artifactId>
        <version>${retrofit.version}</version>
    </dependency>
    <!--guava-->
    <dependency>
        <groupId>com.google.guava</groupId>
        <artifactId>guava</artifactId>
        <version>${guava.version}</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-test</artifactId>
        <version>2.1.5.RELEASE</version>
        <scope>test</scope>
    </dependency>
    <!--javamail-->
        <!--<dependency>
            <groupId>javax.mail</groupId>
            <artifactId>javax.mail-api</artifactId>
            <version>${java-mail.version}</version>
        </dependency>-->
        <!-- 这里使用的是com.sun.mail邮件api-->
        <dependency>
            <groupId>com.sun.mail</groupId>
            <artifactId>javax.mail</artifactId>
            <version>${java-mail.version}</version>
        </dependency>
</dependencies>

Spring配置文件application.properties

server.port=9092
server.context-path=/study_mq
#logging
logging.file.path=D:\\logs\\SpringBoot-RabbitMQ
logging.file.name=springboot-rabbitmq-01

spring.mvc.view.prefix=/WEB-INF/views/
spring.mvc.view.suffix=.jsp
multipart.max-request-size=20Mb
multipart.max-file-size=10Mb

logging.level.org.springframework = INFO
logging.level.com.fasterxml.jackson = INFO
logging.level.com.debug.steadyjack = DEBUG

spring.jackson.date-format=yyyy-MM-dd HH:mm:ss
spring.jackson.time-zone=GMT+8
spring.datasource.initialize=false
spring.jmx.enabled=false

#数据库
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/study_rabbitmq?characterEncoding=utf8
spring.datasource.username=root
spring.datasource.password=123456

#mybatis
mybatis.config-location=classpath:mybatis-config.xml
mybatis.checkConfigLocation = true
mybatis.mapper-locations=classpath:mappers/*.xml

#rabbitmq
spring.rabbitmq.host=39.105.91.158
spring.rabbitmq.port=5672
spring.rabbitmq.username=jack
spring.rabbitmq.password=123456
spring.rabbitmq.virtual-host=/test

# 配置并发是多消费者
# 这个是什么意思目前也没了解清楚?
spring.rabbitmq.listener.concurrency=10
# 最多有多少个消费者
spring.rabbitmq.listener.max-concurrency=20
# 每个消费者预处理多少个数据
spring.rabbitmq.listener.prefetch=50

# 自定义属性变量
mq.env=local
basic.info.mq.exchange.name=${mq.env}:basic:info:mq:exchange
basic.info.mq.routing.key.name=${mq.env}:basic:info:mq:routing:key
basic.info.mq.queue.name=${mq.env}:basic:info:mq:queue

# 发送邮件的队列和交换机
mail.queue.name=${mq.env}.mail.queue
mail.exchange.name=${mq.env}.mail.exchange
mail.routing.key.name=${mq.env}.mail.routing.key

# 邮件配置
spring.boot.mail.properties.host=smtp.qq.com
spring.boot.mail.properties.port=465
spring.boot.mail.properties.userName=120845345@qq.com
# 这个是授权码,生成后放到这里(注意:我这里为了信息的安全 放个假的在这里,在使用的时候需要自己临时去获取哦)
spring.boot.mail.properties.password=123456
spring.boot.mail.properties.protocol=smtp
spring.boot.mail.properties.needAuth=true
spring.boot.mail.properties.sslClass=javax.net.ssl.SSLSocketFactory
# 用哪个邮箱号发送
mail.from=120845345@qq.com
# 发送给哪个邮箱号(这里可以写多个人邮箱 以逗号分隔)
mail.to=30477127@qq.com
# 抄送给谁
mail.by=linsenzhong@126.com
# 发送的邮箱主题
mail.subject=这是SpringBoot整合Rabbitmq的邮件
# 发送的内容
mail.content=您好,这是RabbitMQ实战系列第二阶段的内容-用于注册时异步发送邮件进行邮箱验证!

配置类-对RabbitMQ进行设置以及创建和绑定Queue、Exchange

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.core.AcknowledgeMode;
import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.DirectExchange;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.rabbit.config.SimpleRabbitListenerContainerFactory;
import org.springframework.amqp.rabbit.connection.CachingConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.rabbit.support.CorrelationData;
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.amqp.SimpleRabbitListenerContainerFactoryConfigurer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;


/**
 * Created by steadyjack on 2018/8/20.
 */
@Configuration
public class RabbitmqConfig {
    private static final Logger log= LoggerFactory.getLogger(RabbitmqConfig.class);
    @Autowired
    private Environment env;
    @Autowired
    private CachingConnectionFactory connectionFactory;
    @Autowired
    private SimpleRabbitListenerContainerFactoryConfigurer factoryConfigurer;
    @Autowired
    private RabbitTemplate rabbitTemplate;

    /**
     * 单一消费者
     * @return
     */
    @Bean(name = "singleListenerContainer")
    public SimpleRabbitListenerContainerFactory listenerContainer(){
        SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();
        factory.setConnectionFactory(connectionFactory);
        factory.setMessageConverter(new Jackson2JsonMessageConverter());
        factory.setConcurrentConsumers(1);
        factory.setMaxConcurrentConsumers(1);
        factory.setPrefetchCount(1);
        factory.setTxSize(1);
        return factory;
    }

    /**
     * 多个消费者
     * @return
     */
    @Bean(name = "multiListenerContainer")
    public SimpleRabbitListenerContainerFactory multiListenerContainer(){
        SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();
        factoryConfigurer.configure(factory,connectionFactory);
        factory.setMessageConverter(new Jackson2JsonMessageConverter());
        factory.setAcknowledgeMode(AcknowledgeMode.NONE);
        factory.setConcurrentConsumers(env.getProperty("spring.rabbitmq.listener.concurrency",int.class));
        factory.setMaxConcurrentConsumers(env.getProperty("spring.rabbitmq.listener.max-concurrency",int.class));
        factory.setPrefetchCount(env.getProperty("spring.rabbitmq.listener.prefetch",int.class));
        return factory;
    }

    @Bean
    public RabbitTemplate rabbitTemplate(){
        connectionFactory.setPublisherConfirms(true);
        connectionFactory.setPublisherReturns(true);
        RabbitTemplate rabbitTemplate = new RabbitTemplate(connectionFactory);
        rabbitTemplate.setMandatory(true);
        // 设置消息发送到rabbitMQ,rabbitMQ接收到这个消息后的回调
        rabbitTemplate.setConfirmCallback(new RabbitTemplate.ConfirmCallback() {
            @Override
            public void confirm(CorrelationData correlationData, boolean ack, String cause) {
                log.info("消息发送成功:correlationData({}),ack({}),cause({})",correlationData,ack,cause);
            }
        });
        // 设置消息发送到rabbitMQ,rabbitMQ找不到对应的队列发送这个消息时 将消息返回给生产者的回调
        rabbitTemplate.setReturnCallback(new RabbitTemplate.ReturnCallback() {
            @Override
            public void returnedMessage(Message message, int replyCode, String replyText, String exchange, String routingKey) {
                log.info("消息丢失:exchange({}),route({}),replyCode({}),replyText({}),message:{}",exchange,routingKey,replyCode,replyText,message);
            }
        });
        return rabbitTemplate;
    }
    
    //TODO:发送邮件消息模型
    @Bean
    public Queue mailQueue(){
        return new Queue(env.getProperty("mail.queue.name"),true);
    }
    @Bean
    public DirectExchange mailExchange(){
        return new DirectExchange(env.getProperty("mail.exchange.name"),true,false);
    }
    @Bean
    public Binding mailBinding(){
        return BindingBuilder.bind(mailQueue()).to(mailExchange()).with(env.getProperty("mail.routing.key.name"));
    }
}    

通过@ConfigurationProperties读取邮箱的配置并封装到MailProperties属性中

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;

/**
 * Created by Administrator on 2018/9/1.
 */
@Configuration
@ConfigurationProperties(prefix = "spring.boot.mail.properties")
public class MailProperties {

    private String host;

    private Integer port;

    private String userName;

    private String password;

    private String protocol;

    private String needAuth;

    private String sslClass;

    public String getHost() {
        return host;
    }

    public void setHost(String host) {
        this.host = host;
    }

    public Integer getPort() {
        return port;
    }

    public void setPort(Integer port) {
        this.port = port;
    }

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getProtocol() {
        return protocol;
    }

    public void setProtocol(String protocol) {
        this.protocol = protocol;
    }

    public String getNeedAuth() {
        return needAuth;
    }

    public void setNeedAuth(String needAuth) {
        this.needAuth = needAuth;
    }

    public String getSslClass() {
        return sslClass;
    }

    public void setSslClass(String sslClass) {
        this.sslClass = sslClass;
    }
}

发送邮件的主要代码

import com.jack.config.MailProperties;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Service;

import javax.mail.*;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import java.util.Properties;

/**
 * Created by Administrator on 2018/9/1.
 */
@Service
public class MailService {

    @Autowired
    private MailProperties mailProperties;

    @Autowired
    private Environment env;

    public void sendEmail() throws Exception{
        Properties properties = new Properties();
        properties.setProperty("mail.host", mailProperties.getHost());
        properties.setProperty("mail.transport.protocol", mailProperties.getProtocol());
        properties.setProperty("mail.smtp.auth", mailProperties.getNeedAuth());
        properties.setProperty("mail.smtp.socketFactory.class", mailProperties.getSslClass());
        properties.setProperty("mail.smtp.port", mailProperties.getPort()+"");

        /*Session session = Session.getDefaultInstance(properties);
        session.setDebug(true);*/ //第一种写法

        Authenticator auth=new Authenticator() {
            @Override
            protected PasswordAuthentication getPasswordAuthentication() {
                return new PasswordAuthentication(mailProperties.getUserName(),mailProperties.getPassword());
            }
        };
        Session session = Session.getInstance(properties,auth); //第二种写法

        MimeMessage mimeMessage = new MimeMessage(session);
        mimeMessage.setFrom(env.getProperty("mail.from"));
        mimeMessage.setSubject(env.getProperty("mail.subject"));
        mimeMessage.setContent(env.getProperty("mail.content"), "text/html;charset=utf-8");

        //TODO:批量发送多个收件人
        String arr[]=env.getProperty("mail.to").split(",");
        Address[] addresses=new Address[arr.length];
        for(int i=0;i<arr.length;i++){
            addresses[i]=new InternetAddress(arr[i]);
        }
        mimeMessage.addRecipients(Message.RecipientType.TO, addresses);

        //TODO:只发送一个收件人
        //mimeMessage.addRecipients(Message.RecipientType.TO, "1974544863@qq.com");
        //mimeMessage.addRecipients(Message.RecipientType.CC, "linsenzhong@126.com");

        Transport transport = session.getTransport();
        transport.connect(mailProperties.getHost(), mailProperties.getUserName(), mailProperties.getPassword());
        transport.sendMessage(mimeMessage, mimeMessage.getAllRecipients());
        transport.close();
    }
}

发送消息

import com.jack.response.BaseResponse;
import com.jack.response.StatusCode;
import com.jack.service.MailService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.core.MessageBuilder;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;


/**
 * Created by Administrator on 2018/9/1.
 */
@RestController
public class MailController {

    private static final Logger log= LoggerFactory.getLogger(MailController.class);
    private static final String Prefix="mail";

    @Autowired
    private MailService mailService;
    @Autowired
    private RabbitTemplate rabbitTemplate;
    @Autowired
    private Environment env;

    @RequestMapping(value = Prefix+"/send",method = RequestMethod.GET)
    public BaseResponse sendMail(){
        BaseResponse response=new BaseResponse(StatusCode.Success);
        try {
            //mailService.sendEmail();
            rabbitTemplate.setExchange(env.getProperty("mail.exchange.name"));
            rabbitTemplate.setRoutingKey(env.getProperty("mail.routing.key.name"));
            rabbitTemplate.convertAndSend(MessageBuilder.withBody("mail发送".getBytes("UTF-8")).build());
        }catch (Exception e){
            e.printStackTrace();
        }
        log.info("邮件发送完毕----");
        return response;
    }
}

监听和消费并发送邮件

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.messaging.handler.annotation.Payload;
import org.springframework.stereotype.Service;

/**
 * @author cwl
 * @description: TODO
 * @date 2020/8/26 20:59
 */
@Service
public class CommonMqService {
    private static final Logger log = LoggerFactory.getLogger(CommonMqService.class);

    @Autowired
    private RabbitTemplate rabbitTemplate;
    @Autowired
    private Environment environment;
    @Autowired
    private MailService mailService;
    
    /**
     * 监听消费邮件发送
     * @param message
     */
    @RabbitListener(queues = "${mail.queue.name}",containerFactory = "singleListenerContainer")
    public void consumeMailQueue(@Payload byte[] message){
        try {
            log.info("监听消费邮件发送 监听到消息: {} ",new String(message,"UTF-8"));
            //TODO:发送邮件
            mailService.sendEmail();
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值