Freemarker学习--程序开发

一、创建 Configuration 实例

 

Configuration cfg = new Configuration(Configuration.VERSION_2_3_22);
cfg .setClassForTemplateLoading(this.getClass(), "ftl");

cfg.setDefaultEncoding("UTF-8");
cfg.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);

 不需要重复创建 Configuration 实例; 它的代价很高,尤其是会丢失缓存。Configuration实例就是应用级别的单例。

 

二、获取模板

Template temp = cfg.getTemplate("hashes.ftl");

Configuration 缓存 Template 实例,当再次获得 hashes.ftl 的时候,它可能再读取和解析模板文件了, 而只是返回第一次的 Template实例。

三、数据模型

在内部,模板中可用的变量都是实现了freemarker.template.TemplateModel 接口的Java对象。 但在数据模型中,可以使用基本的Java集合类作为变量,因为这些变量会在内部被替换为适当的 TemplateModel 类型,类freemarker.template.ObjectWrapper的职责

A、标量

有4种类型的标量:

  • 布尔值
  • 数字
  • 字符串
  • 日期类型(子类型: 日期(没有时间部分),时间或者日期-时间)

每一种标量类型都是 TemplateTypeModel 接口的实现,这里的 Type 就是类型的名称。这些接口只定义了一个方法: typegetAsType();。 它返回变量的Java类型(boolean, Number, String 和 Date 各自代表的值)。

B、哈希表 对应TemplateHashModel 

C、序列对应TemplateSequenceModel  

D、集合 对应TemplateCollectionModel 

E、方法对应TemplateMethodModel 

方法示例:

public class IndexOfMethod implements TemplateMethodModel {
    
    public TemplateModel exec(List args) throws TemplateModelException {
        if (args.size() != 2) {
            throw new TemplateModelException("Wrong arguments");
        }
        return new SimpleNumber(
            ((String) args.get(1)).indexOf((String) args.get(0)));
    }
}

如果将一个实例放入根数据模型中,像这样:

root.put("indexOf", new IndexOfMethod());

那么就可以在模板中调用:

<#assign x = "something">
${indexOf("met", x)}
${indexOf("foo", x)}

将会输出:

2
-1

 F、指令 对应TemplateDirectiveModel 

我们来创建一个指令,这个指令可以一次又一次地执行其中的嵌套内容, 这个次数由指定的数字来确定(就像 list 指令), 可以使用<hr>将输出的重复内容分开。 这个指令我们命名为"repeat"。示例模板如下:

<#assign x = 1>

<@repeat count=4>
  Test ${x}
  <#assign x++>
</@repeat>

<@repeat count=3 hr=true>
  Test
</@repeat>

<@repeat count=3; cnt>
  ${cnt}. Test
</@repeat>

输出为:

  Test 1
  Test 2
  Test 3
  Test 4

  Test
<hr>  Test
<hr>  Test

  1. Test
  2. Test
  3. Test
指令的实现类为:
public class RepeatDirective implements TemplateDirectiveModel {
    
    private static final String PARAM_NAME_COUNT = "count";
    private static final String PARAM_NAME_HR = "hr";
    
    public void execute(Environment env,
            Map params, TemplateModel[] loopVars,
            TemplateDirectiveBody body)
            throws TemplateException, IOException {
        
        // ---------------------------------------------------------------------
        // Processing the parameters:
        
        int countParam = 0;
        boolean countParamSet = false;
        boolean hrParam = false;
        
        Iterator paramIter = params.entrySet().iterator();
        while (paramIter.hasNext()) {
            Map.Entry ent = (Map.Entry) paramIter.next();
            
            String paramName = (String) ent.getKey();
            TemplateModel paramValue = (TemplateModel) ent.getValue();
            
            if (paramName.equals(PARAM_NAME_COUNT)) {
                if (!(paramValue instanceof TemplateNumberModel)) {
                    throw new TemplateModelException(
                            "The \"" + PARAM_NAME_HR + "\" parameter "
                            + "must be a number.");
                }
                countParam = ((TemplateNumberModel) paramValue)
                        .getAsNumber().intValue();
                countParamSet = true;
                if (countParam < 0) {
                    throw new TemplateModelException(
                            "The \"" + PARAM_NAME_HR + "\" parameter "
                            + "can't be negative.");
                }
            } else if (paramName.equals(PARAM_NAME_HR)) {
                if (!(paramValue instanceof TemplateBooleanModel)) {
                    throw new TemplateModelException(
                            "The \"" + PARAM_NAME_HR + "\" parameter "
                            + "must be a boolean.");
                }
                hrParam = ((TemplateBooleanModel) paramValue)
                        .getAsBoolean();
            } else {
                throw new TemplateModelException(
                        "Unsupported parameter: " + paramName);
            }
        }
        if (!countParamSet) {
                throw new TemplateModelException(
                        "The required \"" + PARAM_NAME_COUNT + "\" paramter"
                        + "is missing.");
        }
        
        if (loopVars.length > 1) {
                throw new TemplateModelException(
                        "At most one loop variable is allowed.");
        }
        
        // Yeah, it was long and boring...
        
        // ---------------------------------------------------------------------
        // Do the actual directive execution:
        
        Writer out = env.getOut();
        if (body != null) {
            for (int i = 0; i < countParam; i++) {
                // Prints a <hr> between all repetations if the "hr" parameter
                // was true:
                if (hrParam && i != 0) {
                    out.write("<hr>");
                }
                
                // Set the loop variable, if there is one:
                if (loopVars.length > 0) {
                    loopVars[0] = new SimpleNumber(i + 1);
                }
                
                // Executes the nested body (same as <#nested> in FTL). In this
                // case we don't provide a special writer as the parameter:
                body.render(env.getOut());
            }
        }
    }

}
 四、实用类
1、访问静态方法
BeansWrapper wrapper = BeansWrapper.getDefaultInstance();
TemplateHashModel staticModels = wrapper.getStaticModels();
TemplateHashModel fileStatics =
    (TemplateHashModel) staticModels.get("java.io.File");
 2、访问枚举类型
BeansWrapper wrapper = BeansWrapper.getDefaultInstance();
TemplateHashModel enumModels = wrapper.getEnumModels();
TemplateHashModel roundingModeEnums =
    (TemplateHashModel) enumModels.get("java.math.RoundingMode");
 3、自定义模版加载
FileTemplateLoader ftl1 = new FileTemplateLoader(new File("/tmp/templates"));
FileTemplateLoader ftl2 = new FileTemplateLoader(new File("/usr/data/templates"));
ClassTemplateLoader ctl = new ClassTemplateLoader(getClass(), "");
TemplateLoader[] loaders = new TemplateLoader[] { ftl1, ftl2, ctl };
MultiTemplateLoader mtl = new MultiTemplateLoader(loaders);

cfg.setTemplateLoader(mtl);
 

你可能感兴趣的:(freemarker)