美文网首页
freemarker除了做网页还能?

freemarker除了做网页还能?

作者: 五洋捉鳖zz | 来源:发表于2020-07-08 14:00 被阅读0次

写在前面

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

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

实现方式

  • 最简单的模版可以是借助字符串拼接或者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();
  • 这里只是简单的封装下哦,可能还有更好的处理方式,看看你的系统,有哪些可以用模版处理的,赶快行动起来吧,毕竟优雅的处理字符串还是需要的。

相关文章

网友评论

      本文标题:freemarker除了做网页还能?

      本文链接:https://www.haomeiwen.com/subject/hwtccktx.html