【个人技术经验及开发技巧分享】 【个人技术经验及开发技巧分享】
首页
  • 操作系统初识
  • JAVA基础
  • JVM
  • 开发框架
  • Redis
  • Zookeeper
  • 消息中间件
  • 持久化
  • 算法
  • 网络
  • 系统架构
  • 并发编程
  • 框架
  • 开发杂货
  • 线上排查
  • 技巧备忘
  • 部署指南
  • 版本管理
  • 工作流程
  • 发版流程
  • 友情链接
  • 网站备忘
  • 在线工具
  • 学习
  • 各种云
  • 应用下载

Louis

首页
  • 操作系统初识
  • JAVA基础
  • JVM
  • 开发框架
  • Redis
  • Zookeeper
  • 消息中间件
  • 持久化
  • 算法
  • 网络
  • 系统架构
  • 并发编程
  • 框架
  • 开发杂货
  • 线上排查
  • 技巧备忘
  • 部署指南
  • 版本管理
  • 工作流程
  • 发版流程
  • 友情链接
  • 网站备忘
  • 在线工具
  • 学习
  • 各种云
  • 应用下载
  • 开发杂货

    • ES查询压测
    • Spring Cloud Stream
    • 线上Tomcat配置参考
    • 配置Prometheus及健康检测
    • Feign支持BasicAuth验证
    • Feign远程调用
    • Hystrix单方法熔断配置
    • 邮件发送自定义Excel
      • 1 邮件功能
        • 1.1 添加邮件相关依赖包
        • 1.2 邮件配置
        • 1.3 发送邮件工具类
      • 2 Excel功能
        • 2.1 添加EasyExcel相关依赖包
        • 2.2 获取Excel模板并填充数据
      • 3 发送Excel附件的邮件
    • 本地开发联调配置
    • RabbitMQ配置备忘
    • Nacos配置中心
    • Java代码杂记
    • Oracle脚本备忘
    • Mysql并发数与连接数
    • 批量算费本地工具类
    • Apollo配置模糊查询
    • 异步任务AsyncIAE
    • 生产环境机器配置参考
  • 线上排查

  • 技巧备忘

  • 部署指南

  • 技术应用
  • 开发杂货
luoxiaofeng
2022-05-27
目录

邮件发送自定义Excel

需求:

给定Excel模板,将数据填充到模板,并将生成的Excel文件发送邮件。
1

解决方案:

采用EasyExcel填充模板文件。
采用spring提供的发送邮件接口JavaMailSender实现邮件功能。
1
2

# 1 邮件功能

# 1.1 添加邮件相关依赖包

<!-- 邮件 -->
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-mail</artifactId>
</dependency>
1
2
3
4
5

# 1.2 邮件配置

spring:
  mail:
    host: smtphz.qiye.163.com 
    username: xxxxxx
    password: xxxxxx
    port: 465
    protocol: smtps
    default-encoding: UTF-8
    properties:
      mail:
        smtp:
        ssl:
          enable: true
        starttls:
        enable: true
        required: true
        connectiontimeout: 5000
        timeout: 3000
        writetimeout: 5000
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

# 1.3 发送邮件工具类

package com.xxx.impl.util;

import cn.hutool.core.util.ObjectUtil;
import com.xxx.vo.order.EmailAttachment;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.InputStreamSource;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import javax.mail.MessagingException;
import javax.mail.internet.MimeMessage;
import java.io.File;
import java.util.List;

@Service
@Slf4j
public class EmailUtil {

  @Resource
  private JavaMailSender javaMailSender;

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

  /**
   * 发送邮件
   *
   * @param title     邮件标题
   * @param msg       消息内容
   * @param appendix  附件
   * @param receivers 接收人
   */
  public void sendEmail(String title, String msg, File appendix, String... receivers) {
    try {
      //没有附件 或 没有收件人,不发送邮件
      if (ObjectUtil.isEmpty(appendix) || ObjectUtil.isEmpty(receivers)) {
        return;
      }
      MimeMessage mimeMessage = javaMailSender.createMimeMessage();
      MimeMessageHelper messageHelper = new MimeMessageHelper(mimeMessage, true);
      messageHelper.setFrom(from);
      messageHelper.setTo(receivers);
      messageHelper.setSubject(title);
      messageHelper.setText(msg);
      messageHelper.addAttachment(appendix.getName(), appendix);
      javaMailSender.send(mimeMessage);

    } catch (MessagingException e) {
      e.printStackTrace();
    }
  }

