FreeMarker自定义标签
一.实现思路/出发点(需求)
定义模板html,后台根据正则表达式进行筛选模板。
对定义的标签分类处理(单标签与列表标签):
单标签:查询对应表,对应字段进行返回
列表标签:自定义标签,根据标签内容生成sql,进行查询,返回列表
二.自定义标签的方法
引自:https://blog.csdn.net/m0_53611007/article/details/119651082
- 使用 宏定定义标签
- 实现 TemplateDirectiveModel的 execute() 方法
注:本文使用第二种方法,利用java编写
三.编写模板static.html
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>${html_title}</title>
</head>
<body>
<h1 align="center">${global.title}</h1>
<h1 align="center">${global.cfg_description}</h1>
<h1 align="center">${global.cfg_keywords}</h1>
<table border="1" style="margin: auto" width="1000px">
<tr style="height: 30px">
<td>序号</td>
<td>姓名</td>
<td>生日</td>
<td>性别</td>
</tr>
<!--content_list,orderbychar...等为自定义参数,更改的同时需要更改后台代码-->
<@content_list orderbychar="birth" order="desc" tableName="student" count=10>
<!--list为自定义参数,需与后台同步,更改需同步更改-->
<#if list?exists && (list?size>0)>
<#list list as stu>
<tr>
<td>${stu.sid}</td>
<td>${stu.name}</td>
<td>${stu.birth}</td>
<td>${stu.sex}</td>
</tr>
</#list>
</#if>
</@content_list>
</table>
</body>
</html>
四.读取static.html,筛选标签
import org.springframework.core.io.ClassPathResource;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* @author quanjl
* @date 2022/10/27
* 描述:读取html
*/
public class ReadHtmlUtil {
public static String GLOBAL_RULE = "\\{global.*\\}";
public static String LIST_RULE = "<@content_list.*>";
public static Map<String, List<String>> toHtmlString(String file) throws IOException {
List<String> liststr = new ArrayList<>();
List<String> list = new ArrayList<>();
Map<String, List<String>> stringListMap = new HashMap<>();
if (file==""){
file = new ClassPathResource("html/" + "static.html").getFile().toString();
}
// 读取文件
FileInputStream fis=new FileInputStream(file);
InputStreamReader isr=new InputStreamReader(fis, "UTF-8");
BufferedReader br = new BufferedReader(isr);
String line="";
// 逐行读取
while ((line=br.readLine())!=null) {
// 正则表达式验证每行
// 验证global
Pattern pattern = Pattern.compile(GLOBAL_RULE);
Matcher matcher = pattern.matcher(line);
while (matcher.find()){
// System.out.println("符合条件的标签有:"+matcher.group());
liststr.add(matcher.group());
}
// 验证list
Matcher matcher_list = Pattern.compile(LIST_RULE).matcher(line);
while (matcher_list.find()){
System.out.println(matcher_list.group());
list.add(matcher_list.group());
}
}
stringListMap.put("global", liststr);
stringListMap.put("list", list);
br.close();
isr.close();
fis.close();
return stringListMap;
}
}
五.ContentDirective类实现TemplateDirectiveModel
public class ContentDirective implements TemplateDirectiveModel {
@Autowired
private GlobalServiceImpl globalService;
//排序字段
private static final String PARAM_ORDERBYCHAR = "orderbychar";
//排序顺序
private static final String PARAM_ORDER = "order";
//表名
private static final String PARAM_TABLE_NAME = "tableName";
//条数
private static final String PARAM_COUNT = "count";
@Override
public void execute(Environment env, Map params,TemplateModel[] loopVars,
TemplateDirectiveBody body) throws TemplateException, IOException {
System.out.println("----------------正在访问:com.example.demo.utils.ContentDirective.execute方法");
if(body==null){
throw new TemplateModelException("null body");
}else{
List<Student> students = new ArrayList<>();
/** 表名、排序字段、排序顺序*/
String tableName = getString(PARAM_TABLE_NAME, params);
String orderbychar = getString(PARAM_ORDERBYCHAR, params)==null?"id":getString(PARAM_ORDERBYCHAR, params);
String order = getString(PARAM_ORDER, params)==null?"desc":getString(PARAM_ORDER, params);
int count = getInt(PARAM_COUNT, params)==null?10:getInt(PARAM_COUNT, params);
//接收到参数之后可以根据做具体的操作,然后将数据再在页面中显示出来。
if (tableName!=null && orderbychar!=null && order!=null){
// 根据html页面标签内参数,生成sql语句
String sql = "select * from "+tableName+" order by "+orderbychar+" "+order+" limit 0,"+count;
// 调用查询
students = globalService.executeSql(sql);
}
//接收到参数之后可以根据做具体的操作,然后将数据再在页面中显示出来。
if(students!=null){
env.setVariable("list", DEFAULT_WRAPPER.wrap(students));
}
Writer out = env.getOut();
body.render(out);
}
}
/**
* 获取String类型的参数的值
* @param paramName
* @param paramMap
* @return
* @throws TemplateModelException
*/
public static String getString(String paramName, Map<String, TemplateModel> paramMap) throws TemplateModelException{
TemplateModel model = paramMap.get(paramName);
if(model == null || model.toString().length()==0){
return null;
}
if(model instanceof TemplateScalarModel){
return ((TemplateScalarModel)model).getAsString();
}else if (model instanceof TemplateNumberModel) {
return ((TemplateNumberModel)model).getAsNumber().toString();
}else{
throw new TemplateModelException(paramName);
}
}
/**
*
* 获得int类型的参数
* @param paramName
* @param paramMap
* @return
* @throws TemplateModelException
*/
public static Integer getInt(String paramName, Map<String, TemplateModel> paramMap) throws TemplateModelException{
TemplateModel model = paramMap.get(paramName);
if(model==null || model.toString().length()==0){
return null;
}
if(model instanceof TemplateScalarModel){
String str = ((TemplateScalarModel)model).getAsString();
try {
return Integer.valueOf(str);
} catch (NumberFormatException e) {
throw new TemplateModelException(paramName);
}
}else if(model instanceof TemplateNumberModel){
return ((TemplateNumberModel)model).getAsNumber().intValue();
}else{
throw new TemplateModelException(paramName);
}
}
}
六.控制层代码
public String b() {
try {
//创建一个合适的Configration对象
Configuration configuration = new Configuration();
// 模板路径
configuration.setDirectoryForTemplateLoading(new File("E:\\xxx\xxx\xxx\\html"));
configuration.setObjectWrapper(new DefaultObjectWrapper());
// 设置utf-8,防止乱码
configuration.setDefaultEncoding("UTF-8");
// 获取模版。
Template template = configuration.getTemplate("static.html");
/**
* stringList集合,存放html内筛选出的字符串:
* 例:${global.title}
*/
Map<String, List<String>> stringListMap = ReadHtmlUtil.toHtmlString("");
if (stringListMap.size()>0){
// 创建map,存储页面所需数据
Map<String, Object> paramMap = new HashMap<String, Object>();
Global global = new Global();
String tableName = "";// global:表名
String fieldName = "";// title:字段名
String labelName = "";// 标签名称<@xxx ....></@xxx>
for (String str:stringListMap.get("global")){
/**
* StringUtils使用commons-lang3包进行截取
* tableName表名称:global
* fieldName字段名称:title
*/
tableName = StringUtils.substringBetween(str, "{", ".");
fieldName = StringUtils.substringBetween(str, ".", "}");
// str = str.substring(13,str.length()-2);
String ss = globalService.getString(fieldName);
if (fieldName.equals("title"))
global.setTitle(ss);
if (fieldName.equals("cfg_description"))
global.setCfg_description(ss);
if (fieldName.equals("cfg_keywords"))
global.setCfg_keywords(ss);
}
paramMap.put(tableName, global);
// <@list tableName="student" orderbychar="birth" order="desc">标签
for (String str:stringListMap.get("list")){
// 标签名称
labelName = StringUtils.substringBetween(str, "<@", " ");
System.out.println(labelName);
}
paramMap.put(labelName, new ContentDirective());
paramMap.put("html_title","FreeMarker静态页面");
// 写入文件
Writer writer = new OutputStreamWriter(new FileOutputStream("E:\\xxx\\xxx\\xxx\\html\\success.html"),"UTF-8");
template.process(paramMap, writer);
}
} catch (IOException e) {
e.printStackTrace();
} catch (TemplateException e) {
e.printStackTrace();
}
return "生成成功!";
}
七.生成的html(success.html)
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>FreeMarker静态页面</title>
</head>
<body>
<h1 align="center">百度一下,你就知道</h1>
<h1 align="center">百度百度百度</h1>
<h1 align="center">1321</h1>
<table border="1" style="margin: auto" width="1000px">
<tr style="height: 30px">
<td>序号</td>
<td>姓名</td>
<td>生日</td>
<td>性别</td>
</tr>
<!--content_list,orderbychar...等为自定义参数,更改的同时需要更改后台代码-->
<!--list为自定义参数,需与后台同步,更改需同步更改-->
<tr>
<td>1</td>
<td>张磊</td>
<td>2101</td>
<td>男</td>
</tr>
<tr>
<td>3</td>
<td>赵胜</td>
<td>1111</td>
<td>男</td>
</tr>
<tr>
<td>2</td>
<td>韩梅梅</td>
<td>0801</td>
<td>女</td>
</tr>
<tr>
<td>4</td>
<td>王力</td>
<td>0202</td>
<td>男</td>
</tr>
</table>
</body>
</html>
八.数据库所用表
1.global表
DROP TABLE IF EXISTS `global`;
CREATE TABLE `global` (
`id` int(11) NOT NULL,
`title` varchar(255) DEFAULT NULL,
`cfg_description` varchar(255) DEFAULT NULL,
`cfg_keywords` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records of global
-- ----------------------------
INSERT INTO `global` VALUES ('1', '百度一下,你就知道', '百度百度百度', '1321');
2.student表
DROP TABLE IF EXISTS `student`;
CREATE TABLE `student` (
`sid` varchar(255) NOT NULL,
`name` varchar(255) DEFAULT NULL,
`birth` varchar(255) DEFAULT NULL,
`sex` varchar(255) DEFAULT NULL,
PRIMARY KEY (`sid`),
KEY `name` (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records of student
-- ----------------------------
INSERT INTO `student` VALUES ('1', '张磊', '2101', '男');
INSERT INTO `student` VALUES ('2', '韩梅梅', '0801', '女');
INSERT INTO `student` VALUES ('3', '赵胜', '1111', '男');
INSERT INTO `student` VALUES ('4', '王力', '0202', '男');
目前实现最简单需求,记录一下,后续再继续改