freemarker除了做网页还能?

写在前面

  • 模版化应用广泛,所有的网页都是借助模版化,将丰富多彩的数据展现在用户面前。对于后端开发而言也离不开模版,例如代码生成器,邮件短信提示文字内容,更如对于一些大型的分布式系统的配置文件生成等等。

模版其实和数据离不开的,一个模版只是规定了一部分最终内容的格式,最终内容的展示还需要将数据绑定至模版后实现。正常的流程为 获取模版&获取数据 ->模版数据渲染->生成最终内容

实现方式

  • 最简单的模版可以是借助字符串拼接或者String.format。但这些仅仅只适用于一些简单模版。
String useName = "helloWorld";
String msg1 = "您好" +useName+ "监测到今天是您的生日,祝您生日快乐!";
String msg2 = String.format("您好%s,检测到今天是您的生日,祝您生日快乐!", useName);
Message.send(msg1);
Message.send(msg2);
  • 但是对于一些较为复杂的内容,使用👆的方式显然加大了后期的维护难度,同时不利于系统的扩展性与延展性。这里我们借助apache freemarker,在我们的项目中实现一些复杂的模版渲染。
  1. 引入依赖(这里使用万金油的maven,当然您也可以选择你喜欢的任何打包工具)
<dependency>
    <groupId>org.freemarker</groupId>
    <artifactId>freemarker</artifactId>
    <version>2.3.29</version>
</dependency>
  1. 在我们的Resource目录下创建一个自定义文件夹,这里就叫ftl吧
  2. 在ftl目录下创建我们的模版birthdayMsg.ftl内容如下
您好,${useName},检测到今天是您的生日,祝您生日快乐!
  1. 创建一个模版渲染的工具类

getTemplate() 此方法为获取模版内容的方法
generate() 此方法为模版渲染数据的方法,为方便展示这里使用的数据格式用map描述,如果你喜欢,可以改为自建的pojo
/ftl:这个为我们在resoruce目录下创建的目录文件夹,你可以改成自己喜欢的样子

package //package保密改成你自己的;

import freemarker.template.Configuration;
import freemarker.template.Template;
import io.transwarp.malasong.shell.model.BaseDataModel;

import java.io.*;
import java.util.Map;

public class TemplateUtil {

    public static Configuration configuration;

    static {
        try{
            configuration = new Configuration(Configuration.VERSION_2_3_0);
            configuration.setClassForTemplateLoading(TemplateLoader.class, "/ftl");
        }catch(Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * get template instance
     * @param templateName
     * @return
     */
    public static Template getTemplate(String templateName) {
        try {
            return configuration.getTemplate(templateName);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    public static String generate(Map<String, String> params, String templatePath) {
        Template template = getTemplate(templatePath);
        try(StringWriter stringWriter = new StringWriter()) {
            template.process(params, stringWriter);
            return stringWriter.toString();
        }catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
}

  1. 现在我们来重新实现下👆简单实现中的业务逻辑
String useName = "helloWorld";
Map<String, String> data = new HashMap<>();
data.put("userName", useName);
String msg = TemplateUtil.generate(data, "/birthdayMsg.ftl");
Message.send(msg1);
  1. 当我们的通知消息只有一个useName时,显然简单方式较为方便,但是当我们的通知模版内容哦越来越复杂,在使用复杂模式势必会造成简单的text文本与内容高度耦合.后期维护困难。

进阶

  • 上面也看到了每次使用模版都需要去通过模版名称获取模版内容,完成最终绑定,如果模版非常多,那么管理起来将会非常困难。这里我们可以对TemplateUtil 再做进一步的封装,让模版名称传入的更优雅,并创建一些Model来描述我们的模版数据结构。
  1. 首先加大我们的需求难度,对不同国家的人进行生日提醒,提醒时需要告知多少岁,当然不同国家需要使用不同的语言。
  2. 创建注解类,用于描述我们的模版名称及模版路径
package //;
import java.lang.*;
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface TemplateResource {

    String path() default "sql"; // resource下的路径
    String template() default ""; // 具体的模板名称${MODEL_LINE_NAME}.ftl
}
  1. 创建我们的生日提醒的model

package //;

public abstract class BirthdayMsg{

    public  String useName;
    public  int age;

    // 通过注解获取模版路径及模版名称
    public Tuple2<String,String> getPathAndTemplateName() {
        TemplateResource annotation = this.getClass().getAnnotation(TemplateResource.class);
        if(annotation != null) {
            return new Tuple2<>(annotation.path(), annotation.template());
        }
        return null;
    }

    // 模版初始化
    public Template initTemplate(Tuple2<String,String> pathNameTemplateName) {
        Configuration configuration;
        try {
            //创建Configuration对象
            configuration = new Configuration(Configuration.VERSION_2_3_0);
            //设置模板所在目录
            configuration.setClassForTemplateLoading(MailUtils.class,pathNameTemplateName.t1());
            //获取模板
            return configuration.getTemplate(pathNameTemplateName.t2());

        }catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    // 内容导出
    public String generate() {
        Template template = initTemplate(getPathAndTemplateName);
        try(StringWriter stringWriter = new StringWriter()) {
            template.process(this, stringWriter);
            return stringWriter.toString();
        }catch (Exception e) {
            e.printStackTrace();
        }
        return null;
        
    }

    }
    
    // getter setter ...
}
  1. 创建中文用户的生日提醒类,,其他语言的我们这里就不列举了,
package //;


@TemplateResource(path="/ch", template="birthdayMsg")
public class BirthdayMsgCh extends BirthdayMsg{

}
  1. 实际使用
String language = ""
// 依据不同的language新建不同的model
BirthdayMsg model = new XXXXX
// 给model填入数据
....
String msg = model.genrate();
  • 这里只是简单的封装下哦,可能还有更好的处理方式,看看你的系统,有哪些可以用模版处理的,赶快行动起来吧,毕竟优雅的处理字符串还是需要的。
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,684评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,143评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,214评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,788评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,796评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,665评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,027评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,679评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,346评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,664评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,766评论 1 331
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,412评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,015评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,974评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,073评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,501评论 2 343

推荐阅读更多精彩内容