SpringBoot使用freemarker生成文件并发送邮箱

426 阅读1分钟

    由于工作中涉及到一些复杂格式的文件(doc,xls,pdf等)导出,在网上学习一下poi和freemaker两种方式生成文件。poi对于复杂格式文件的转换代码较为复杂,使用freemarker相对较为方便,下面记录一下freemarker生成简单文件的步骤
1、在要生成的文件中规划好需要的格式,并另存在.xml文件,查看xml文件无误后修改后缀名为.ftl;
比如将下面Excel文件生成为ftl文件:
Excel文件:
image.png
ftl代码(只展示主要部分):

<Worksheet ss:Name="Sheet1">
 <Table ss:ExpandedColumnCount="4" ss:ExpandedRowCount="2" x:FullColumns="1"
  x:FullRows="1" ss:StyleID="s16" ss:DefaultColumnWidth="52"
  ss:DefaultRowHeight="15">
  <Row>
   <Cell><Data ss:Type="String">姓名</Data></Cell>
   <Cell><Data ss:Type="String">年龄</Data></Cell>
   <Cell><Data ss:Type="String">性别</Data></Cell>
   <Cell><Data ss:Type="String">爱好</Data></Cell>
  </Row>
  <Row>
   <Cell><Data ss:Type="String">${userName}</Data></Cell>
   <Cell><Data ss:Type="String">${age}</Data></Cell>
   <Cell><Data ss:Type="String">${sex}</Data></Cell>
   <Cell><Data ss:Type="String">${happies}</Data></Cell>
  </Row>
 </Table>
 <WorksheetOptions xmlns="urn:schemas-microsoft-com:office:excel">
  <PageSetup>
   <Header x:Margin="0.3"/>
   <Footer x:Margin="0.3"/>
   <PageMargins x:Bottom="0.75" x:Left="0.7" x:Right="0.7" x:Top="0.75"/>
  </PageSetup>
  <Print>
   <ValidPrinterInfo/>
   <PaperSizeIndex>9</PaperSizeIndex>
   <HorizontalResolution>600</HorizontalResolution>
   <VerticalResolution>600</VerticalResolution>
  </Print>
  <Selected/>
  <Panes>
   <Pane>
    <Number>3</Number>
    <ActiveRow>1</ActiveRow>
    <ActiveCol>3</ActiveCol>
   </Pane>
  </Panes>
  <ProtectObjects>False</ProtectObjects>
  <ProtectScenarios>False</ProtectScenarios>
 </WorksheetOptions>
</Worksheet>

需要注意的是ftl中接收数据的格式为${},其中传入的数据可以是Map或者实体类,也可以用list集合包装map或者实体类,这就需要在后端或者ftl中对数据进行处理。
2、建立freemarker工具类;

public class FreeMarkerUtils {

    private static Configuration configuration = null;
    static{
        //创建操作类
        configuration = new Configuration(Configuration.DEFAULT_INCOMPATIBLE_IMPROVEMENTS);
        //注意后缀是以反斜杠开始;setClassForTemplateLoading:在类路径中读取ftl文件
        configuration.setClassForTemplateLoading(FreeMarkerUtils.class, "/ftl");
        //设置编码格式
        configuration.setDefaultEncoding("utf-8");
    }

    public static void generateFileFromFtl(String templateName, Map<String, Object> map, String filePath, StringWriter stringWriter){
        try (FileWriter fw = new FileWriter(filePath)){
            //读取模版
            Template template = configuration.getTemplate(templateName);
            //对模版进行处理,将传来的map写到文件中
            template.process(map, fw);
            if (stringWriter != null){
                template.process(map, stringWriter);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}

3、传入数据
这里需要将生成的文件作为附件发送,所以需要写一个对应邮件格式的ftl文件并创建发送邮件的工具类;

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>测试邮件-大嘴巴</title>
</head>
<body>
    <h2>工作人员兴趣统计:</h2>
    <table border="1" cellspacing="0" align="center">

        <tr align="center">
            <td>姓名</td>
            <td>年龄</td>
            <td>性别</td>
            <td>爱好</td>
        </tr>

        <tr align="center">
            <td>${userName}</td>
            <td>${age}</td>
            <td>${sex}</td>
            <td>${happies}</td>
        </tr>

    </table>
</body>
</html>

邮件工具类

//发送邮件的工具类:
public class SendMailUtils{
    @Value("${spring.mail.host}")
    private String host;

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

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

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

    public void sendEmail(String htmlContent, String fileHtml) throws Exception {
        JavaMailSenderImpl sender = new JavaMailSenderImpl();
        Properties properties = new Properties();
        properties.setProperty("mail.transport.protocol", "smtp");// 连接协议
        properties.setProperty("mail.smtp.timeout", "25000");
        properties.setProperty("mail.smtp.socketFactory.port", port);
        properties.setProperty("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
        properties.setProperty("mail.debug", "true");
        sender.setJavaMailProperties(properties);
        sender.setUsername(userName);
        sender.setPassword(password);
        sender.setHost(host);
        sender.setPort(Integer.parseInt(port));
        MimeMessage message = sender.createMimeMessage();
        MimeMessageHelper helper = new MimeMessageHelper(message, true, "utf-8");
        helper.setFrom(userName);
        helper.setSubject("test");
        helper.setTo("xxx@yyy.com");
        helper.setText(htmlContent);
        String s = MimeUtility.encodeText("test");
        helper.addAttachment(s + ".html", new File(fileHtml));
        sender.send(message);
    }
}

配置文件中对邮箱的配置:

spring.mail.host=smtp.qq.com
spring.mail.port=587
spring.mail.username=xxx@qq.com
spring.mail.password=填入授权码
spring.mail.properties.mail.smtp.auth=true
spring.mail.properties.mail.smtp.ssl.enable=true
spring.mail.properties.mail.smtp.starttls.enable=true
spring.mail.properties.mail.smtp.starttls.required=true

进行测试:

Map<String, Object> map = new HashMap<>();
map.put("userName", "大嘴巴");
map.put("age", "XX");
map.put("sex", "男");
map.put("happies","敲代码...");
String excelPath = "E:\usr\local\excel\output.xls";
String htmlPath = "E:\usr\local\html\output.html";
StringWriter str = new StringWriter();
generateFileFromFtl("testHtml.ftl", map, htmlPath, str);
sendEmail.sendEmail(str.toString(), htmlPath);
generateFileFromFtl("testExcel.ftl", map, excelPath, null);