thymeleaf+Springboot实现自定义标签
在项目开发中,有一些组件不能满足我们快速开发的要求,我们需要封装一些组件来更加的便利我们。比如,我们可以封装一个下拉框组件,只要开发人员只有引用这个组件的标签,就能出现效果,而不用再去请求url,渲染等等。以下我们以一个select下拉组件为例
1、我们先自定义一个类:MqInputTagProcessor 并继承了AbstractElementTagProcessor父类
package com.www.baidu.com.web.tag.processor;
import org.apache.commons.lang.StringUtils;
import org.thymeleaf.context.ITemplateContext;
import org.thymeleaf.exceptions.TemplateProcessingException;
import org.thymeleaf.model.IModel;
import org.thymeleaf.model.IModelFactory;
import org.thymeleaf.model.IOpenElementTag;
import org.thymeleaf.model.IProcessableElementTag;
import org.thymeleaf.processor.element.AbstractElementTagProcessor;
import org.thymeleaf.processor.element.IElementTagStructureHandler;
import org.thymeleaf.standard.expression.IStandardExpression;
import org.thymeleaf.standard.expression.IStandardExpressionParser;
import org.thymeleaf.standard.expression.StandardExpressionParser;
import org.thymeleaf.templatemode.TemplateMode;
import java.util.HashMap;
import java.util.Map;
public class MqInputTagProcessor extends AbstractElementTagProcessor
{
private final static String TAG_NAME = "definitionSelect";
private final static int PRECEDENCE = 9999;
/**
* Description:
* @param dialectPrefix
*/
public MqInputTagProcessor(String dialectPrefix)
{
super(TemplateMode.HTML, // 模板类型
dialectPrefix, // 要应用于名称的匹配前缀
TAG_NAME, // 标签名称
true, // 将标签前缀应用于标签名称
null, // 无属性名称:将通过标签名称匹配
false, // 没有要应用于属性名称的前缀
PRECEDENCE // 优先级
);
}
@Override
protected void doProcess(ITemplateContext context, IProcessableElementTag tag,
IElementTagStructureHandler structureHandler)
{
// 获取我们html中封装的标签上的各个属性值,也可以用tag.getAttributeMap()来获取
String mqNameValue = tag.getAttributeValue("name");
String mqValue = tag.getAttributeValue("value");
String mqId = tag.getAttributeValue("id");
String mqClass = tag.getAttributeValue("class");
String mqStyle = tag.getAttributeValue("style");
String value = evaluateExpression(context, mqValue) + "";
IModelFactory modelFactory = context.getModelFactory();
// 模拟从数据库中获取的数据
Map<String, String> strMap = new HashMap<>(16);
strMap.put("zhangsan", "张三");
strMap.put("lisi", "李四");
strMap.put("wangwu", "王五");
strMap.put("zhaoliu", "赵六");
// 创建IModel对象
IModel model = modelFactory.createModel();
// 获得IOpenElementTag对象来构建标签模板
IOpenElementTag openElementTag = modelFactory.createOpenElementTag("select", "class", mqClass);
openElementTag = modelFactory.setAttribute(openElementTag, "style", mqStyle);
openElementTag = modelFactory.setAttribute(openElementTag, "id", mqId);
openElementTag = modelFactory.setAttribute(openElementTag, "value", value);
openElementTag = modelFactory.setAttribute(openElementTag, "name", mqNameValue);
// 把IOpenElementTag对象构建的标签模板放入model中
model.add(openElementTag);
// 构建select下的option标签
model.add(modelFactory.createOpenElementTag("option value=''"));
model.add(modelFactory.createText("选择类别"));
// 构建结束标签
model.add(modelFactory.createCloseElementTag("option"));
// 创建option
strMap.forEach((k, v) -> {
IOpenElementTag openElementTag1 = modelFactory.createOpenElementTag(String.format("option value='%s'", k));
if (k.equals(value))
{
openElementTag1 = modelFactory.setAttribute(openElementTag1, "selected", "true");
}
model.add(openElementTag1);
model.add(modelFactory.createText(v));
model.add(modelFactory.createCloseElementTag("option"));
modelFactory.createOpenElementTag("option");
});
model.add(modelFactory.createCloseElementTag("select"));
// 指示引擎用指定的模板替换整个元素
structureHandler.replaceWith(model, false);
}
private Object evaluateExpression(ITemplateContext context, String expression) throws TemplateProcessingException
{
if (StringUtils.isEmpty(expression))
{
return null;
}
final IStandardExpressionParser parser = new StandardExpressionParser();
final IStandardExpression evaluableExpression = parser.parseExpression(context, expression);
return evaluableExpression.execute(context);
}
}
2、定义方言
package com.xxxx.web.tag.dialect;
import com.skywares.web.tag.processor.*;
import org.thymeleaf.dialect.AbstractProcessorDialect;
import org.thymeleaf.processor.IProcessor;
import java.util.HashSet;
import java.util.Set;
public class StDialect extends AbstractProcessorDialect
{
private static final int PROCESSOR_PRECEDENCE = 1000;// 方言(标签)优先级
private static final String DIALECT_NAME = "ai Dialect";// 方言(标签)名称
private static final String PREFIX = "ai";// 方言(标签)前缀
protected StDialect(String name, String prefix, int processorPrecedence)
super(name, prefix, processorPrecedence);
}
public StDialect()
{
// 我们将设置此方言与“方言处理器”优先级相同
// 标准方言, 以便处理器执行交错。
super(DIALECT_NAME, PREFIX, PROCESSOR_PRECEDENCE);
}
/**
* 注册标签
*/
@Override
public Set<IProcessor> getProcessors(String dialectPrefix)
{
return createStandardProcessorsSet(dialectPrefix);
}
public static Set<IProcessor> createStandardProcessorsSet(final String dialectPrefix)
{
Set<IProcessor> processors = new HashSet<IProcessor>();
processors.add(new DefinitionsSelectTagProcessor(dialectPrefix));
return processors;
}
}
3、界面上的使用:
// qo为回显的Map集合,itemId为key
<ai:definitionSelect id="oidjf" name="stuNo" th:value="{qo['stuNo']}" />
4、实现的效果: