欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

【SpringBoot 采坑记】- FreeMarker

程序员文章站 2022-06-01 07:51:11
...

以下以邮件演示说明

1. pom.xml引入依赖:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-freemarker</artifactId>
    <version>2.3.0.RELEASE</version>
</dependency>

2. yml文件:

spring:
  freemarker:
    cache: false
    charset: UTF-8
    content-type: text/xml
    template-loader-path: classpath:/templates/
    suffix: .ftl

3. .ftl文件

<!DOCTYPE html>
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>测试模板邮件</title>
</head>
<body>

<table border="1" align="center" width="50%">
    <tr>
        <th>区域Id</th>
        <th>区域名称</th>
        <th>区域级别</th>
    </tr>
    <#list districtModelList as districtModel>
        <tr>
            <td>${districtModel.districtId}</td>
            <td>${districtModel.districtName}</td>
            <td>${districtModel.level}</td>
        </tr>
    </#list>

</table>

</body>
</html>

4..java文件

  • mail代码片段
    /**
     * 发送模板邮件
     *
     * @param receiver 邮件接收人
     * @param subject  邮件主题
     * @throws MessagingException
     */
    public void sendTemplateMail(String receiver, String subject, Object model) throws MessagingException, IOException, TemplateException {
        MimeMessage mimeMessage = javaMailSender.createMimeMessage();

        MimeMessageHelper mimeMessageHelper = new MimeMessageHelper(mimeMessage, true);

        assembleMailMessage(mimeMessageHelper, receiver, subject);

        Template template = configuration.getTemplate("district.ftl", "utf-8");

        String text = FreeMarkerTemplateUtils.processTemplateIntoString(template, model);

        mimeMessageHelper.setText(text, true);

        javaMailSender.send(mimeMessage);
    }

    private void assembleMailMessage(MimeMessageHelper mimeMessageHelper, String receiver, String subject) throws MessagingException {
        mimeMessageHelper.setFrom(username);
        mimeMessageHelper.setTo(receiver);
        mimeMessageHelper.setSentDate(new Date());
        mimeMessageHelper.setSubject(subject);
    }
  • controller代码片段
    @GetMapping("test/mail/freemarker")
    public ApiResponse testMail() throws MessagingException, IOException, TemplateException {
        Map<String, Object> map = new HashMap<>(1);

        map.put("districtModelList", DataProvider.getDistrictProvince());

        mailService.sendTemplateMail("aaa@qq.com", "测试邮件标题", map);

        return ApiResponse.success();
    }
  • 数据代码片段
    public static List<DistrictModel> getDistrictProvince() {
        List<DistrictModel> districtModelList = new ArrayList<>(23);

        districtModelList.add(new DistrictModel("10001", "安徽省", null, 1));
        districtModelList.add(new DistrictModel("10002", "福建省", null, 1));
        districtModelList.add(new DistrictModel("10003", "甘肃省", null, 1));
        districtModelList.add(new DistrictModel("10004", "广东省", null, 1));
        districtModelList.add(new DistrictModel("10005", "贵州省", null, 1));
        districtModelList.add(new DistrictModel("10006", "海南省", null, 1));
        districtModelList.add(new DistrictModel("10007", "河北省", null, 1));
        districtModelList.add(new DistrictModel("10008", "河南省", null, 1));
        districtModelList.add(new DistrictModel("10009", "黑龙江省", null, 1));
        districtModelList.add(new DistrictModel("10010", "湖北省", null, 1));
        districtModelList.add(new DistrictModel("10011", "湖南省", null, 1));
        districtModelList.add(new DistrictModel("10012", "吉林省", null, 1));
        districtModelList.add(new DistrictModel("10013", "江苏省", null, 1));
        districtModelList.add(new DistrictModel("10014", "江西省", null, 1));
        districtModelList.add(new DistrictModel("10015", "辽宁省", null, 1));
        districtModelList.add(new DistrictModel("10016", "青海省", null, 1));
        districtModelList.add(new DistrictModel("10017", "山东省", null, 1));
        districtModelList.add(new DistrictModel("10018", "山西省", null, 1));
        districtModelList.add(new DistrictModel("10019", "陕西省", null, 1));
        districtModelList.add(new DistrictModel("10020", "四川省", null, 1));
        districtModelList.add(new DistrictModel("10021", "*省", null, 1));
        districtModelList.add(new DistrictModel("10022", "云南省", null, 1));
        districtModelList.add(new DistrictModel("10023", "浙江省", null, 1));

        return districtModelList;
    }
  • model代码片段
