使用Thymeleaf和Spring正确地从标签发送对象

问题描述 投票:0回答:1

我有一个使用Thymeleaf作为模板引擎的Spring Boot应用程序(库管理器)。

该应用程序包括两个主要的@Components,BookAuthor。一个Book可以有一个Author

我可以成功创建,检索,更新和删除任何Author,但无法正确创建或更新Books(虽然我可以检索并删除它们)。在发出插入Book的POST请求时(插入已经存在的对象只是更新它)我在浏览器中收到400 Bad Request. Validation failed for object='book'.错误,并且控制台列出了typeMismatch: Failed to convert property value of type 'java.lang.String' to required type 'com.springboot.demoweb.model.Author'错误。

我正在检查发送到应用程序的请求,而不是发送一个JSON“节点”(抱歉,我不知道JSON是如何工作的)包含根JSON“节点”AuthorBook的属性,它只是发送结果Author.toString()(我过分夸大。不重写这个方法不会改变任何东西)。

这是<select>片段:

<form action="#" th:action="@{/books}" th:object="${book}" method="post">
    ...

    <select th:field="*{author}">
        <option th:each="author : ${authors}"
                th:value="${author}"
                th:text="${author}"/>
    </select>

    ...
</form>

Author.java文件:

@Component
public class Author implements Serializable {
    private String id;
    private String name;

    @DateTimeFormat(pattern = "yyyy-MM-dd")
    private Calendar dateBorn;

    @DateTimeFormat(pattern = "yyyy-MM-dd")
    private Calendar dateDeath;

    ... // Getters and setters
}

Book.java文件:

@Component
public class Book {
    private String isbn;
    private String title;
    private Author author;

    ... // Getters and setters
}

BookController.java

@Controller
public class BookController {
    @GetMapping(value = "/books/edit", params = "isbn")
    public String viewEdit(@RequestParam("isbn") String isbn, Model model) {
        model.addAttribute("book", bookService.find(isbn));
        model.addAttribute("authors", authorService.all());
        return "books/edit";
    }

    // th:action="@{/books}" falls here
    @PostMapping("/books")
    public RedirectView create(Book book) {
        bookService.create(book);
        return new RedirectView("/books.html?isbn=" + book.getIsbn());
    }

    ... // Other mappings
}

变量bookServiceauthorService分别对Map<String, Book>Map<String, Author>进行简单的操作。

我可以为Thymeleaf做什么将Author作为Book中的对象发送,而不仅仅是它的字符串表示?我是否必须在HTML页面中更改某些内容?控制器?添加Thymeleaf配置?

java spring spring-boot thymeleaf
1个回答
0
投票

根据百里香documentation

表单标记中的th:object属性的值必须是变量表达式($ {...}),仅指定模型属性的名称,不带属性导航。这意味着像$ {seedStarter}这样的表达式是有效的,但$ {seedStarter.data}不会。

您的Thymeleaf表单呈现所选作者的toString值。无法在选项列表中绑定Author对象。因此,更改Book对象添加新属性authorId(如果Book是JPA实体,请使用@Transient注释)。

@Component
public class Book {
     private String isbn;
     private String title;
     private Author author;
     // New Transient attribute to bind authorId from select component
     private String authorId;
}

现在,可以使用select组件绑定此新属性,因为它符合上述文档。

<form action="#" th:action="@{/books}" th:object="${book}" method="post">
...

<select th:field="*{authorId}">
    <option th:each="author : ${authors}"
            th:value="${author.id}"
            th:text="${author.name}"/>
</select>

...

在您的控制器中,您可以使用book.authorId获取作者对象并将其设置为book对象。

@PostMapping("/books")
public RedirectView create(Book book) {
    Author author = authorService.findById(book.authorId);
    book.setAuthor(author);
    bookService.create(book);
    return new RedirectView("/books.html?isbn=" + book.getIsbn());
}
© www.soinside.com 2019 - 2024. All rights reserved.