如何在Thymeleaf模板中自动高亮动态值?
实现Thymeleaf动态输出值的高亮包裹
可以实现这个需求,核心思路是在变量输出阶段对值进行包裹,同时保留模板中条件判断的原始变量引用,以下是两种可行方案:
方案一:自定义表达式工具类(手动包裹,灵活可控)
- 编写工具类,提供高亮包裹方法:
public class HighlightUtils { public static String highlight(Object value) { if (value == null) { return ""; } return "<span style='background-color: yellow;'>" + value.toString() + "</span>"; } }
- 将工具类注册为Thymeleaf表达式对象,让模板可直接调用:
import org.thymeleaf.context.IExpressionContext; import org.thymeleaf.expression.IExpressionObjectFactory; import java.util.Collections; import java.util.Set; public class HighlightExpressionObjectFactory implements IExpressionObjectFactory { public static final String HL_OBJECT_NAME = "hl"; @Override public Set<String> getAllExpressionObjectNames() { return Collections.singleton(HL_OBJECT_NAME); } @Override public Object buildObject(IExpressionContext context, String name) { if (HL_OBJECT_NAME.equals(name)) { return new HighlightUtils(); } return null; } @Override public boolean isCacheable(String name) { return HL_OBJECT_NAME.equals(name); } }
- 在Spring配置中注册表达式对象工厂:
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.thymeleaf.spring5.SpringTemplateEngine; import org.thymeleaf.spring5.templateresolver.SpringResourceTemplateResolver; @Configuration public class ThymeleafConfig { @Bean public SpringTemplateEngine templateEngine(SpringResourceTemplateResolver resolver) { SpringTemplateEngine engine = new SpringTemplateEngine(); engine.setTemplateResolver(resolver); engine.addExpressionObjectFactory(new HighlightExpressionObjectFactory()); return engine; } }
- 修改模板,仅在输出时调用高亮方法,条件判断保留原始变量:
<div th:if="${a} == 'a'" th:text="'hello ' + ${#hl.highlight(a)}?${#hl.highlight(b)}:${#hl.highlight(c)}">
这种方式不会影响条件判断逻辑,且能精准控制哪些变量需要高亮。
方案二:自定义处理器(自动包裹,无需修改模板)
如果不想手动修改模板,可以通过自定义Thymeleaf处理器,自动拦截th:text/th:utext属性,修改其表达式为自动包裹变量的形式:
- 编写处理器类处理
th:text:
import org.thymeleaf.context.ITemplateContext; import org.thymeleaf.engine.AttributeName; import org.thymeleaf.model.IProcessableElementTag; import org.thymeleaf.processor.element.AbstractAttributeTagProcessor; import org.thymeleaf.processor.element.IElementTagStructureHandler; import org.thymeleaf.templatemode.TemplateMode; public class HighlightTextProcessor extends AbstractAttributeTagProcessor { private static final String ATTR_NAME = "text"; private static final int PRECEDENCE = 1000; public HighlightTextProcessor(String dialectPrefix) { super(TemplateMode.HTML, dialectPrefix, null, false, ATTR_NAME, true, PRECEDENCE, true); } @Override protected void doProcess(ITemplateContext context, IProcessableElementTag tag, AttributeName attrName, String attrValue, IElementTagStructureHandler handler) { // 替换表达式中的变量引用为高亮包裹形式(简单正则,复杂表达式需用表达式解析器) String processedExpr = attrValue.replaceAll("\\$\\{([^}]+)\\}", "\\${#hl.highlight($1)}"); handler.setAttribute(attrName, processedExpr); } }
- 编写自定义方言并注册处理器(需同时实现
HighlightUTextProcessor处理th:utext):
import org.thymeleaf.dialect.AbstractProcessorDialect; import org.thymeleaf.processor.IProcessor; import java.util.HashSet; import java.util.Set; public class HighlightDialect extends AbstractProcessorDialect { public static final String NAME = "Highlight Dialect"; public static final String PREFIX = "hl"; public static final int PROCESSOR_PRECEDENCE = 1000; public HighlightDialect() { super(NAME, PREFIX, PROCESSOR_PRECEDENCE); } @Override public Set<IProcessor> getProcessors(String prefix) { Set<IProcessor> processors = new HashSet<>(); processors.add(new HighlightTextProcessor(prefix)); processors.add(new HighlightUTextProcessor(prefix)); return processors; } }
- 在Spring配置中注册方言和表达式对象工厂(同方案一):
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.thymeleaf.spring5.SpringTemplateEngine; import org.thymeleaf.spring5.templateresolver.SpringResourceTemplateResolver; @Configuration public class ThymeleafConfig { @Bean public SpringTemplateEngine templateEngine(SpringResourceTemplateResolver resolver) { SpringTemplateEngine engine = new SpringTemplateEngine(); engine.setTemplateResolver(resolver); engine.addDialect(new HighlightDialect()); engine.addExpressionObjectFactory(new HighlightExpressionObjectFactory()); return engine; } }
- 模板无需修改,处理器会自动将
th:text中的变量替换为高亮包裹形式,条件判断不受影响。
注意事项
- 简单正则替换可能无法处理复杂表达式(如嵌套表达式、方法调用),若需支持复杂场景,需使用Thymeleaf的表达式解析器遍历表达式树进行修改。
- 如果使用
th:utext,需确保高亮后的HTML不会被转义,工具类中的输出无需额外处理,因为th:utext会直接渲染HTML。
内容的提问来源于stack exchange,提问作者Cardinal
相关产品推荐
相关产品推荐

