1. 导读
    1. 集成spring-kafka,生产者生产邮件message,消费者负责发送
    2. 引入线程池,多线程发送消息
    3. 多邮件服务器配置
    4. 定时任务生产消息;计划邮件发送
  2. 实现过程
    1. 导入依赖
   <properties>
        <java.version>1.8</java.version>
        <mysql.version>5.1.38</mysql.version>
        <mapper.version>2.1.5</mapper.version>
        <mybatis.version>1.3.2</mybatis.version>
        <gson.version>2.8.2</gson.version>
        <lang3.version>3.4</lang3.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <!-- Spring Test -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>${mybatis.version}</version>
        </dependency>
        <!--数据库驱动-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>${mysql.version}</version>
        </dependency>
        <!-- 通用Mapper启动器 -->
        <dependency>
            <groupId>tk.mybatis</groupId>
            <artifactId>mapper-spring-boot-starter</artifactId>
            <version>${mapper.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.kafka</groupId>
            <artifactId>spring-kafka</artifactId>
        </dependency>
        <!-- 自定义配置文件需要 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-configuration-processor</artifactId>
            <optional>true</optional>
        </dependency>
        <!-- 使用SLF4J + Logback 作为日志框架 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-logging</artifactId>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-mail-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-mail</artifactId>
        </dependency>
        <dependency>
            <groupId>com.google.code.gson</groupId>
            <artifactId>gson</artifactId>
            <version>${gson.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
            <version>${lang3.version}</version>
        </dependency>
    </dependencies>

2.application.yml配置kafka、邮箱、数据库参数

本文采用的yml配置方式,若使用的properties的可使用https://www.toyaml.com/index.html这个在线工具转换;

邮箱配置,若使用的163、或者qq等,自己百度怎么申请授权码(一大堆教程);

数据库采用的Hikari连接池,号称java平台最快的;

# 配置Kafka集群IP地址,多个IP以逗号隔开:spring:  kafka:    bootstrap-servers: 你的kafkaIP:端口号    producer:      retries: 2 #发送失败后的重复发送次数      key-serializer: org.apache.kafka.common.serialization.StringSerializer #key序列化方式      value-serializer: org.apache.kafka.common.serialization.StringSerializer #value序列化方式      compression-type: gzip #压缩格式      batch-size: 16384 #批量发送的消息数量      buffer-memory: 33554432 #32M的批处理缓冲区    consumer:      auto-offset-reset: earliest #最早未被消费的offset      enable-auto-commit: false #是否开启自动提交      #auto-commit-interval: 1000 #自动提交的时间间隔      key-deserializer: org.apache.kafka.common.serialization.StringDeserializer #key解码方式      value-deserializer: org.apache.kafka.common.serialization.StringDeserializer #value解码方式      group-id: kafka.consumer.group.id.1      max-poll-records: 50      properties:        session-timeout-ms: 20000 #连接超时时间        max-poll-interval-ms: 15000 #手动提交设置与poll的心跳数,如果消息队列中没有消息,等待毫秒后,调用poll()方法。如果队列中有消息,立即消费消息,每次消费的消息的多少可以通过max.poll.records配置。        max-partition-fetch-bytes: 15728640 #设置拉取数据的大小 15M    client-id: kafkacli    listener:      ack-mode: manual_immediate

  datasource:    type: com.zaxxer.hikari.HikariDataSource    driver-class-name: com.mysql.jdbc.Driver    url:  * #自己的    username: * #账号    password: * #密码    hikari:      minimum-idle: 5      # 空闲连接存活最大时间,默认600000(10分钟)      idle-timeout: 180000      # 连接池最大连接数,默认是10      maximum-pool-size: 10      # 此属性控制从池返回的连接的默认自动提交行为,默认值:true      auto-commit: true      # 连接池名称      pool-name: MyHikariCP      # 此属性控制池中连接的最长生命周期,值0表示无限生命周期,默认1800000即30分钟      max-lifetime: 1800000      # 数据库连接超时时间,默认30秒,即30000      connection-timeout: 30000      connection-test-query: SELECT 1

  # 邮箱服务器配置,以163邮箱为例  mail:    host: smtp.163.com #邮箱服务器地址    port: 25 #端口    username: *  #用户名    password: * #授权密码    default-encoding: UTF-8    properties:      from: *  #用户名      mail:        smtp:          connectiontimeout: 5000          timeout: 3000          writetimeout: 5000

  # 邮件模板  thymeleaf:    cache: false    prefix: classpath:/views/  # 邮件附件  servlet:    multipart:      max-file-size: 10MB #限制单个文件大小      max-request-size: 50MB #限制请求总量

logging:  level:    com.example: debug  pattern:#    console: %d{yyyy/MM/dd-HH:mm:ss} [%thread] %-5level %logger- %msg%n#    file: %d{yyyy/MM/dd-HH:mm} [%thread] %-5level %logger- %msg%n  path: C:\log

# 邮件失败重试次数com:  example:    mail:      sendNumber: 3 #邮件发送失败重试次数      threadKillTime: 60 #线程超时杀死

mybatis:  type-aliases-package: com.example.mail.entity  configuration:    map-underscore-to-camel-case: true  mapper-locations: mappers/*Mapper.xml

# 异步线程配置,配置核心线程数async:  executor:    thread:      core_pool_size: 15 #核心线程数量,线程池创建时候初始化的线程数      max_pool_size: 15 #最大线程数,只有在缓冲队列满了之后才会申请超过核心线程数的线程      queue_capacity: 99999 #缓冲队列,用来缓冲执行任务的队列      keep_alive_seconds: 60 #当超过了核心线程出之外的线程在空闲时间到达之后会被销毁      await_termination_seconds: 30 #设置线程池中任务的等待时间,如果超过这个时候还没有销毁就强制销毁,以确保应用最后能够被关闭,而不是阻塞住。      name:        prefix: async-service-        prefixson: async-service-son

3.邮件消息格式

{
  "mailUid": "邮件唯一标识",
  "fromName": "发件人别名",
  "fromMail": "发件人地址",
  "toMail": "收件人地址(多个邮箱则用逗号","隔开)",
  "ccMail": "抄送人地址(多个邮箱则用逗号","隔开)",
  "bccMail": "密送人地址(多个邮箱则用逗号","隔开)",
  "planSendTime": "计划邮件时间",
  "mailSubject": "邮件主题",
  "mailContent": "邮件正文",
  "sendNum": 发送次数,
  "serverFlag": "邮件服务器标识(多邮件服务器用)"
}

4.kafka生产者、消费者、mail发送类等主要方法代码

//生产者
public void sendToKafkaStandardMessageAsync(MailDTO mailDTO) {

    producer = new KafkaProducer<String, Object>(kafkaConfig.producerConfigs());

    producer.send(new ProducerRecord<String, Object>(topicName, gson.toJson(mailDTO)), new Callback() {        @Override        public void onCompletion(RecordMetadata metadata, Exception exception) {            if (metadata != null) {                log.info("生产消息成功{},发送次数{},checksum:{},offset:{},partition:{},topic:{}", mailDTO.getMailUid(),mailDTO.getSendNum(),metadata.checksum(), metadata.offset(), metadata.partition(), metadata.topic());            }            if (exception != null) {                log.info("生产消息失败{}", exception.getMessage());            }        }    });    producer.close();}
//消费者
/** * 监听一个Kafka 主题 **/@KafkaListener(topics = MQConstants.Topic.ITEM_EXCHANGE_NAME)public void receiveMessageFromKafka(ConsumerRecord<?, ?> record, Acknowledgment ack) {    log.info("监听消息,MailUid:{}", gson.fromJson(String.valueOf(record.value()), MailDTO.class).getMailUid());

    Optional<?> kafkaMessage = Optional.ofNullable(record.value());    if (kafkaMessage.isPresent()) {        sendMessageService.sendMessages(gson.fromJson(String.valueOf(record.value()), MailDTO.class));    }    ack.acknowledge();//手动提交偏移量}
//构建复杂邮件信息类
    public void sendMimeMail(MailVo mailVo) {
        try {
            MimeMessageHelper messageHelper = new MimeMessageHelper(mailSender.createMimeMessage(), true);//true表示支持复杂类型
            mailVo.setFrom("这里读取配置文件中配的from地址");//邮件发信人从配置项读取
            messageHelper.setFrom(mailVo.getFrom());//邮件发信人
            messageHelper.setSentDate(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse("2019-07-18 12:45:48"));
            messageHelper.setTo(mailVo.getTo().split(","));//邮件收信人
            messageHelper.setSubject(mailVo.getSubject());//邮件主题
            messageHelper.setText(mailVo.getText());//邮件内容
            if (!StringUtils.isEmpty(mailVo.getCc())) {//抄送
                messageHelper.setCc(mailVo.getCc().split(","));
            }
            if (!StringUtils.isEmpty(mailVo.getBcc())) {//密送
                messageHelper.setCc(mailVo.getBcc().split(","));
            }
            if (mailVo.getMultipartFiles() != null) {//添加邮件附件
                for (MultipartFile multipartFile : mailVo.getMultipartFiles()) {
                    messageHelper.addAttachment(multipartFile.getOriginalFilename(), multipartFile);
                }
            }
            if (StringUtils.isEmpty((CharSequence) mailVo.getSentDate())) {//发送时间
                mailVo.setSentDate(new Date());
                messageHelper.setSentDate(mailVo.getSentDate());
            }
            mailSender.send(messageHelper.getMimeMessage());//正式发送邮件
            mailVo.setStatus("ok");
            log.info("发送邮件成功:{}->{}", mailVo.getFrom(), mailVo.getTo());
        } catch (Exception e) {
            throw new RuntimeException(e);//发送失败
        }
    }

5.思路解析,画图吧,口述太费劲

完整代码: https://github.com/wwt729/mail.git

springboot+kafka+邮件发送(最佳实践)的更多相关文章

  1. springboot添加邮件发送及压缩功能

    springboot添加邮件发送及文件压缩功能 转载请注明出处:https://www.cnblogs.com/funnyzpc/p/9190233.html 先来一段诗 ``` 就这样吧 忍受折磨 ...

  2. SpringBoot集成邮件发送

    一:简述 在日常中的工作中难免会遇到程序集成邮件发送功能.接收功能:此篇文章我将使用SpringBoot集成邮件发送功能和接收功能:若对邮件一些基本协议和发送流程不懂的请务必参考我之前写的博客或者浏览 ...

  3. 补习系列(12)-springboot 与邮件发送【华为云技术分享】

    目录 一.邮件协议 关于数据传输 二.SpringBoot 与邮件 A. 添加依赖 B. 配置文件 C. 发送文本邮件 D.发送附件 E. 发送Html邮件 三.CID与图片 参考文档 一.邮件协议 ...

  4. 补习系列(12)-springboot 与邮件发送

    目录 一.邮件协议 关于数据传输 二.SpringBoot 与邮件 A. 添加依赖 B. 配置文件 C. 发送文本邮件 D.发送附件 E. 发送Html邮件 三.CID与图片 参考文档 一.邮件协议 ...

  5. 30分钟带你了解Springboot与Mybatis整合最佳实践

    前言:Springboot怎么使用想必也无需我多言,Mybitas作为实用性极强的ORM框架也深受广大开发人员喜爱,有关如何整合它们的文章在网络上随处可见.但是今天我会从实战的角度出发,谈谈我对二者结 ...

  6. springboot实现邮件发送

    1.创建springboot项目. 2.创建好的项目如图: 在static目录下新建index.html. 3.点击启动项目 在浏览器的地址栏中访问:http://localhost:8080/ 访问 ...

  7. SpringBoot整合邮件发送

    本节介绍SpringBoot项目如何快速配置和发送邮件,包括简单的邮件配置.发送简单邮件.发送HTML邮件.发送携带附件的邮件等. 示例源码在:https://github.com/laolunsi/ ...

  8. springboot 简单邮件发送

    写作原因: 项目接近尾声,需求一变再变,其实技术点从未改变,只是业务逻辑的变更,发送邮件提醒的功能,两个月变更七次.我想把技术点记录下来,这里无关乎业务,只有发送邮件的功能. 邮件发送准备说明: 由于 ...

  9. 基于springboot的web项目最佳实践

    springboot 可以说是现在做javaweb开发最火的技术,我在基于springboot搭建项目的过程中,踩过不少坑,发现整合框架时并非仅仅引入starter 那么简单. 要做到简单,易用,扩展 ...

随机推荐

  1. Python自学day-2

    一.模块     模块分两种:标准库和第三方库,标准库是不需要安装就可以使用的库.     import [模块名]:导入一个库,优先是在项目路径中寻找.自定义模块名不要和标准库模块名相同.   sy ...

  2. Azkaban学习之路(二)—— Azkaban 3.x 编译及部署

    一.Azkaban 源码编译 1.1 下载并解压 Azkaban 在3.0版本之后就不提供对应的安装包,需要自己下载源码进行编译. 下载所需版本的源码,Azkaban的源码托管在GitHub上,地址为 ...

  3. 【Netty整理01-快速入门】Netty简单使用Demo(已验证)

    多处摘抄或手打,为了十积分厚着脸皮标为原创,惭愧惭愧~本篇文章用于快速入门搭建一个简单的netty 应用,如想稍微深入系统的了解,请参照本人下一篇博客,链接: 参考地址: 官方文档:http://ne ...

  4. python的基本语法

    编码 python3.0以上的版本,默认的源文件都是以UTF-8编码,所有的字符串都是unicode字符串,当然也可以为源文件指定不同的编码方式; 编码实例: #随机取一个变量 str = " ...

  5. django基础知识之后台管理Admin站点:

    Admin站点 通过使用startproject创建的项目模版中,默认Admin被启用 1.创建管理员的用户名和密码 python manage.py createsuperuser 然后按提示填写用 ...

  6. 深入学习Spring框架(三)- AOP面向切面

    1.什么是AOP? AOP为 Aspect Oriented Programming 的缩写,即面向切面编程, 通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术..AOP是OOP的延续, ...

  7. SQL Server 触发器和事务

    一.触发器 1. 定义 --基本语法 create trigger Trigger_Name on TableName for type --type:insert,update,delete as ...

  8. Leetcode多线程题库练习(新功能尝鲜)& 个人感悟

    大家好, 我是方子龙.很久没有自己写文章了. 一面是因为工作上的需求开发任务比较重,下班回家基本上就躺床玩几把王者,度过闲暇时光. 二面是一有点时间就自己主动地去看书和学习,知道自己还缺少很多知识,由 ...

  9. Ui自动化测试上传文件方法都在这里了

    前言 实施UI自动化测试的时候,经常会遇见上传文件的操作,那么对于上传文件你知道几种方法呢?今天我们就总结一下几种常用的上传文件的方法,并分析一下每个方法的优点和缺点以及哪种方法效率,稳定性更高 被测 ...

  10. C# Winform --xml文件

    背景: 在工作中,学习和使用OPC Server/Client系统时,发现开发的设计结构是把设备PLC的TAGLIST写为XML文件,在程序启动的时候载入从而完成自动配置. 从而开始了C# ASP.N ...