Thymeleaf从Spring Data JPA迭代Java 8流

rdlzhqv9  于 7个月前  发布在  Spring
关注(0)|答案(3)|浏览(55)

我的Google-Fu让我失望了,所以我问你.有没有一种方法可以用Thymeleaf来编译Java 8 Stream,类似于迭代List的方式,同时仍然保持Stream的性能目标?
存储库

Stream<User> findAll()

字符串
模型

Stream<User> users = userRepository.findAll();
model.addAttribute("users", users);


视图

<div th:each="u: ${users}">
   <div th:text="${u.name}">


如果我尝试这个,我得到:

org.springframework.expression.spel.SpelEvaluationException: EL1008E: Property or field 'name' cannot be found on object of type 'java.util.stream.ReferencePipeline$Head' - maybe not public?


如果我使用List,它会像预期的那样工作。
有没有一个正确的方法来处理我找不到的流?

new9mtju

new9mtju1#

虽然Thymeleaf不支持流,但它支持Iterable,因此您可以执行以下操作:
产品型号:

Stream<User> users = userRepository.findAll();
model.addAttribute("users", (Iterable<User>) users::iterator);

字符串
您的视图将像您已经编写的那样工作:

<div th:each="u: ${users}">
    <div th:text="${u.name}">


查看第3版文档,它说它将支持任何实现Iterator的对象,所以它也应该可以做到这一点:
产品型号:

Stream<User> users = userRepository.findAll();
model.addAttribute("users", users.iterator());


我没有使用这个版本,所以我还没有能够得到它的工作,虽然。

nzk0hqpo

nzk0hqpo2#

据我所知,在Thymeleaf文档中没有办法做到你想要的。
此外,Thymeleaf不提供任何与流交互的方式,请考虑Stream对象在您执行终端操作之前无法访问其包含的对象(例如Collectors.toList()

laawzig2

laawzig23#

这篇文章有点旧了,但我没有看到任何更新的。它可以用正确的秘密酱料来完成。
在Java代码中,你必须做三件事:
1.使用@javax.transaction. transaction注解
1.手动调用Thymeleaf处理模板
1.在模板处理上使用try-with-resources块来保证流是关闭的
在你的模板中,如果你传递Stream的迭代器,你不必做任何不同的事情,因为Thyemeleaf已经理解了迭代器。
当从Spring Data返回流时,@ transmitting annotation是必需的。关键是带注解的方法必须在流结束之前实际使用流-这不会使用Thyemleaf以“正常”方式发生,其中该方法仅返回String模板名称。
与此同时,流已经关闭(当使用流来执行诸如将List转换为Map之类的操作时,您不必这样做)。通过自己控制模板生成过程,您可以确保流在@ transmitting方法中关闭并使用。
Java代码看起来像这样(我使用Spring 5 MVC):

@Controller
public class CustomerController {
    @Autowired
    SpringTemplateEngine templateEngine;

    @Autowired
    private CustomerRepository customerRepository;

    @RequestMapping("/customers")
    @Transactional
    public void customers(
        final String firstName,
        final HttpServletRequest request,
        final HttpServletResponse response
    ) throws IOException {
        final WebContext ctx = new WebContext(
            request,
            response,
            request.getServletContext(),
            request.getLocale()
        );

        try (
            final Stream<CustomerModelEntity> models = 
                (firstName == null) || firstName.isEmpty() ?
                customerRepository.findAll() :
                customerRepository.findByFirstNameIgnoringCaseOrderByLastNameAscFirstNameAsc(firstName)
        ) {
            ctx.setVariable(
                "customers",
                models.iterator()
            );

            response.setContentType("text/html");

            templateEngine.process(
                "customer-search",
                ctx,
                response.getWriter()
            );
        }
    }
}

字符串
Thymeleaf模板看起来如下(我使用解耦逻辑):

<?xml version="1.0"?>
<thlogic>
  <attr sel=".results" th:remove="all-but-first">
    <attr sel="/.row[0]" th:each="customer : ${customers}">
      <attr sel=".first-name" th:text="${customer.firstName}" />
      <attr sel=".middle-name" th:text="${customer.middleName}" />
      <attr sel=".last-name" th:text="${customer.lastName}" />
    </attr>
  </attr>
</thlogic>

相关问题