1. 方法变量在存于实现了TemplateMethodModel接口的模板中。这个接口包含一个方法: TemplateModel exec(java.util.List arguments)。
2. 当使用FTL方法调用表达式时, exec方法将会被调用。形参将会包含FTL方法调用形参的值。exec方法的返回值给出了FTL方法调用表达式的返回值。
3. TemplateMethodModelEx接口扩展了TemplateMethodModel接口。它没有添加任何新方法。事实上这个对象实现这个标记接口是给FTL引擎暗示, 形式参数应该直接以TemplateModel的形式放进java.util.List。否则将会以String形式放入list。
4. 例子
4.1. 新建一个名为FMProgrammingMethod的动态Web工程, 同时添加相关jar包。
4.2. 编写FMFactory.java
package com.fm.util;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import freemarker.template.Configuration;
import freemarker.template.TemplateExceptionHandler;
public class FMFactory {
private final static FMFactory instance = new FMFactory();
private FMFactory() {}
public static FMFactory getInstance() {
return instance;
}
private Map<String, Configuration> map = new ConcurrentHashMap<String, Configuration>();
// 创建单个Configuration实例
public synchronized Configuration getCfg(Object servletContext, String path) {
if(null != map.get(path)) {
return map.get(path);
}
Configuration cfg = new Configuration(Configuration.VERSION_2_3_22);
cfg.setServletContextForTemplateLoading(servletContext, path);
cfg.setDefaultEncoding("utf-8");
cfg.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);
map.put(path, cfg);
return cfg;
}
}
4.3. 编写IndexOfMethod.java
package com.fm.action;
import java.util.List;
import freemarker.template.SimpleNumber;
import freemarker.template.SimpleScalar;
import freemarker.template.TemplateMethodModelEx;
import freemarker.template.TemplateModel;
import freemarker.template.TemplateModelException;
/**
* 返回第一个字符串在第二个字符串第一次出现时的索引位置, 如果第二个字符串中不包含第一个字符串, 则返回-1。
*/
public class IndexOfMethod implements TemplateMethodModelEx {
public TemplateModel exec(List args) throws TemplateModelException {
if (args.size() != 2) {
throw new TemplateModelException("Wrong arguments");
}
return new SimpleNumber(((SimpleScalar) args.get(1)).getAsString().indexOf(((SimpleScalar) args.get(0)).getAsString()));
}
}
4.4. 编写ProgrammingMethod.java
package com.fm.action;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.fm.util.FMFactory;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
public class ProgrammingMethod extends HttpServlet {
private static final long serialVersionUID = 1L;
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
Configuration cfg = FMFactory.getInstance().getCfg(req.getServletContext(), "/WEB-INF/templates");
Template template = cfg.getTemplate("programmingmethod.html");
Map<String, Object> root = new HashMap<String, Object>();
root.put("indexOf", new IndexOfMethod());
Writer out = new OutputStreamWriter(resp.getOutputStream());
try {
template.process(root, out);
} catch (TemplateException e) {
e.printStackTrace();
}
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
4.5. 修改web.xml
4.6. 在/WEB-INF/templates目录下编写programmingmethod.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>程序方法</title>
</head>
<body>
<h2>返回第一个字符串在第二个字符串第一次出现时的索引位置</h2>
"met"在"something"第${indexOf("met", "something")}个位置<br />
<#assign idx = indexOf("foo", "something") />
<#if idx == -1>
"foo"在"something"中没有找到。
<#else>
"foo"在"something"第${idx}个位置
</#if>
</body>
</html>
4.7. 运行项目