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

前言

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

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

(0)

相关推荐

  • spring boot 配置动态刷新实现详解

    本文测试使用的spring cloud版本为: Dalston.SR1 很多朋友只知道spring cloud config可以刷新远程git的配置到内存中, 却不知道spring cloud config的客户端可以脱离服务端使用, 更不知道spring cloud config客户端结合actuator还可以刷新本地的配置文件到内存中. 具体做法如下: 1.pom: <?xml version="1.0" encoding="UTF-8"?> <

  • spring boot静态变量注入配置文件详解

    本文实例为大家分享了spring boot静态变量注入配置文件的具体代码,供大家参考,具体内容如下 spring 静态变量注入 spring 中不支持直接进行静态变量值的注入,我们看一下代码: @Component(value = "KafkaConfig") @ConfigurationProperties(prefix = "baseConfig") public class KafkaConfig { private static String logBrok

  • 浅谈springboot自动配置原理

    从main函数说起 一切的开始要从SpringbootApplication注解说起. @SpringBootApplication public class MyBootApplication { public static void main(String[] args) { SpringApplication.run(MyBootApplication.class); } } @SpringBootConfiguration @EnableAutoConfiguration @Compon

  • SpringBoot注入配置文件的3种方法详解

    这篇文章主要介绍了SpringBoot注入配置文件的3种方法详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 方案1:@ConfigurationProperties+@Component 定义spring的一个实体bean装载配置文件信息,其它要使用配置信息是注入该实体bean /** * 将配置文件中配置的每一个属性的值,映射到这个组件中 * @ConfigurationProperties:告诉SpringBoot将本类中的所有属性和配

  • 详解springboot读取yml配置的几种方式

    yml 文件规则 yml文件的好处,天然的树状结构,一目了然,实质上跟properties是差不多的. 不支持tab缩进 可以使用 "-小写字母" 或 "_小写字母"来 代替 "大写字母",如 userName 与 user-name ,user_name 含义是一样的 key: value 格式书写 key 后面跟着冒号,再后面跟着一个空格,然后是值 几种数据格式的表示方式 1.普通的值(数字,字符串,布尔) 2.对象.Map (属性和值) (

  • springboot配置redis过程详解

    在springboot中,默认继承好了一套完好的redis包,可以直接使用,但是如果使用中出了错不容易找到错误的原因,因此这里使用自己配置的redis: 需要使用的三个主要jar包: <dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> <version>2.9.0</version> </dependency>

  • Spring Boot中配置定时任务、线程池与多线程池执行的方法

    配置基础的定时任务 最基本的配置方法,而且这样配置定时任务是单线程串行执行的,也就是说每次只能有一个定时任务可以执行,可以试着声明两个方法,在方法内写一个死循环,会发现一直卡在一个任务上不动,另一个也没有执行. 1.启动类 添加@EnableScheduling开启对定时任务的支持 @EnableScheduling @SpringBootApplication public class TestScheduledApplication extends SpringBootServletInit

  • Springboot为什么加载不上application.yml的配置文件

    调试源代码,配置文件加载代码位置是: org.springframework.boot.context.config.ConfigFileApplicationListener public void postProcessEnvironment(ConfigurableEnvironment environment,SpringApplication application)方法 这个方法执行完,enviroment->propertySources从4个,变成6个,最终加载完成 先读取pro

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

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

  • Springboot mybais配置多数据源过程解析

    一.分包方式实现: 1.在application.properties中配置两个数据库: #druid连接池 #dataSoureOne(这里是我本地的数据源) spring.datasource.one.type=com.alibaba.druid.pool.DruidDataSource spring.datasource.one.driver-class-name=com.mysql.jdbc.Driver spring.datasource.one.jdbc-url=jdbc:mysql

  • 配置springboot项目使用外部tomcat过程解析

    这篇文章主要介绍了配置springboot项目使用外部tomcat过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 在pom文件中添加依赖 <!--使用自带的tomcat--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-tomcat</artifac

  • SpringBoot基于数据库实现定时任务过程解析

    这篇文章主要介绍了SpringBoot基于数据库实现定时任务过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 在我们平时开发的项目中,定时任务基本属于必不可少的功能,那大家都是怎么做的呢?但我知道的大多都是静态定时任务实现. 基于注解来创建定时任务非常简单,只需几行代码便可完成.实现如下: @Configuration @EnableScheduling public class SimpleScheduleTask { //10秒钟执行

  • Springboot整合MybatisPlus的实现过程解析

    这篇文章主要介绍了Springboot整合MybatisPlus的实现过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 1.pom文件 <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3

  • SpringBoot整合mybatis简单案例过程解析

    这篇文章主要介绍了SpringBoot整合mybatis简单案例过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 1.在springboot项目中的pom.xml中添加mybatis的依赖 <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifac

  • SpringBoot加载外部依赖过程解析

    这篇文章主要介绍了SpringBoot加载外部依赖过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 背景 公司一个项目的大数据平台进行改造,之前使用Structured Streaming作为实时计算框架,需要替换为替换为Kafka Streams,并使用SpringBoot包装,使其可以纳入微服务体系. 然而由于之前并没有接触过SpringFramework相关技术,并且项目工期较为紧张,因此只好花了2天时间看了看Spring和Spri

  • SpringBoot基本web开发demo过程解析

    这篇文章主要介绍了SpringBoot基本web开发demo过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 1.在创建的springboot项目中的pom.xml中导入Lombok的依赖 <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18

  • Springboot整合thymleaf模板引擎过程解析

    这篇文章主要介绍了Springboot整合thymleaf模板引擎过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 thymeleaf作为springboot官方推荐使用的模板引擎,简单易上手,功能强大,thymeleaf的功能和jsp有许多相似之处,两者都属于服务器端渲染技术,但thymeleaf比jsp的功能更强大. 1. thymeleaf入门 1.1 引入坐标 <!--springBoot整合thymeleaf--> <d

  • vue新建项目并配置标准路由过程解析

    这篇文章主要介绍了vue新建项目并配置标准路由过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 配置路由所有用到的地方总共四步或者说四处 1.index.js(src--router--index.js) import Vue from 'vue' import Router from 'vue-router' // import HelloWorld from '@/components/HelloWorld' import Home

随机推荐