springboot 学习 —— springboot 2.x ,thymeleaf 自定义 select 标签
Posted 猎人在吃肉
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了springboot 学习 —— springboot 2.x ,thymeleaf 自定义 select 标签相关的知识,希望对你有一定的参考价值。
1、添加依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
2、注册自定义标签类
import java.util.HashSet;
import java.util.Set;
import org.springframework.stereotype.Component;
import org.thymeleaf.dialect.AbstractProcessorDialect;
import org.thymeleaf.processor.IProcessor;
import org.thymeleaf.standard.StandardDialect;
/**
* 类说明:自定标签注册类
*/
@Component
public class CustomLabel extends AbstractProcessorDialect
/**
* 定义方言名称
*/
private static final String NAME="系统自定义标签";
/**
* 定义方言属性
*/
private static final String PREFIX="bm";
protected CustomLabel()
super(NAME, PREFIX, StandardDialect.PROCESSOR_PRECEDENCE);
@Override
public Set<IProcessor> getProcessors(final String dialectPrefix)
final Set<IProcessor> processor=new HashSet<>();
processor.add(new CustomLabelSelect(PREFIX)); // <bm:select>标签
// 如果有多个标签时,在下面添加
//processor.add(new CustomLabelSelect(PREFIX));
return processor;
3、自定义标签实现类
import java.util.ArrayList;
import java.util.List;
import cn.hutool.core.util.StrUtil;
import com.bjifia.tousu.common.utils.SpringContextHolder;
import com.bjifia.tousu.modules.service.SysDictService;
import com.bjifia.tousu.modules.service.impl.SysDictServiceImpl;
import com.bjifia.tousu.modules.vo.SysDictShowVO;
import org.apache.commons.lang3.StringUtils;
import org.springframework.util.CollectionUtils;
import org.thymeleaf.context.ITemplateContext;
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.Expression;
import org.thymeleaf.standard.expression.StandardExpressionParser;
import org.thymeleaf.templatemode.TemplateMode;
import org.unbescape.html.HtmlEscape;
/**
* 类说明:自定义select标签,使用方法:
* <pre>
* <bm:select class="" id="testSelect" name="testSelect" dictType="字典类型" headerLabel="请选择" headerValue="" th:value="$xxx.xxx"></bm:select>
* </pre>
*/
public class CustomLabelSelect extends AbstractElementTagProcessor
private static final String TAG_NAME = "select";//标签名 select 这个玩意就是 自定义标签的 : select, 应该是可以定义多个标签
private static final int PRECEDENCE = 1000;//优先级
public CustomLabelSelect(String dialectPrefix)
super(TemplateMode.HTML, // 此处理器将仅应用于HTML模式
dialectPrefix, // 要应用于名称的匹配前缀
TAG_NAME, // 标签名称:匹配此名称的特定标签
true, // 没有应用于标签名的前缀
null, // 无属性名称:将通过标签名称匹配
false, // 没有要应用于属性名称的前缀
PRECEDENCE// 优先(内部方言自己的优先
);
@Override
protected void doProcess(ITemplateContext context, IProcessableElementTag tag,
IElementTagStructureHandler structureHandler)
//1、创建模型
IModelFactory modelFactory = context.getModelFactory();
IModel model = modelFactory.createModel();
//2、创建模型元素 <select>
IOpenElementTag openElementTag = createModelElement(tag,modelFactory);
model.add(openElementTag);//<select>
// 3、组装 options
List<String> options=createOptions(context,tag);
model.add(modelFactory.createText(HtmlEscape.unescapeHtml(String.join("\\n", options))));
//4、关闭</select>
model.add(modelFactory.createCloseElementTag("select"));
//5、替换前面的标签
structureHandler.replaceWith(model, false);
/**
* 添加模型元素
* @param tag
* @param modelFactory
* @return
*/
private IOpenElementTag createModelElement(IProcessableElementTag tag, IModelFactory modelFactory)
String classValue = tag.getAttributeValue("class");
String id = tag.getAttributeValue("id");
String name = tag.getAttributeValue("name");
String style = tag.getAttributeValue("style");
String disabled = tag.getAttributeValue("disabled");
IOpenElementTag openElementTag = modelFactory.createOpenElementTag("select", "class", classValue);
if (!StringUtils.isEmpty(id))
openElementTag=modelFactory.setAttribute(openElementTag, "id", id);
if (!StringUtils.isEmpty(name))
openElementTag=modelFactory.setAttribute(openElementTag, "name", name);
if (!StringUtils.isEmpty(style))
openElementTag=modelFactory.setAttribute(openElementTag, "style", style);
if (!StringUtils.isEmpty(disabled))
openElementTag=modelFactory.setAttribute(openElementTag, "disabled", disabled);
return openElementTag;
/**
* 组装 options
* @param context
* @param tag
* @return
*/
private List<String> createOptions(ITemplateContext context,IProcessableElementTag tag)
//1、select的option
List<String> options=new ArrayList<>();
//2、设置默认值
String defaultHtml = addDefault(tag);
if (StringUtils.isNotBlank(defaultHtml))
options.add(0,defaultHtml);
//3、根据字典类型获取数据,如果有value值,则默认选中
String ptionHtml = getDictDateByType(tag,context);
options.add(ptionHtml);
return options;
/**
* 添加默认值
* @param tag
* @return
*/
private String addDefault(IProcessableElementTag tag)
String headerLabel = tag.getAttributeValue("headerLabel");
String headerValue = tag.getAttributeValue("headerValue");
StringBuilder sb = new StringBuilder("");
if (!StringUtils.isEmpty(headerLabel))
sb.append("\\n<option value='" + headerValue + "' >");
sb.append(headerLabel + "</option>");
return sb.toString();
/**
* 根据字典类型获取数据
* @param tag
* @param context
* @return
*/
private String getDictDateByType(IProcessableElementTag tag, ITemplateContext context)
// select 中增加了 dictType 属性,用其值 从缓存、、配置、或数据库 中获取数据。
String dictType = tag.getAttributeValue("dictType");
if (StringUtils.isEmpty(dictType))
return "";
String value = tag.getAttributeValue("th:value");
Object executeExpression = null;
if (!StringUtils.isEmpty(value))
// 执行 th:value ,得到其值
executeExpression = executeExpression(value, context);
// 重点说明:
// 这块是从缓存、配置文件 或者 数据库 等中,查询得到数据,用来组装 option 标签
SysDictService sysDictService=SpringContextHolder.getBean(SysDictServiceImpl.class);
List<SysDictShowVO> dicts = sysDictService.getListByKey(StrUtil.trim(dictType));
if (CollectionUtils.isEmpty(dicts))
return "";
// option 标签组装
StringBuilder sb = new StringBuilder();
for (int i = 0, len = dicts.size(); i < len; i++)
SysDictShowVO sysDictShowVO = dicts.get(i);
if (executeExpression != null && executeExpression.toString().equals(sysDictShowVO.getDictValue()))
sb.append("<option value='" +sysDictShowVO.getDictValue() + "' selected=\\"selected\\">");
else
sb.append("<option value='" +sysDictShowVO.getDictValue() + "' >");
sb.append(sysDictShowVO.getDictName() + "</option>\\n");
return sb.toString();
/**
* 执行自定义标签中的表达式
* @param value
* @param context
* @return
*/
private Object executeExpression(String value, ITemplateContext context)
StandardExpressionParser parser = new StandardExpressionParser();
Expression parseExpression = parser.parseExpression(context, value);
Object execute = parseExpression.execute(context);
return execute;
4、使用
<!-- 没有 th:value ,与普通的select基本一样 -->
<bm:select id="status" name="status" dictType="status_type"
headerLabel="请选择" headerValue="" class="form-control" ></bm:select>
<!-- 如有 th:value 时,则可以选中option中与之匹配的值 -->
<bm:select id="status" name="status" dictType="status_type" th:value="$ companys['status'] "
headerLabel="请选择" headerValue="" class="form-control" ></bm:select>
解析后的源代码:
5、转载
thymeleaf 自定义标签,解析表达式:https://blog.csdn.net/z793397795/article/details/97389063
以上是关于springboot 学习 —— springboot 2.x ,thymeleaf 自定义 select 标签的主要内容,如果未能解决你的问题,请参考以下文章