码迷,mamicode.com
首页 > 其他好文 > 详细

[原创]牛刀小试-重构并实现邮件内容生成功能

时间:2015-02-04 23:15:52      阅读:180      评论:0      收藏:0      [点我收藏+]

标签:

案例

近期团队中多个项目均有邮件发送功能,邮件内容采用html格式,各项目独立开发,无统一实现方案。

举例:

某类型EmailSendService

类型拥有多个String字段 content1、content2 ... content7,均为html文本

生成邮件内容直接使用字符串连接

context1 + userName + content2 + inviteCode +
content3 + money + content4 + year +
content5 + month + content6 + day +
content7

整体不足200来行的代码文件,html字符串就占去了100多行

我对这段代码的评价无疑是 负分 滚出~

 

存在的问题及改进点

1、Html代码混杂在java代码中,且被拆分,邮件内容及样式不易更改

2、邮件内容发送变化,则代码需要重写(正常的项目,邮件模板会发送变更是显而易见的实事)

 

重构

目标

1、Html模板存放于Html文件资源中,java代码以资源文件路径指定模板

2、模板支持参数替换功能,参数可以命名

半小时后重构完成,形成如下类型

文本模板类型

支持参数批量替换,以"${argName}"格式指定参数

public class TextTemplate {
    private String template;

    public TextTemplate() {
        setTemplate("");
    }

    public TextTemplate(String template) {
        setTemplate(template);
    }

    public void setTemplate(String template) {
        this.template = template;
    }

    // 填充指定模板,返回结果字符串
    // 模板参数替换 ${key} 替换为对应 value
    public String fillTemplate(LinkedHashMap<String, String> kvs) {
        List<String> searchList = new ArrayList<>();
        List<String> replacementList = new ArrayList<>();

        for (Map.Entry<String, String> entry : kvs.entrySet()) {
            searchList.add("${" + entry.getKey() + "}");
            replacementList.add(entry.getValue());
        }
        int size = searchList.size();
        return StringUtils.replaceEachRepeatedly(template, searchList.toArray(new String[size]),
                                                        replacementList.toArray(new String[size]));
    }
}

这里使用的org.apache.commons.lang包中的StringUtils工具类,其方法replaceEachRepeatedly可以快速完成字符串替换

资源文件加载工具类

提供工具方法接受资源文件相对路径,返回资源文本

public class ResourceUtility {
    public static String getResourceFullText(String path) {
        return getResourceFullText(path, "UTF-8");
    }

    public static String getResourceFullText(String path, String encoding) {
        ClassPathResource resource = new ClassPathResource(path);
        StringWriter writer = new StringWriter();

        try {
            IOUtils.copy(resource.getInputStream(), writer, encoding);
        } catch (IOException e) {
            throw new RuntimeException("cannot load resource data", e);
        }
        return writer.toString();
    }
}

Email内容生成器类型

public class EmailHtmlContentGenerator {
    private TextTemplate textTemplate;

    public EmailHtmlContentGenerator(String resourcePath) {
        textTemplate = new TextTemplate(ResourceUtility.getResourceFullText(resourcePath));
    }

    public String generateContent(LinkedHashMap<String, String> properties) {
        return textTemplate.fillTemplate(properties);
    }
}

重构上层类型EmailSendService

1、抽取所有Html代码至独立的Html文件中,放置与resources目录下,可采用路径如 emailTemplates/welcome.html

2、所有表示Html代码的字符串字段删除

3、删除邮件Html代码合成逻辑,替代如下代码,独立至一个方法中

    public String generateEmailContent(String userName, String invitationCode, String amount, int year, int month,
                                       int day) {
        LinkedHashMap<String, String> properties = new LinkedHashMap<>();
        properties.put("userName", userName);
        properties.put("amount", amount);
        properties.put("year", String.valueOf(year));
        properties.put("month", String.valueOf(month));
        properties.put("day", String.valueOf(day));
        return emailHtmlContentGenerator.generateContent(properties);
    }

 

单元测试

对TextTemplate类型进行单元测试

public class TextTemplateTests {
    @Test
    public void testFillTemplateWithNoParams() {
        TextTemplate textTemplate = new TextTemplate("Hello World");
        assertEquals("Hello World", textTemplate.fillTemplate(new LinkedHashMap<String, String>()));
    }

    @Test
    public void testFillTemplateWithOneParam() {
        TextTemplate textTemplate = new TextTemplate("Hello ${name}");
        LinkedHashMap<String, String> properties = new LinkedHashMap<>();
        properties.put("name", "Ant");
        assertEquals("Hello Ant", textTemplate.fillTemplate(properties));

        properties.put("name", "Man");
        assertEquals("Hello Man", textTemplate.fillTemplate(properties));
    }

    @Test
    public void testFillTemplateWithMultiParams() {
        TextTemplate textTemplate = new TextTemplate("===== ${greet} ${name} =====");
        LinkedHashMap<String, String> properties = new LinkedHashMap<>();
        properties.put("greet", "Hello");
        properties.put("name", "Ant");
        assertEquals("===== Hello Ant =====", textTemplate.fillTemplate(properties));
    }
}

对EmailSendService类型新增方法进行单元测试

    @Test
    public void testGenerateEmailContent() {
        String emailContent = emailSendService.generateEmailContent("Ant", "999.99", 2015, 2, 4);
        assertTrue(emailContent.contains("尊敬的Ant"));
        assertTrue(emailContent.contains("充值999.99元。"));
        assertTrue(emailContent.contains("2015年2月4日"));
    }

 

[原创]牛刀小试-重构并实现邮件内容生成功能

标签:

原文地址:http://www.cnblogs.com/gods/p/4273135.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!