使用 thymeleaf +spring 创建自定义标签(就像 JSP 一样) [英] using thymeleaf +spring to create custom tags (just like JSP)

查看:36
本文介绍了使用 thymeleaf +spring 创建自定义标签(就像 JSP 一样)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用 Thymeleaf 创建自定义标签,就像在 JSP 中一样.我现在拥有的标签是:

<select th:include="fragments/combobox :: combobox_beans (beans=${@accountService.getAccounts()},innerHTML='id,description,currency', separator='-',dumbHtmlName='账户列表', name='sender' )" th:remove="tag"></select>

目的只是定义 bean 列表、要在屏幕上显示的 bean 的属性、它们之间的分隔符、显示为原生模板时的默认值以及我们在此处处理的原始 bean 的属性名称.

combobox.html:

<select th:field="*{__${name}__}" class="combobox form-control" required="required"><option th:each="obj : ${beans}" th:with="valueAsString=${#strings.replace( 'obj.' + innerHTML, ',', '+'' __${separator}__''+ 对象.')}"th:value="${obj}" th:text="${valueAsString}" ><p th:text="${dumbHtmlName}" th:remove="tag"></p></选项></选择>

我需要选项标签的文本基于片段的 innerHTML 属性 (innerHTML='id,description,devise') 中设置的属性.我最终可以选择此文本:

而不是想要的结果

我知道这是由于使用了 Strings 库导致的字符串.有没有办法 Thymeleaf 可以重新评估这个字符串以再次被理解为一个对象?

也许在这种情况下使用字符串库是错误的......也许我需要使用 th:each 来将每个 bean 作为对象处理并读取其属性,但又一次,如何只获取innerHtml中指定的属性?

有人对此有解决方案或变通方法吗?
谢谢.

解决方案

如果有一种方法可以单独在 Thymeleaf/Spring 表达式中做您想做的事,那肯定非常复杂且冗长,而且可能会很痛苦阅读.

更简单的方法是将自定义实用程序对象添加到表达式上下文中.只需要很少的代码.这个答案显示了它.

然后,您需要将新方言作为附加方言添加到 Spring xml 配置中的模板引擎中.假设您有一个相当标准的 Spring 配置,它应该与此类似.

<property name="templateResolver" ref="templateResolver"/><属性名称="additionalDialects"><设置><bean class="mypackage.MyUtilityDialect"/></set></属性></bean>

现在是实用程序对象

您想要的是按名称从对象中获取属性,并将它们的值与分隔符组合在一起.似乎属性名称列表可以是任意大小.要按名称访问属性,最方便的是使用像 Apache beanutils.

使用 Java 8 流库、lambdas 和 Beanutils,您的自定义实用程序对象可能看起来像这样:

公共类 MyUtil {public String joinProperties(Object obj, List props, String separator){返回 props.stream().map(p -> PropertyUtils.getProperty(obj,p).toString()).collect(Collectors.joining(separator))}}

然后,当您将方言添加到 SpringTemplateEngine 时,您可以调用您的实用程序:

th:with="valueAsString=${#myutils.joinProperties(obj,properties,separator)}"

我已经用 properties 替换了你的 innerHTML 参数,它是一个 List,因为它更有意义.它本质上是一个属性名称列表,Spring EL 支持内联列表.

您的调用标记应该如下所示.

<select th:include="fragments/combobox :: combobox_beans (beans=${@accountService.getAccounts()}, properties=${ {'id','description','currency'}}, 分隔符=' - ', 哑HtmlName='帐户列表', 姓名='发件人' )" th:remove="tag"></select>

I am trying to use Thymeleaf to create custom tags, just like in JSP. The tag I have now is:

<select th:include="fragments/combobox :: combobox_beans (beans=${@accountService.getAccounts()}, innerHTML='id,description,currency', separator=' - ', dumbHtmlName='List of accounts', name='sender' )" th:remove="tag"></select>

The purpose is just defining the beans list, the properties of the bean to show on screen, the separator between them, the default value when shown as a native template, and the property name of the original bean we are processing here.

combobox.html:

<div th:fragment="combobox_beans (beans, innerHTML, separator, dumbHtmlName, name)">
<select th:field="*{__${name}__}" class="combobox form-control" required="required">
    <option th:each="obj : ${beans}" th:with="valueAsString=${#strings.replace( 'obj.' + innerHTML, ',', '+''  __${separator}__ ''+ obj.')}"
        th:value="${obj}" th:text="${valueAsString}" >            
        <p th:text="${dumbHtmlName}" th:remove="tag"></p>
    </option>
</select>

I need the text of the option tag to be based on the properties set in innerHTML property (innerHTML='id,description,devise') of the fragment. I end up having an option with this text:

<option value="...">obj.id+' - '+ obj.description+' - '+ obj.currency</option>

instead of the desired result

<option value="...">2 - primary - USD</option>

I know this is due to the usage of Strings library which results in a string. Is there a way Thymeleaf can re-evaluate this string to be understood as an object again?

Maybe using strings library is just so wrong in this situation... Maybe I need to use a th:each to process the each bean as an object and read its properties, but yet again, how to only get the properties specified in innerHtml ?

Anyone has a solution or work-around for this ?
thanks.

解决方案

If there is a way to do what you want in Thymeleaf/Spring expression alone, it most certainly very complicated and long winded, plus it would probably be a pain to read.

The easier way to do it would be add a custom utility object to the expression context. Very little code is needed. This answer shows it.

Then you need to add you new dialect as additional dialect to the template engine in your Spring xml config. Assuming you have a fairly standard Spring config, it should be similar to this.

<bean id="templateEngine" class="org.thymeleaf.spring4.SpringTemplateEngine">
  <property name="templateResolver" ref="templateResolver" />
  <property name="additionalDialects">
    <set>
      <bean class="mypackage.MyUtilityDialect" />
    </set>
  </property>
</bean>

Now for the utility object

What you want is to get the properties from objects by name, and combine their values with a separator. It seems that the list of property names can be of any size. For accessing properties by name, the most convenient thing is to use a library like the Apache beanutils.

Your custom utility object could the look something like this using the Java 8 streams library, lambdas and Beanutils:

public class MyUtil {

  public String joinProperties(Object obj, List<String> props, String separator){
    return props.stream()
          .map(p -> PropertyUtils.getProperty(obj,p).toString())
          .collect(Collectors.joining(separator))
  }
}

Then when you add you dialect to SpringTemplateEngine you can call your utility:

th:with="valueAsString=${#myutils.joinProperties(obj,properties,separator)}"

I have replaced you innerHTML parameter with properties which is a List<String>, because it makes more sense. It is essentially a list of property names, and Spring EL supports inline lists.

Your calling tag should then look like this.

<select th:include="fragments/combobox :: combobox_beans (beans=${@accountService.getAccounts()}, properties=${ {'id','description','currency'} }, separator=' - ', dumbHtmlName='List of accounts', name='sender' )" th:remove="tag"></select>

这篇关于使用 thymeleaf +spring 创建自定义标签(就像 JSP 一样)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