基于SpringBoot:ActiveMQ 之邮箱发送

在项目中。实现邮箱发送的方式有很多种。
最经典的就是用javaMailSender的方式实现。

先在邮箱中申请了smtp,接着配置application.properties里面的参数

spring.mail.protocol=smtp
spring.mail.host=smtp.qq.com
spring.mail.username=隐藏
spring.mail.password=隐藏
spring.mail.defaultEncoding=UTF-8
spring.mail.properties.mail.smtp.auth=true
spring.mail.properties.mail.smtp.starttls.enable=true
spring.mail.properties.mail.smtp.starttls.required=true

添加maven依赖

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-mail</artifactId>
        </dependency>

实现方法


@Service
public class EmailServiceImpl implements EmailService {

//发送邮件的用户名
    @Value("${spring.mail.username}")
    private String sender;

@Override
    public void sendEmail(String to, String subject, StringBuffer content) {
        MimeMessage message = javaMailSender.createMimeMessage();
        MimeMessageHelper helper =null;
        try {
            helper = new MimeMessageHelper(message,true);
            helper.setFrom(sender);
            helper.setSubject(subject);
            helper.setTo(to);
            helper.setText(content.toString(),true);
            javaMailSender.send(message);
            logger.info("邮件已经发送");
        }catch (MessagingException e){
            logger.error("邮件发送异常",e);
        }
    }

然后嵌套在controller中。
注入改该方法。直接使用sendEmail

 	String code = users.getActiCode();
        String subject = "激活邮件";
        StringBuffer context = new StringBuffer();
        context.append("<h1>你好:"+users.getUserName()+"</h1>")
                .append("<h1>激活请点击:</h1><br/><h3><a href='"+sendUrl+"checkCode?code="+code+"'>Click Me</a></h3>");
        emailService.sendEmail(users.getUserEmail(),subject,context);

但是会遇到一种情况。就是必须等待它发送完邮件才能进行下一个动作。
容易造成假卡死的状况。如果。与此同时多个用户都在点击这个发送邮件的动作。可能服务器会崩溃。

ActiveMQ使用

消息中间件。具体使用消息队列(MQ)的优点还有概念就不解释了。网上很多。
但是我们需要的业务要求是

  • 让发送邮件这个事情丢到消息中间件中,也就是将其作为生产者。
  • 消费者收到生产者的消息后,就会开始执行发送邮件这个动作。
  • 用户就不用等待了。让消息中间件处理。我们只需要等待consumer发送邮件。

有很多种MQ,我用的是ActiveMQ

下载ActiveMQ

  • 官网下载。解压。找到bin–>win64–>activemq.bat运行
  • 访问http://localhost:8161,账号密码都默认admin

添加maven依赖

        <!-- 记得添加mail依赖 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-mail</artifactId>
        </dependency>
        <dependency>
            <groupId>org.apache.activemq</groupId>
            <artifactId>activemq-pool</artifactId>
        </dependency>
	  <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-activemq</artifactId>
        </dependency>

添加properties

我这里多创建了一个properties。为了方便区别

application.properties

spring.activemq.broker-url=tcp://localhost:61616
spring.activemq.user=admin
spring.activemq.password=admin
#下面这些不是太必要
#处理序列化对象需要用到的配置
#如果需要这里需要针对queue和topics的选择添加,我没写
spring.activemq.packages.trusted=true
spring.activemq.packages.trust-all=true
spring.activemq.pool.enabled=false
spring.activemq.pool.max-connections=50
spring.activemq.pool.idle-timeout=30000

email.properties

spring.mail.protocol=smtp
spring.mail.host=smtp.qq.com
spring.mail.username=隐藏
spring.mail.password=隐藏
spring.mail.defaultEncoding=UTF-8
spring.mail.properties.mail.smtp.auth=true
spring.mail.properties.mail.smtp.starttls.enable=true
spring.mail.properties.mail.smtp.starttls.required=true

#这里是一个业务需要用得的地址,不需要跟着我添加
com.mailUrl=http://localhost:8081/

创建生产者

记得创建相应的接口

@Slf4j
@Service
public class ActiveMQServiceImpl implements ActiveMQService {
    @Autowired
    JmsTemplate template;

