Thymeleaf表单提交Todo对象字段为空的问题求助
问题排查与解决方案
问题根源
核心问题是Java Record的无参构造器干扰了Spring MVC的数据绑定机制:
- 你为Todo Record手动添加了无参构造器,Spring MVC处理表单提交时会优先调用该构造器创建实例。
- Java Record默认没有Setter方法,Spring无法通过常规JavaBean属性填充方式为字段赋值,最终所有字段保持无参构造器中的默认值。
- 若你的Spring版本低于6.x(对应Spring Boot 3.x),旧版本对Java Record的构造器绑定支持有限,会加剧这个问题。
解决方案
方案一:改用普通JavaBean(推荐新手使用)
将Todo Record改为标准Java实体类,提供Getter、Setter和无参构造器,这是Spring MVC兼容性最好的方式:
import jakarta.persistence.Id; public class Todo { @Id private Long id; private Long userId; private String name; private String description; private boolean completed; // 无参构造器 public Todo() { this(null, null, "", "", false); } // 全参构造器 public Todo(Long id, Long userId, String name, String description, boolean completed) { this.id = id; this.userId = userId; this.name = name; this.description = description; this.completed = completed; } // Getter和Setter方法 public Long getId() { return id; } public void setId(Long id) { this.id = id; } public Long getUserId() { return userId; } public void setUserId(Long userId) { this.userId = userId; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } public boolean isCompleted() { return completed; } public void setCompleted(boolean completed) { this.completed = completed; } @Override public String toString() { return "Todo[id=" + id + ", userId=" + userId + ", name=" + name + ", description=" + description + ", completed=" + completed + "]"; } }
方案二:保留Java Record(需Spring 6+)
若坚持使用Java Record,需做以下调整:
- 移除手动添加的无参构造器,让Spring通过Record默认生成的全参构造器进行参数绑定:
import jakarta.persistence.Id; // 移除自定义无参构造器,使用Record默认的全参构造器 public record Todo(@Id Long id, Long userId, String name, String description, boolean completed) {}
- 修改Controller中的实例化代码,因无无参构造器,需用全参构造器创建Todo实例:
@GetMapping public String getAllTodos(Model model) { List<Todo> todos = todoRepository.findAll(); model.addAttribute("todos", todos); // 使用全参构造器创建空实例 model.addAttribute("todo", new Todo(null, null, "", "", false)); return "test"; }
- 确保Spring版本为6.x及以上(即Spring Boot 3.x及以上),旧版本Spring不支持通过构造器自动绑定Record参数。
额外检查点
- 你的Thymeleaf表单配置正确:
th:object="${todo}"和th:field="*{name}"会自动生成正确的表单参数名称,无需调整。 - Spring Boot默认开启CSRF防护,Thymeleaf的
<form>标签会自动注入CSRF令牌,不会导致参数丢失。
内容的提问来源于stack exchange,提问作者Ike Osenberg
相关产品推荐
相关产品推荐

