SpringBoot 动态配置邮箱发件人过程解析

所属分类: 软件编程 / java 阅读数: 38
收藏 0 赞 0 分享

前言

现在的消息模块少不了邮件发送、短信发送和手机推送的功能。邮件发送的功能历史最为悠久,也算的上烂大街的功能。一般在配置文件中设置好邮箱地址、账号、密码和发件服务器地址后便不会再去改动。可是有的客户却希望人为指定发件人信息。这个需求并不过分,需要解决两个大问题:如何在容器启动成功后重新修改发送邮件的Bean。如何在服务器重启后,发件人依然是更改后的配置信息。这里记录实现的步骤。

需求分析

一)、在未配置邮箱账号时,系统拥有默认的邮箱发件人

二)、重新设置邮箱发件人后,需立即生效

三)、重启服务器后,邮箱发件人依然是更改后的邮箱账号,而非默认发件人

基础的邮箱发送

邮箱发送的功能放在现在变得非常的简单好用,一导二配三发送。😊

第一步:导入邮箱依赖包

compile('org.springframework.boot:spring-boot-starter-mail')

第二步:配置发件人邮箱信息

spring:
  mail:
   host: smtp.mxhichina.com
   username: itdragon@xx
   password: itdragon
   default-encoding: utf-8

第三步:发送邮件

@Autowired
lateinit var javaMailSender: JavaMailSender
fun pushMsgEmail(target: String, subject: String, content: String) {
  if (target.isEmpty() || !Pattern.matches(REG_EMAIL_FORMAT, target)) return
  val mailMsg = SimpleMailMessage()
  mailMsg.setFrom(mailUserName!!)
  mailMsg.setTo(target)
  mailMsg.setSubject(subject)
  mailMsg.setText(content)
  javaMailSender.send(mailMsg)
}

可配置的邮件发送

这里的可配置值的是配置邮箱的发件人。首先我们要解决第一个问题,JavaMailSender 的Bean对象是在容器启动成功后就已经注入到容器中。如何在容器启动后重新注入新的JavaMailSender 的Bean对象呢?

网上找了一些案例,他们都是通过销毁Bean然后再重新创建Bean的方式实现。我有点好奇地是,为什么不直接将新的对象直接赋值从而替换原有的Bean对象?Spring默认是单例模式,从Java内存的角度看,这样做似乎没毛病!如果有不对的地方望不吝赐教😋

@Autowired
lateinit var javaMailSender: JavaMailSender
fun configEmail(postMailConfig: PostMailConfig): JavaMailSender {
  val javaMailSender = JavaMailSenderImpl()
  javaMailSender.host = postMailConfig.mailHost
  javaMailSender.username = postMailConfig.mailUsername
  javaMailSender.password = postMailConfig.mailPassword
  val javaMailProperties = Properties()
  javaMailProperties["mail.smtp.auth"] = true
  javaMailProperties["mail.smtp.starttls.enable"] = true
  javaMailProperties["mail.smtp.timeout"] = 5000
  javaMailProperties["mail.smtp.socketFactory.class"] = "javax.net.ssl.SSLSocketFactory"
  javaMailProperties["mail.smtp.socketFactory.port"] = "465"
  javaMailProperties["mail.smtp.port"] = "465"
  javaMailSender.javaMailProperties = javaMailProperties
  this.javaMailSender = javaMailSender
  return javaMailSender
}

再来解决第二个问题,服务器重启后,默认情况下依然会重新加载application.yml中的配置信息。这会出现邮箱发件人和实际配置的发件人不匹配的情况。其实这个问题也很好解决,加一个事件监听器,在容器初始化成功后执行,根据之前保存的邮箱信息,重新配置邮箱。当然,我们需要一张表记录当前发件人信息。

// 创建事件监听器
class ApplicationStartup : ApplicationListener<ContextRefreshedEvent> {  
  override fun onApplicationEvent(contextRefreshedEvent: ContextRefreshedEvent) {
    val systemBaseConfigMapper = contextRefreshedEvent.applicationContext.getBean(SystemBaseConfigMapper::class.java)
    val postMailConfig = systemBaseConfigMapper.selectByMail()
    val mailService = contextRefreshedEvent.applicationContext.getBean(MailService::class.java)
    mailService.configEmail(postMailConfig)
  }
  
}
// 注册事件监听器
fun main(args: Array<String>) {
  
  val springApplication = SpringApplication(StartApplication::class.java)
  springApplication.addListeners(ApplicationStartup())
  springApplication.run(*args)  
}