    /**
     *@Auther kiwi
     *@Data 2019/9/8
    * 发送邮件
     */
    @Override
    public void sendEmail(String to, String subject, String content) throws IOException {
        template.send("registerBySystem", new MessageCreator() {
                @Override
                public Message createMessage(Session session) throws JMSException {
                    MapMessage mapMessage = session.createMapMessage();
                    mapMessage.setString("content", content);
                    mapMessage.setString("address", to);
                    mapMessage.setString("subject", subject);
                    return mapMessage;
                }
            });
        log.info("发送给消费者");

    }
}

to是发送过去的邮箱,subject是标题,content是邮件的内容
这里使用了JmsTemplate的send方法。第一个参数是生产者发布的名称。后面是传入Message的值,通过这里的Message作为中间值。

消费者

注意,消费者必须加上@Service或者@Component
消费者才能检测到

@Slf4j
@Service
public class ConsumerService {

    @Autowired
    private EmailUtil emailUtil;
    /**
     * 通过监听目标队列实现功能
     */
    @JmsListener(destination = "registerBySystem")
    public void sendMail(Message message) throws Exception {
        MapMessage mapMessage = (MapMessage) message;
        String content = mapMessage.getString("content");
        String address = mapMessage.getString("address");
        String subject = mapMessage.getString("subject");
        emailUtil.sendEmail(address,subject,content);
    }

}

通过注解@JmsListener里面对生产者名称“registerBySystem”的监听。
然后通过message的值,传入sendEmail。
也就是这里,我们开始出现发送邮件的动作。

发送邮件


@Slf4j
@Component
@PropertySource(value = {"classpath:email.properties"})
public class EmailUtil {

    @Value("${spring.mail.username}")
    private String sender;

    @Value("${spring.mail.host}")
    private String host;

    @Value("${spring.mail.password}")
    private String pwd;


    public void sendEmail(String to, String subject, String content) throws Exception {

  
        Properties props = new Properties();

        props.setProperty("mail.transport.protocol", "smtp");
        props.setProperty("mail.smtp.host", host);
        props.setProperty("mail.smtp.auth", "true");
        Session session = Session.getDefaultInstance(props);
        // 开启debug模式,可以看到更多详细的输入日志
        MimeMessage message = this.addEmail(session,to,subject, content);

        //获取传输通道
        Transport transport = session.getTransport();
        transport.connect(host, sender, pwd);
        //连接,并发送邮件
        transport.sendMessage(message, message.getAllRecipients());
        transport.close();


    }
        /**
         * 创建邮件
         */
        public MimeMessage addEmail(Session session,String to, String subject, String content) throws Exception {
            // 根据会话创建邮件
            MimeMessage msg = new MimeMessage(session);

            // 设置发送邮件方
            msg.setFrom(new InternetAddress(sender));
            // 设置邮件接收方
            msg.setRecipient(Message.RecipientType.TO, new InternetAddress(to));
            // 设置邮件标题
            msg.setSubject(subject, "utf-8");
            msg.setContent(content,"text/html;charset=utf-8");
            // 设置显示的发件时间
            msg.setSentDate(new Date());
            // 保存设置
            msg.saveChanges();
            return msg;
        }

}


具体实现注册很详细了。
注意。在刚刚的ConsumerService中。一定要Autowired该方法。
才能在这里通过@Value获取email.properties的值

邮件模板

也就是content参数

public class EmailTemplate {

