Spring Boot加载Thymeleaf表单触发TemplateProcessingException问题排查
问题分析与解决方案
启动Spring Boot应用加载首页时,反复出现以下错误:
org.thymeleaf.exceptions.TemplateProcessingException: Error during execution of processor 'org.thymeleaf.spring5.processor.SpringInputGeneralFieldTagProcessor' (template: "index" - line 15, col 28)
错误指向index.html第15行的th:field="*{name}",堆栈跟踪显示核心原因:
java.lang.IllegalStateException: Neither BindingResult nor plain target object for bean name 'respondent' available as request attribute
已在GET请求中向Model传入新的Respondent对象,但表单仍无法渲染,问题出在以下几个地方:
相关代码片段
index.html
<html lang="en-US" xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org"/> <head> <title>TODO supply a title</title> <meta charset="UTF-8"/> <meta name="viewport" content="width=device-width, initial-scale=1.0"/> </head> <body> <div th:replace="fragments.html :: header"></div> <form action="#" th:action="@{/respondent}" method="post" th:object="${respondent}"> <input type="text" th:field="*{name}"><br/> <input type="text" th:field="*{groupname}"><br/> <input type="submit" value="submit"/> </form> <div th:replace="fragments.html :: footer"></div> </body> </html>
RestController.java
@Controller @AllArgsConstructor public class RestController { @Autowired private RespondentRepository respondentRepository; @GetMapping("/") public String getHome(Model model) { model.addAttribute("respondent", new Respondent()); System.out.println("added respondent"); return "index"; } @ModelAttribute("respondent") public Respondent newRespondent() { return new Respondent(); } @PostMapping("/respondent") public String newRespondent(@ModelAttribute("respondent") Respondent respondent, Model model) { model.addAttribute("respondent", respondent); System.out.println("adding to repo (hopefully)"); respondentRepository.save(respondent); return "index"; } }
Respondent.java
@Entity @Getter @Setter public class Respondent implements Serializable { @Id @GeneratedValue(strategy = GenerationType.AUTO) private Long id; private String name; private String groupName; public Respondent(String name, String groupName) { this.name = name; this.groupName = groupName; } public Respondent(Long id, String name, String groupName) { this.id = id; this.name = name; this.groupName = groupName; } public Respondent() { } }
RespondentRepository.java
public abstract class RespondentRepository implements CrudRepository {}
修复步骤
表单字段名与实体属性不匹配
实体类中属性名为groupName(驼峰命名),但index.html中写成了groupname,Thymeleaf无法找到对应属性导致绑定失败。修改index.html中的字段:<input type="text" th:field="*{groupName}"><br/>Repository定义错误
Spring Data JPA的Repository必须是接口而非抽象类,且需要指定实体类型和主键类型。修改RespondentRepository:import org.springframework.data.repository.CrudRepository; public interface RespondentRepository extends CrudRepository<Respondent, Long> {}消除依赖注入冗余
类上使用了@AllArgsConstructor,会自动生成包含所有成员变量的构造方法,此时@Autowired可以省略(Spring会通过构造方法注入),修改RestController:@Controller @AllArgsConstructor public class RestController { private RespondentRepository respondentRepository; // 其余代码不变 }可选:统一ModelAttribute处理
已经通过@ModelAttribute全局添加了respondent对象,GET方法中的model.addAttribute("respondent", new Respondent())可以去掉,避免重复设置。
完成以上修改后,重新启动应用,表单即可正常渲染,提交功能也能正常工作。
内容的提问来源于stack exchange,提问作者Nick Siepmann
相关产品推荐
相关产品推荐