  /**
   * 发送邮件
   *
   * @param title     邮件标题
   * @param msg       消息内容
   * @param appendix  附件
   * @param receivers 接收人
   */
  public void sendEmailByIns(String title, String msg, String fileName, InputStreamSource appendix, String... receivers) {
    try {
      MimeMessage mimeMessage = javaMailSender.createMimeMessage();
      MimeMessageHelper messageHelper = new MimeMessageHelper(mimeMessage, true);
      messageHelper.setFrom(from);
      messageHelper.setTo(receivers);
      messageHelper.setSubject(title);
      messageHelper.setText(msg, true);
      messageHelper.addAttachment(fileName, appendix);
      javaMailSender.send(mimeMessage);
    } catch (MessagingException e) {
      e.printStackTrace();
    }
  }

  /**
   * 发送邮件
   *
   * @param title     邮件标题
   * @param msg       消息内容
   * @param attachmentList  附件
   * @param receivers 接收人
   */
  public void sendEmailByIns(String title, String msg, List<EmailAttachment> attachmentList, String... receivers) {
    try {
      MimeMessage mimeMessage = javaMailSender.createMimeMessage();
      MimeMessageHelper messageHelper = new MimeMessageHelper(mimeMessage, true);
      messageHelper.setFrom(from);
      messageHelper.setTo(receivers);
      messageHelper.setSubject(title);
      messageHelper.setText(msg, true);
      if (!CollectionUtils.isEmpty(attachmentList)) {
        for (EmailAttachment attachment : attachmentList) {
          messageHelper.addAttachment(attachment.getFileName(), attachment.getAppendix());
        }
      }
      javaMailSender.send(mimeMessage);
    } catch (MessagingException e) {
      e.printStackTrace();
    }
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
package com.xxx.vo.order;

import lombok.Data;
import org.springframework.core.io.InputStreamSource;

@Data
public class EmailAttachment {

  private String fileName;

  private InputStreamSource appendix;

}
1
2
3
4
5
6
7
8
9
10
11
12
13

# 2 Excel功能

提示

EasyExcel是一个基于Java的简单、省内存的读写Excel的开源项目。在尽可能节约内存的情况下支持读写百M的Excel。

github地址:https://github.com/alibaba/easyexcel (opens new window)

使用说明:https://easyexcel.opensource.alibaba.com (opens new window)

# 2.1 添加EasyExcel相关依赖包

<!-- Excel -->
<dependency>
  <groupId>com.alibaba</groupId>
  <artifactId>easyexcel</artifactId>
  <version>2.1.6</version>
</dependency>
1
2
3
4
5
6

# 2.2 获取Excel模板并填充数据

模板文件存放在项目resources目录下

image-20220528173736320

例:DN-A模板内容

image-20220528171225820

public class Test {

  public DataResult sendMail(TestMailInfoDto testMailInfoDto) {
    log.info("sendMail testMailInfoDto = {}", JSON.toJSONString(testMailInfoDto));

    try {
      TestDnVO testDnVO = basicsTestMapper.queryTestDn(testMailInfoDto.getBillcode());
      List<TestDnDetailVO> testDnDetailVOList = basicsTestMapper.queryTestDnDetail(testMailInfoDto.getBillcode());
      List<TestImeiVO> testImeiVOList = basicsTestMapper.queryTestImeiList(testMailInfoDto.getBillcode());

      List<EmailAttachment> attachmentList = new ArrayList<>();
      EmailAttachment dnAttachment = getDnAttachment(testDnVO, testDnDetailVOList, getDNTemplate(testMailInfoDto));
      if (dnAttachment != null) {
        attachmentList.add(dnAttachment);
      }
      EmailAttachment imeiAttachment = getImeiAttachment(testImeiVOList, getImeiTemplate(testMailInfoDto));
      if (imeiAttachment != null) {
        attachmentList.add(imeiAttachment);
      }
      emailUtil.sendEmailByIns(testMailInfoDto.getTitle(), testMailInfoDto.getMsg(), attachmentList, testMailInfoDto.getReceivers());
    } catch (Exception e) {
      log.error("sendMail Exception", e);
      return error(ResultCodeEnum.SYSTEM_BUSY.getCode(), e.getMessage());
    }
    return success();
  }

  private EmailAttachment getDNTemplate(TestMailInfoDto testMailInfoDto) {
    EmailAttachment attachment = null;
    ClassPathResource classPathResource = null;
    switch (testMailInfoDto.getDmTemplete()) {
      case "DN-A":
        classPathResource = new ClassPathResource("excel" + File.separator + "DN-A.xlsx");
        break;
      case "DN-B":
        classPathResource = new ClassPathResource("excel" + File.separator + "DN-B.xlsx");
        break;
      case "DN-C":
        classPathResource = new ClassPathResource("excel" + File.separator + "DN-C.xlsx");
        break;
    }
    if (classPathResource != null) {
      attachment = new EmailAttachment();
      attachment.setFileName(testMailInfoDto.getDmTemplete() + ".xlsx");
      attachment.setAppendix(classPathResource);
    }
    return attachment;
  }

  private EmailAttachment getDnAttachment(TestDnVO testDnVO, List<TestDnDetailVO> testDnDetailVOList, EmailAttachment emailAttachment) throws Exception {
    if (emailAttachment == null) {
      return null;
    }

    ByteArrayOutputStream out = new ByteArrayOutputStream();
    ExcelWriter excelWriter = null;
    try {
      excelWriter = EasyExcel.write(out).withTemplate(emailAttachment.getAppendix().getInputStream()).build();
      WriteSheet writeSheet = EasyExcel.writerSheet().build();

      //dn主单
      //由于变量属性有一个个设置,直接通过反射的反射一次性设置
      Map<String, Object> map = new HashMap<>();
      Class clazz = testDnVO.getClass();
      Field[] fields = clazz.getDeclaredFields();
      for (Field field : fields) {
        field.setAccessible(true);
        map.put(field.getName(), field.get(testDnVO));
      }

      //dn明细
      // 这里注意 入参用了forceNewRow 代表在写入list的时候不管list下面有没有空行 都会创建一行,然后下面的数据往后移动。默认 是false,会直接使用下一行,如果没有则创建。
      // forceNewRow 如果设置了true,有个缺点 就是他会把所有的数据都放到内存了,所以慎用
      // 简单的说 如果你的模板有list,且list不是最后一行,下面还有数据需要填充 就必须设置 forceNewRow=true 但是这个就会把所有数据放到内存 会很耗内存
      FillConfig fillConfig = FillConfig.builder().forceNewRow(Boolean.TRUE).build();
      excelWriter.fill(testDnDetailVOList, fillConfig, writeSheet);

      //dn明细汇总
      int totalPcs = 0;
      int totalCtns = 0;
      int totalPlts = 0;
      BigDecimal totalGw = BigDecimal.ZERO;
      BigDecimal totalCbm = BigDecimal.ZERO;
      for (TestDnDetailVO detailVO : testDnDetailVOList) {
        totalPcs += (detailVO.getPcs() == null ? 0 : detailVO.getPcs());
        totalCtns += (detailVO.getCtns() == null ? 0 : detailVO.getCtns());
        totalPlts += (detailVO.getPlts() == null ? 0 : detailVO.getPlts());
        totalGw = totalGw.add(detailVO.getGw() == null ? BigDecimal.ZERO : detailVO.getGw());
        totalCbm = totalCbm.add(detailVO.getGw() == null ? BigDecimal.ZERO : detailVO.getCbm());
      }
      map.put("totalPcs", totalPcs);
      map.put("totalCtns", totalCtns);
      map.put("totalPlts", totalPlts);
      map.put("totalGw", totalGw.doubleValue());
      map.put("totalCbm", totalCbm.doubleValue());

      excelWriter.fill(map, writeSheet);

    } finally {
      if (excelWriter != null) {
        excelWriter.finish();
      }
    }
    emailAttachment.setAppendix(new ByteArrayResource(out.toByteArray()));
    return emailAttachment;
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107

# 3 发送Excel附件的邮件

image-20220528175829762

image-20220528180015935

Hystrix单方法熔断配置
本地开发联调配置

← Hystrix单方法熔断配置 本地开发联调配置→

最近更新
01
SpringBoot
10-21
02
Spring
10-20
03
Sentinel
10-14
更多文章>
Copyright © 2022-2023 Louis | 粤ICP备2022060093号-1
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式