【问题标题】:How to set object field from Thymeleaf template?如何从 Thymeleaf 模板设置对象字段?
【发布时间】:2019-04-18 14:28:58
【问题描述】:

我是 Spring 的新手,我试图在 Spring in action 5 (Craig Walls) 的帮助下学习它。我正在创建小型 Spring Boot MVC 应用程序。现在我对 Thymeleaf 有一点问题。

我有控制器、视图和模型作为 POJO 对象。当我试图从表单中获取数据时,Intellij Idea 告诉我这行中我的 Thymeleaf 视图有问题:

Model
import java.util.Date;
import java.util.List;

import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;

import lombok.Data;


@Data
public class Taco {

    private Long id;

    private Date createdAt;

    @NotNull
    @Size(min=5, message="Name must be at least 5 characters long")
    private String name;

    @Size(min=1, message="You must choose at least 1 ingredient")
    private List<Ingredient> ingredients;


}

查看

<!DOCTYPE html>
<html lang="en"
      xmlns="http://www.w3.org/1999/xhtml"
      xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Taco Cloud</title>
    <link rel="stylesheet" th:href="@{/styles.css}"/>

</head>
<body>

    <h1>Design your taco!</h1>
    <img src="../static/images/TacoCloud.png" alt="TacoCloud.png" th:src="@{/images/TacoCloud.png}">

    <form method="POST" th:object="${taco}">
        <div class="grid">
            <div class="ingredient-group" id="wraps">
                <h3>Designate yor wrap:</h3>
                <div th:each="ingredient:${wrap}">
                    <input name="ingredients" type="checkbox" th:value="${ingredient.id}"/>

                    <span th:text="${ingredient.name}">INGREDIENT</span><br/>
                </div>
            </div>


            <div class="ingredient-group" id="proteins">
            <h3>Pick your protein:</h3>
            <div th:each="ingredient: ${protein}">
                <input name="ingredients" type="checkbox" th:value="${ingredient.id}"/>
                <span th:text="${ingredient.name}">INGREDIENT</span>
            </div>
        </div>


            <div class="ingredient-group" id="cheeses">
                <h3>Choose your cheese:</h3>
                <div th:each="ingredient:${cheese}">
                    <input name="ingredients" type="checkbox" th:value="${ingredient.id}"/>
                    <span th:text="${ingredient.name}">INGREDIENT</span><br/>
                </div>
            </div>

            <div class="ingredient-group" id="veggies">
                <h3>Determine your veggies:</h3>
                <div th:each="ingredient : ${veggies}">
                    <input name="ingredients" type="checkbox" th:value="${ingredient.id}"
                    />
                    <span th:text="${ingredient.name}">INGREDIENT</span><br/>
                </div>
            </div>
            <div class="ingredient-group" id="sauces">
                <h3>Select your sauce:</h3>
                <div th:each="ingredient : ${sauce}">
                    <input name="ingredients" type="checkbox" th:value="${ingredient.id}"
                    />
                    <span th:text="${ingredient.name}">INGREDIENT</span><br/>
                </div>
            </div>
        </div>
        <div>
            <h3>Name your taco creation:</h3>
            <input type="text" name="name"  th:field="*{name}"/> 

            <br/>
            <button>Submit your taco</button>
        </div>

    </form>

</body>
</html>

控制器

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.Errors;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import tacos.Ingredient.Type;
import tacos.Ingredient;
import org.springframework.web.bind.annotation.ModelAttribute;
import tacos.Taco;
import tacos.data.IngredientRepository;

import javax.validation.Valid;


import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;


@Slf4j
@Controller
@RequestMapping("/design")
public class DesignTacoController {

    private final IngredientRepository ingredientRepo;

    @Autowired
    public DesignTacoController(IngredientRepository ingredientRepo){
        this.ingredientRepo=ingredientRepo;
    }


    @GetMapping
    public String showDesignForm(Model model) {

        List<Ingredient> ingredients=new ArrayList<>();
        ingredientRepo.findAll().forEach(i->ingredients.add(i));

        Type[] types = Ingredient.Type.values();
        for (Type type : types) {
            model.addAttribute(type.toString().toLowerCase(),
                    filterByType(ingredients, type));
        }

        return "design";
    }


    private List<Ingredient> filterByType(
            List<Ingredient> ingredients, Type type) {
        return ingredients
                .stream()
                .filter(x -> x.getType().equals(type))
                .collect(Collectors.toList());
    }

    @PostMapping
    public String processDesign(@Valid @ModelAttribute("design") Taco design, Errors errors, Model model) {
        if (errors.hasErrors()) {
            return "design";
        }

        // Save the taco design...
        // We'll do this in chapter 3
        log.info("Processing design: " + design);

        return "redirect:/orders/current";
    }

}

最后我得到了这个错误:

org.thymeleaf.exceptions.TemplateInputException: An error happened during template parsing (template: "class path resource [templates/design.html]")

Caused by: org.attoparser.ParseException: Error during execution of processor 'org.thymeleaf.spring5.processor.SpringInputGeneralFieldTagProcessor' (template: "design" - line 64, col 45)

【问题讨论】:

  • 你的 html 的第 64 行有什么内容?
  • 对不起。这个
  • Col 32 从这里开始
  • &lt;form method="POST" th:object="${taco}"&gt;更改为&lt;form method="POST" th:object="${design}"&gt;
  • 它可以工作,但输入不正确但另一个页面部分不起作用(为什么我应该将 taco 更改为设计?

标签: java spring-boot thymeleaf


【解决方案1】:

我注意到您的代码中有两点。

  1. 我没有在您的表单上看到提交表单所需的th:action
  2. form method="POST" th:object="${taco}" 更改为form method="POST" th:object="${design}"

尝试修复这两个,它应该可以工作。

【讨论】:

  • 页面的另一部分是什么意思?
  • 如何查看我从数据库中获取数据并在此构造的帮助下将它们显示在视图中
    INGREDIENT
  • 如果我将 th:object 替换为 th:object="${design}",这将不起作用
  • 我听不懂你在说什么。看看百里香文档。 thymeleaf.org/doc/tutorials/2.1/thymeleafspring.html
【解决方案2】:

我遇到了同样的问题。

我的解决方案是在 Taco.java 中添加 getter 作为名称。不知何故,lombok 不会在运行时自动生成 getter。

th:object="${taco}" 应该是th:object="${design}"

无需对th:action 进行更改。来自教程

如果您再看一下视图中的标签,您会发现它的方法属性设置为 POST。此外, 没有声明动作属性。这意味着当提交表单时,浏览器将收集表单中的所有数据,并在 HTTP POST 请求中将其发送到服务器,发送到 GET 请求显示表单的同一路径 - /design 路径。

【讨论】:

    【解决方案3】:

    我在代码中发现了两件事:

    1. 我没有在 html 中找到您的表单的任何操作。您应该使用th:action 标签来添加操作。
    2. 在 html 中,您使用 th:object="${taco}" 为您的 html 表单声明一个对象。但是您不会在返回 html 设计的控制器方法中的模型中添加“taco”对象。您应该在控制器方法中添加“taco”对象,如下所示。

      model.addAttribute(“taco”, taco Object);

    【讨论】:

    • 感谢您的帮助。我解决了问题。您是对的。
    猜你喜欢
    • 2020-02-27
    • 2020-07-29
    • 2020-10-17
    • 1970-01-01
    • 2017-10-15
    • 1970-01-01
    • 1970-01-01
    • 2016-09-12
    相关资源
    最近更新 更多