首页 > 解决方案 > bean 类 [java.util.ArrayList] 的无效属性“books [0]”

问题描述

Caused by: org.springframework.beans.NotReadablePropertyException: Invalid property 'books[0]' of bean class [java.util.ArrayList]: Bean property 'books[0]' is not readable or has an invalid getter method: Does the return type of the getter match the parameter type of the setter?

阅读列表.html

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <title>Reading List</title>
    <link rel="stylesheet" th:href="@{/style.css}"></link>
</head>
<body>
<h2>Your Reading List</h2>
<div th:unless="${#lists.isEmpty(books)}">
    <dl th:each="book : ${books}">
        <dt class="bookHeadline">
            <span th:text="${book.title}">Title</span> by
            <span th:text="${book.author}">Author</span>
            (ISBN: <span th:text="${book.isbn}">ISBN</span>)
        </dt>
        <dd class="bookDescription">
            <span th:if="${book.description}" th:text="${book.description}">Description</span>
            <span th:if="${book.description eq null}"> No description available</span>
        </dd>
    </dl>
</div>
<div th:if="${#lists.isEmpty(books)}">
    <p>You have no books in your book list</p>
</div>



<hr/>
<h3>Add a book</h3>
<form method="POST" action="#" th:action="@{/readingList}" th:object="${books}">
    <div th:if="${#fields.hasErrors()}">
    <span class="validationError">
        Please correct the problems below and resubmit.
    </span>
    </div>


    <label for="title">Title:</label>
      <input type="text"  th:field="*{books[0].title}" size="50"/><br/>
      <span class="validationError"
            th:if="${#fields.hasErrors('books[0].title')}"
            th:errors="*{books[0].title}">
          title error
      </span>
    <!--   <input type="text" name="title" size="50"></input><br/>-->


    <label for="author">Author:</label>
    <input type="text" name="author" size="50"></input><br/>
    <label for="isbn">ISBN:</label>
    <input type="text" name="isbn" size="15"></input><br/>
    <label for="description">Description:</label><br/>
    <textarea name="description" rows="5" cols="80"></textarea><br/>
    <input type="submit"></input>
</form>
</body>
</html>

ReadingListController.java

package com.example.readinglist;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import javax.validation.Valid;
import java.util.List;

@Controller
@RequestMapping("/readingList")
public class ReadingListController {

    private static final String reader = "craig";

    private ReadingListRepository readingListRepository;

    @Autowired
    public ReadingListController(ReadingListRepository readlingListRepository) {
        this.readingListRepository = readlingListRepository;
    }


    @GetMapping
    public String readersBooks(Model model) {
        List<Book> readingList = readingListRepository.findByReader(reader);
        if (readingList != null) {
            model.addAttribute("books", readingList);
        }
        return "readingList";
    }

    @PostMapping
    public String addToReadingList(@Valid Book book, BindingResult bindingResult, RedirectAttributes attr) {
        if(bindingResult.hasErrors()){
            return "error";
        }
        book.setReader(reader);
        readingListRepository.save(book);
        attr.addFlashAttribute("books", book);
        return "redirect:/readingList";
    }

}

图书.java

package com.example.readinglist;

import lombok.Data;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;

@Data
@Entity
public class Book {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;
    private String reader;
    private String isbn;
    @NotBlank(message = "title cannot be null")
    private String title;
    private String author;
    private String description;

}

我知道这个问题是由于验证 title 属性的方法错误,<input type="text" th:field="*{books[0].title}" size="50"/>因为它books是一个数组列表,而不是一个简单的对象。但问题是,我只想验证title字段的输入,但是传入的对象是一个数组,我该怎么办呢?我也检查了许多类似的问题,但它们都不符合我的情况。

标签: spring-bootspring-mvcthymeleaf

解决方案


如果您打算使用th:objectand th:fieldth:object 则不能是 type List,Thymeleaf 就是不允许这样做。您需要另一个对象(aBookForm或类似的东西),它包含List<Book> books它的属性。

使用该新BookForm对象作为您的th:object然后您的th:field表达式应该起作用。

在 Thymeleaf Spring 整数示例中可以看到一个示例。您可以看到,在这个动态字段示例中SeedStarter 类 具有 aList<Row>并且它们不只是使用 List 作为th:object.


推荐阅读