@Data
@ApiModel("区域信息")
@AllArgsConstructor
@Accessors(chain = true)
public class DistrictModel {

    @ApiModelProperty(value = "区域Id", required = true)
    private String districtId;

    @ApiModelProperty(value = "区域名称", required = true)
    private String districtName;

    @ApiModelProperty(value = "父级区域Id")
    private String parentDistrictId;

    @ApiModelProperty(value = "区域级别", required = true)
    private Integer level;
}

5. 效果展示:

【SpringBoot 采坑记】- FreeMarker

注意事项:

  • freemarker只能接受Map键值对或者JavaBean作为参数
    举例:
  1. Map
<!DOCTYPE html>
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>测试模板邮件</title>
</head>
<body>

<table border="1" align="center" width="50%">
    <tr>
        <th>区域Id</th>
        <th>区域名称</th>
        <th>区域级别</th>
    </tr>
    <tr>
        <td>${districtId}</td>
        <td>${districtName}</td>
        <td>${level}</td>
    </tr>
</table>

</body>
</html>
    @GetMapping("test/mail/freemarker")
    public ApiResponse testMail() throws MessagingException, IOException, TemplateException {

        Map<String, String> map = new HashMap<>(3);

        map.put("districtId", "10012");
        map.put("districtName", "大连市");
        map.put("level", "2");
        
        mailService.sendTemplateMail("aaa@qq.com", "测试邮件标题", map);

        return ApiResponse.success();
    }

效果图:
【SpringBoot 采坑记】- FreeMarker
2. JavaBean

<!DOCTYPE html>
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>测试模板邮件</title>
</head>
<body>

<table border="1" align="center" width="50%">
    <tr>
        <th>区域Id</th>
        <th>区域名称</th>
        <th>区域级别</th>
    </tr>
    <tr>
        <td>${districtId}</td>
        <td>${districtName}</td>
        <td>${level}</td>
    </tr>
</table>

</body>
</html>
    @GetMapping("test/mail/freemarker")
    public ApiResponse testMail() throws MessagingException, IOException, TemplateException {

        DistrictModel districtModel = new DistrictModel("10010", "北京市", null, 1);

        mailService.sendTemplateMail("aaa@qq.com", "测试邮件标题", districtModel);

        return ApiResponse.success();
    }

效果图:
【SpringBoot 采坑记】- FreeMarker

  • 如果想展示list,需要将集合放到map中,再根据对应key取出集合,如上所示

  • 异常说明
    1.freemarker.core.InvalidReferenceException: The following has evaluated to null or missing:Tip: If the failing expression is known to legally refer to something that's sometimes null or missing, either specify a default value like myOptionalVar!myDefault...

    说明mapkey或者bean的属性名字对应不上,freemarker找不到要展示的数据;或者属性的值为null

    2.java.lang.IllegalArgumentException: freemarker.template.DefaultObjectWrapper didn't convert java.util.ArrayList to a TemplateHashModel. Generally, you want to use a Map<String, Object> or a JavaBean as the root-map (aka. data-model) parameter. The Map key-s or JavaBean property names will be the variable names in the template.

    说明freemarker需要接收map或者bean作为参数,但是你传了一个list,将list放入map中即可