【问题标题】:Thymeleaf Select Option Performance IssueThymeleaf 选择选项性能问题
【发布时间】:2018-09-29 08:46:39
【问题描述】:

我最近一直在搞乱 Spring MVC 5 和 Thymeleaf 3.0 并且发现了一些奇怪的东西。我已经开始从网站上的教程中实现一个下拉列表,并注意到一些性能问题。如果我使用以下代码,我的页面需要大约 5.5 秒来呈现大约 100 个项目的下拉列表。

<select th:field="*{item}">
    <option th:each="item : ${items}" 
            th:value="${item.getId()}" 
            th:text="${item.getValue()}"></option>
</select>

另一方面,如果我使用以下代码,我的页面会在大约 150 毫秒内呈现。

<div th:each="item : ${items}">
    <span th:text="${item.getId()}"/>
    <span th:text="${item.getValue()}"/>
</div>

我已经遍历了我的控制器中的项目列表并打印了这些值,以查看它们从数据库中获取数据是否有任何减慢,但是从控制器中获取项目是立即发生的。我还尝试在 select 标记中呈现不同的 html 元素以进行测试,即使它不是有效的 html,它仍然可以快速呈现页面。

我唯一一次在页面渲染中遇到极大的延迟是当我在选项的选择标记内使用 th:each 时。 Thymeleaf 是否以不同方式处理选择标签?我认为,如果相同的项目列表,调用相同的方法可以通过 div 循环在 130 毫秒内呈现页面,它应该能够以相当的速度创建选项,而不是花费 5.5 秒。

以前有没有人遇到过这样的问题?我做了一些搜索,发现在 Thymeleaf 中循环存在性能问题,但这些案例有超过 100,000 条记录,其中我的列表大约有 100 项。任何帮助将不胜感激。

更新

我已将问题缩小到在 th:field="*{item}" 上表现不佳。如果我运行以下代码,页面会立即加载。

<select>
    <option th:each="item : ${items}" 
            th:value="${item.getId()}" 
            th:text="${item.getValue()}"></option>
</select>

一旦我尝试使用 th:field="*{item}" 绑定选择,页面会挂起大约 5.5 秒。使用 th:field 进行绑定是否会导致延迟问题?

【问题讨论】:

  • 可能是延迟初始化?
  • 目前我正在通过使用 JPA CrudRepository findAll() 在我的控制器中返回一个列表来获取所有项目,并且模型上的关系是一个带有连接列的@OneToOne,所以一切都应该被初始化。

标签: spring-mvc thymeleaf


【解决方案1】:

我在创建页面时遇到了同样的问题,选择/选项部分花费了一分钟。我的代码有点不同,因为我在表格中有选项,但我认为这并不重要。我的初始代码如下所示:

<tr th:each="scorePart,rowStat : ${song.scoreParts}">
    <td>
        <select th:field="*{scoreParts[__${rowStat.index}__].instrument}">
            <option th:each="i2 : ${allInstruments}"
                    th:value="${i2.id}"
                    th:text="${i2.name}">bla</option>
        </select>
    </td>
    <td> more data... </td>
</tr>

但后来我将 id 添加到字段部分:

<tr th:each="scorePart,rowStat : ${song.scoreParts}">
    <td>
        <select th:field="*{scoreParts[__${rowStat.index}__].instrument.id}">
            <option th:each="i2 : ${allInstruments}"
                    th:value="${i2.id}"
                    th:text="${i2.name}">bla</option>
        </select>
    </td>
    <td> more data... </td>
</tr>

然后一切正常。两种情况的结果相同,只有第二种情况没有延迟。

【讨论】:

    【解决方案2】:

    这篇文章很旧,但希望我能帮助遇到同样问题的人。这发生在我几天前。将字段映射到对象列表时需要超过 40 秒才能完成的请求。如果您将属性th:field 仅映射到 id,则 Spring 在将其返回给控制器时不会序列化整个对象,只会序列化 id。我找到的解决方案是使用不同的语法重新创建 Thymeleaf 生成的输出。

    而不是这个:

    <select th:field="*{item}">
        <option th:each="item : ${items}" 
                th:value="${item.getId()}" 
                th:text="${item.getValue()}"></option>
    </select>
    

    这样做:

    <select name="item" id="item">
        <option th:each="it : ${items}"
                th:selected ="${it.getId()} == *{item.getId()}"
                th:value="${item.getId()}" 
                th:text="${item.getValue()}"></option>
    </select>
    

    输出将是相同的,但页面加载速度会快 30 倍,并且会保留整个对象“item”。

    【讨论】:

      猜你喜欢
      • 2017-05-01
      • 2018-02-03
      • 1970-01-01
      • 2010-09-25
      • 1970-01-01
      • 1970-01-01
      • 2014-02-18
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多