之前在項目中使用了Freemarker的自定義指令和方法,感覺挺方便的,記錄下,防止遺忘。Talk is cheap, show the code!
Freemarker模板
添加Freemarker的maven依賴
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>2.3.28</version>
</dependency>
hello.ftl
模板包含一個自定義手機號碼隱位的方法和一個菜單展示的自定義指令
<html>
<head>
<title>你好,${username}</title>
</head>
<body>
手機號碼:${phoneMask(phone, 2, 4)}
<@menus method="menus"; showAll>
<#if showAll>
<#if menus?? && menus?size gt 0>
<#list menus as item>
<h1>${item}</h1>
</#list>
</#if>
<#else>
沒有可用菜單
</#if>
</@menus>
</body>
</html>
自定義指令
自定義一個菜單展示指令:MenusTagDirective.java
import java.io.IOException;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import freemarker.core.Environment;
import freemarker.template.Configuration;
import freemarker.template.DefaultObjectWrapperBuilder;
import freemarker.template.TemplateBooleanModel;
import freemarker.template.TemplateDirectiveBody;
import freemarker.template.TemplateDirectiveModel;
import freemarker.template.TemplateException;
import freemarker.template.TemplateModel;
public class MenusTagDirective implements TemplateDirectiveModel {
/**
* @param environment 環境變量(實現複雜功能時可能會用)
* @param map 在.ftl模板中使用自定義指令傳的參數(key-value形式)
* @param templateModels 返回值,數組形式
* @param templateDirectiveBody 指令內容
* @throws TemplateException
* @throws IOException
*/
@Override
public void execute(Environment environment, Map map, TemplateModel[] templateModels, TemplateDirectiveBody templateDirectiveBody) throws TemplateException, IOException {
DefaultObjectWrapperBuilder builder = new DefaultObjectWrapperBuilder(Configuration.VERSION_2_3_28);
if (map.containsKey("method") && "menus".equalsIgnoreCase(map.get("method").toString())) {
// 這裏直接new一個菜單列表,真實環境可以自己獲取
List<String> menusList = new LinkedList<>();
menusList.add("用戶管理");
menusList.add("角色管理");
menusList.add("權限管理");
menusList.add("系統設置");
environment.setVariable("menus", builder.build().wrap(menusList));
templateModels[0] = TemplateBooleanModel.TRUE;
}else{
templateModels[0] = TemplateBooleanModel.FALSE;
}
templateDirectiveBody.render(environment.getOut());
}
}
自定義方法
自定義手機號碼隱位的method,繼承自TemplateMethodModelEx,以前TemplateMethodModel被Deprecated。
import java.util.List;
import freemarker.template.TemplateMethodModelEx;
import freemarker.template.TemplateModelException;
/**
* 手機隱位
* ${phoneMask(phone, beginIdx, suffixIdx)}
*/
public class PhoneMask implements TemplateMethodModelEx {
@Override
public Object exec(List args) throws TemplateModelException {
if (args.size() != 3) {
throw new TemplateModelException(
"the field number of phoneMask is wrong");
}
try {
String phoneNum = args.get(0).toString();
int beginIdx = Integer.valueOf(args.get(1).toString().trim());
int suffixIdx = Integer.valueOf(args.get(1).toString().trim());
// 這裏沒有對begin和suffix做嚴格校驗
StringBuilder sb = new StringBuilder();
int size = phoneNum.length();
if(size > beginIdx + suffixIdx) {
String prefix = phoneNum.substring(0, beginIdx);
String suffix = phoneNum.substring(size - suffixIdx);
String middle = phoneNum.substring(beginIdx, size - suffixIdx).replaceAll(".", "*");
sb.append(prefix).append(middle).append(suffix);
} else {
sb.append(phoneNum);
}
return sb.toString();
} catch (Exception e) {
throw new TemplateModelException(
"phoneMask 處理異常", e);
}
}
}
測試方法
public static void main( String[] args )
{
Configuration cfg = new Configuration(Configuration.getVersion());
try {
// 設置模板位置
cfg.setDirectoryForTemplateLoading(new File("D:\\workspaces\\freemarkerdemo\\src\\main\\resources"));
cfg.setDefaultEncoding("UTF-8");
cfg.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);
// 自定義指令\方法
cfg.setSharedVariable("menus", new MenusTagDirective());
cfg.setSharedVariable("phoneMask", new PhoneMask());
Template temmplate = cfg.getTemplate("hello.ftl");
Map<String, String> map = new HashMap<>();
map.put("username", "admin");
map.put("phone", "13849323456");
StringWriter sw = new StringWriter();
try {
temmplate.process(map,sw);
} catch (TemplateException e) {
e.printStackTrace();
}
System.out.println(sw.toString());
} catch (IOException e) {
e.printStackTrace();
}
}
測試結果
<html>
<head>
<title>你好,admin</title>
</head>
<body>
手機號碼:13*******56
<h1>用戶管理</h1>
<h1>角色管理</h1>
<h1>權限管理</h1>
<h1>系統設置</h1>
</body>
</html>