    /**
     *@Auther kiwi
     *@Data 2019/9/8
     @param  * @param
     * 注册模板
     *@reutn java.lang.String
    */
    public static String registerTemplate(String sendUrl,String code) throws IOException {
        String fileName = "pod-scale-alarm.html";
        InputStream inputStream = ClassLoader.getSystemResourceAsStream(fileName);
        BufferedReader fileReader = new BufferedReader(new InputStreamReader(inputStream));
        StringBuffer buffer = new StringBuffer();
        String line = "";
        try {
            while ((line = fileReader.readLine()) != null) {
                buffer.append(line);
            }
        } catch (Exception e) {
            log.error("读取文件失败,fileName:{}", fileName, e);
        } finally {
            inputStream.close();
            fileReader.close();
        }

        String contentText = "以下是需要点击的链接, 进入便可完成注册.<a href='"+sendUrl+"checkCode?code="+code+"'>Click Me</a>";
        //邮件表格header
        String header = "<td>商品管理(itemManagement)</td><td>订单管理(orderManagement)</td><td>用户管理(userManagement)</td><td>系统管理(systemManagement)</td><td>调度任务(Scheduled Tasks)</td>";
        StringBuilder linesBuffer = new StringBuilder();
        linesBuffer.append("<tr><td>" + "four menu" + "</td><td>" + "four menu" + "</td><td>" + "three menu" + "</td>" +
                "<td>" + "two menu" + "</td><td>" + "two menu" + "</td></tr>");

        String emailHeadColor = "#8A2BE2";
        String date = DateFormatUtils.format(new Date(), "yyyy/MM/dd HH:mm:ss");
        //填充html模板中的五个参数
        String htmlText = MessageFormat.format(buffer.toString(), emailHeadColor, contentText, date, header, linesBuffer.toString());

        //改变表格样式
        htmlText = htmlText.replaceAll("<td>", "<td style=\"padding:6px 10px; line-height: 150%;\">");
        htmlText = htmlText.replaceAll("<tr>", "<tr style=\"border-bottom: 1px solid #eee; color:#666;\">");
        return htmlText;
    }
}

pod-scale-alarm.html

<body style="color: #666; font-size: 14px; font-family: 'Open Sans',Helvetica,Arial,sans-serif;">
<div class="box-content" style="width: 80%; margin: 20px auto; max-width: 800px; min-width: 600px;">
    <div class="header-tip" style="font-size: 12px;
                                   color: #aaa;
                                   text-align: right;
                                   padding-right: 25px;
                                   padding-bottom: 10px;">
    <a href="http://www.kiwi1.cn" >Welcome to my Blog</a>
    </div>
    <div class="info-top" style="padding: 15px 25px;
                                 border-top-left-radius: 10px;
                                 border-top-right-radius: 10px;
                                 background: {0};
                                 color: #fff;
                                 overflow: hidden;
                                 line-height: 32px;">
        <img alt="Hello"  src="https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1567918888673&di=882438e088da517bca429a3eb88a9034&imgtype=0&src=http%3A%2F%2Fgss0.baidu.com%2F94o3dSag_xI4khGko9WTAnF6hhy%2Fzhidao%2Fpic%2Fitem%2F6a600c338744ebf8225842acd9f9d72a6059a773.jpg"
             style="float: left; margin: 0 10px 0 0; width: 32px;" /><div style="color:#010e07"><strong>欢迎注册网站 b2b_mall</strong></div>
    </div>
    <div class="info-wrap" style="border-bottom-left-radius: 10px;
                                  border-bottom-right-radius: 10px;
                                  border:1px solid #ddd;
                                  overflow: hidden;
                                  padding: 15px 15px 20px;">
        <div class="tips" style="padding:15px;">
            <p style=" list-style: 160%; margin: 10px 0;">Hi,</p>
            <p style=" list-style: 160%; margin: 10px 0;">{1}</p>
        </div>
        <div class="time" style="text-align: right; color: #999; padding: 0 15px 15px;">{2}</div>
        <br>
        <table class="list" style="width: 100%; border-collapse: collapse; border-top:1px solid #eee; font-size:12px;">
            <thead>
            <tr style=" background: #fafafa; color: #333; border-bottom: 1px solid #eee;">
                {3}
            </tr>
            </thead>
            <tbody>
            {4}
            </tbody>
        </table>
    </div>
</div>
</body>

使用activeMQService

//注入,记得加上@PropertySource("email.properties")
    @Resource
    private ActiveMQService activeMQService;
    @Value("${com.mailUrl}")
    private String sendUrl;

//实现

        activeMQService.sendEmail("????@qq.com","欢迎注册", EmailTemplate.registerTemplate(sendUrl,"参数地址")));

可根据自己的代码修改

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值