Thymeleaf:用 <br> 替换换行符

Thymeleaf: replace newline characters with <br>

我有一个可能包含换行符的字段 (<textarea name="desc" />),我想将它们替换为 HTML 对应的字段:<br />。我怎样才能做到这一点?我正在使用 Thymeleaf 2.1.4.RELEASE.

As in JSP,简单明了用起来不行

${#strings.replace(desc, '\n', '<br />')}

至少有两个问题:

  • '\n' 被底层表达式语言(在我的例子中是 SpEL,因为我使用 Spring MVC)视为由两个单独字符组成的字符串文字:'\' 和 'n' 而不是单个换行符
  • 由于 Thymeleaf 底层 XML 解析器不允许将 <> 放入表达式
  • 中,因此抛出异常

我找到的第一个问题的解决方案是在控制器中设置换行符并将其传递给视图。

要解决第二个问题,您需要使用 &lt; 而不是 <&gt; 而不是 >。还要记住,这意味着使用 th:utext 而不是 th:text

// in controller:
model.addAttribute("newLineChar", '\n');

// in view
${#strings.replace(desc, newLineChar, '&lt;br /&gt;')}

如果您使用 Thymeleaf + Spring(这意味着 Thymeleaf 将使用 SpEL 而不是 OGNL),您也可以使用 SpEL T operator。这样您就不必声明控制器中的换行符变量,但请注意,在这种情况下,换行符分隔符会因您的应用 运行 on:

的操作系统而异
${#strings.replace(desc, T(System).getProperty('line.separator'), '&lt;br /&gt;')}

我最终要使用的是上面的组合 + Apache StringUtils 定义 public static final String LF = "\n";:

${#strings.replace(desc, T(org.apache.commons.lang3.StringUtils).LF, '&lt;br /&gt;')}

可以使用自定义方言和属性处理器来完成此操作,而无需大量内联 SpEl 或 hack。

创建自定义属性处理器

public class NewlineAttrProcessor extends AbstractUnescapedTextChildModifierAttrProcessor
{
    public NewlineAttrProcessor()
    {
        super("nl2br");
    }

    @Override
    protected String getText(Arguments arguments, Element element, String attributeName)
    {
        final Configuration configuration = arguments.getConfiguration();

        final IStandardExpressionParser parser =
            StandardExpressions.getExpressionParser(configuration);

        final String attributeValue = element.getAttributeValue(attributeName);

        final IStandardExpression expression =
            parser.parseExpression(configuration, arguments, attributeValue);

        final String value = (String)expression.execute(configuration, arguments);
        return StringUtils.replace(value, "\n", "<br />");
    }

    @Override
    public int getPrecedence()
    {
        return 10000;
    }
}

您必须扩展 AbstractUnescapedTextChildModifierAttrProcessor 处理器,否则您将获得 <br /> 的 html 实体标签,而您实际上不会得到换行符。

创建自定义方言

要实现自定义方言,您需要这样的方言 class:

public class MyCustomDialect extends AbstractDialect
{
    @Override
    public String getPrefix()
    {
        return "cd";
    }

    @Override
    public Set<IProcessor> getProcessors()
    {
        final Set<IProcessor> processors = new HashSet<>();
        processors.add(new NewlineAttrProcessor());
        return processors;
    }
}

getPrefix 方法 return 值是您用来调用您创建的任何自定义处理器的值。例如,Thymeleaf 使用 th。我们在上面实现的自定义处理器正在寻找 nl2br 因此要调用它,您可以使用 cd:nl2br 属性而不是 th:text.

正在注册您的新方言

在您的主要 class 中,您只需要创建一个 @Bean 即可 return 您的方言 class.

的新实例
@SpringBootApplication
public class MyApplication {

    public static void main(String[] args) {
        SpringApplication.run(MyApplication.class, args);
    }

    @Bean
    public MyCustomDialect myCustomDialect()
    {
        return new MyCustomDialect();
    }
}

使用自定义处理器

最后,在您的模板文件中,您将有一个像这样的 HTML 标签:

<div cd:nl2br="${myObject.myField}">MY MULTILINE FIELD</div>

有关实现自定义方言的更详尽指南,我推荐 Thymeleaf 文档:

正如 dominik 所述,换行的 \n 不起作用。但是,您可以使用 &#10;.

${#strings.replace(desc,'&#10;','&lt;br&gt;')}

或者使用转义来防止代码注入:

${#strings.replace(#strings.escapeXml(desc),'&#10;','&lt;br&gt;')}