最后发送邮件的代码如下

@Service
class MailServiceImpl : MailService {
  @Value("\${spring.mail.username}")
  var mailUserName: String? = null
  @Autowired
  lateinit var javaMailSender: JavaMailSender
  @Autowired
  lateinit var systemBaseConfigMapper: SystemBaseConfigMapper
  override fun pushMsgEmail(target: String, subject: String, content: String) {
    if (target.isEmpty() || !Pattern.matches(REG_EMAIL_FORMAT, target)) return
    val mailMsg = SimpleMailMessage()
    mailMsg.setFrom(mailUserName!!)
    mailMsg.setTo(target)
    mailMsg.setSubject(subject)
    mailMsg.setText(content)
    try {
      systemBaseConfigMapper.selectByMailName()?.let {
        mailMsg.setFrom(it.value!!)
      }
      javaMailSender.send(mailMsg)
    } catch (e: Exception) {
      e.printStackTrace()
    }
  }

  override fun configEmail(postMailConfig: PostMailConfig): JavaMailSender {
    val javaMailSender = JavaMailSenderImpl()
    javaMailSender.host = postMailConfig.mailHost
    javaMailSender.username = postMailConfig.mailUsername
    javaMailSender.password = postMailConfig.mailPassword
    val javaMailProperties = Properties()
    javaMailProperties["mail.smtp.auth"] = true
    javaMailProperties["mail.smtp.starttls.enable"] = true
    javaMailProperties["mail.smtp.timeout"] = 5000
    javaMailProperties["mail.smtp.socketFactory.class"] = "javax.net.ssl.SSLSocketFactory"
    javaMailProperties["mail.smtp.socketFactory.port"] = "465"
    javaMailProperties["mail.smtp.port"] = "465"
    javaMailSender.javaMailProperties = javaMailProperties
    this.javaMailSender = javaMailSender
    return javaMailSender
  }
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

更多精彩内容其他人还在看

Springmvc restful配置遇到的小坑

本文是小编给大家带了的Springmvc restful配置遇到的小小坑,小编给大家带来了问题原因及解决办法,非常不错,具有参考借鉴价值,感兴趣的朋友一起看下吧
收藏 0 赞 0 分享

Java中的匿名内部类小结

java内部类分为: 成员内部类、静态嵌套类、方法内部类、匿名内部类。这篇文章主要介绍了Java中的匿名内部类的相关资料,需要的朋友可以参考下
收藏 0 赞 0 分享

Java的云打印Lodop

这篇文章主要介绍了Java的云打印Lodop 的相关资料,非常不错,具有参考借鉴价值,需要的朋友可以参考下
收藏 0 赞 0 分享

Java线程池框架核心代码解析

这篇文章主要针对Java线程池框架核心代码进行详细解析,分析Java线程池框架的实现ThreadPoolExecutor,感兴趣的小伙伴们可以参考一下
收藏 0 赞 0 分享

Java 交换两个变量的数值实现方法

下面小编就为大家带来一篇Java 交换两个变量的数值实现方法。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
收藏 0 赞 0 分享

全面了解JAVA_BaseDAO数据处理类

下面小编就为大家带来一篇全面了解JAVA_BaseDAO数据处理类。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
收藏 0 赞 0 分享

java、python、JavaScript以及jquery循环语句的区别

本篇文章主要介绍java、python、JavaScript以及jquery的循环语句的区别,这里整理了它们循环语句语法跟示例,以便大家阅读,更好的区分它们的不同
收藏 0 赞 0 分享

基于JDBC封装的BaseDao(实例代码)

下面小编就为大家带来一篇基于JDBC封装的BaseDao(实例代码)。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
收藏 0 赞 0 分享

简单通用JDBC辅助类封装(实例)

下面小编就为大家带来一篇简单通用JDBC辅助类封装(实例)。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
收藏 0 赞 0 分享

浅谈java线程中生产者与消费者的问题

下面小编就为大家带来一篇浅谈java线程中生产者与消费者的问题。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
收藏 0 赞 0 分享
查看更多