Spring Boot+Thymeleaf新增Pret记录时遇404错误求助
先帮你梳理下几个关键问题,这些大概率是导致404和功能异常的核心原因:
1. 表单提交URL的大小写与路径问题
你的表单里写的提交路径是:
<form th:action="@{SavePret}" method="post" th:object="${pretFormulaire}">
但控制器的PostMapping注解是:
@PostMapping(value = "/savePret")
URL是严格区分大小写的,SavePret和savePret会被识别为两个完全不同的路径,这直接导致提交请求时找不到对应的控制器方法,返回404。
修改表单的action为小写路径,同时加上斜杠确保是绝对路径:
<form th:action="@{/savePret}" method="post" th:object="${pretFormulaire}">
2. 表单字段绑定与控制器参数接收不匹配
你在下拉框里用th:field="*{livre}"和th:field="*{lecteur}",这会尝试把整个Livre和Lecteur对象提交到后台,但控制器方法里却用Long livre_id, Long lecteur_id接收参数,两者完全不匹配,不仅无法正确获取数据,还可能间接导致请求异常。
正确的做法是在下拉框的th:value里绑定对象的ID,而非整个对象:
<select th:field="*{livreId}"> <option th:each="livre:${listLivres}" th:value="${livre.id}" th:text="${livre.titre}"></option> </select> <select th:field="*{lecteurId}"> <option th:each="lecteur:${listLecteurs}" th:value="${lecteur.id}" th:text="${lecteur.nom}"></option> </select>
同时需要在你的Pret类(或表单绑定的pretFormulaire对应类)中添加livreId和lecteurId两个Long类型字段,并补充对应的getter/setter方法。
然后修改控制器的save方法,从表单对象中获取ID:
@PostMapping(value = "/savePret") public String savePret2(@Valid @ModelAttribute("pretFormulaire") Pret pretFormulaire, BindingResult bindingResult){ // 从表单对象中获取ID Long livreId = pretFormulaire.getLivreId(); Long lecteurId = pretFormulaire.getLecteurId(); // 注意:新版本Spring Data JPA的findOne已废弃,改用findById并处理空值 Livre livre = livreRepository.findById(livreId) .orElseThrow(() -> new IllegalArgumentException("无效的图书ID")); Lecteur lecteur = lecteurRepository.findById(lecteurId) .orElseThrow(() -> new IllegalArgumentException("无效的读者ID")); livre.setNbFoisPret(livre.getNbFoisPret() + 1); // 这里注意:如果disponible是布尔类型,直接设为false而非字符串拼接 livre.setDisponible(false); pretFormulaire.setLecteur(lecteur); pretFormulaire.setLivre(livre); pretFormulaire.setDatePret(new Date()); pretRepository.save(pretFormulaire); // 跳转用绝对路径,避免相对路径导致的跳转异常 return "redirect:/Index"; }
3. 视图名称不匹配
你的控制器formPret方法返回的是"Form",但你实际的页面是addPret.html。如果你的视图解析器配置了前缀+视图名+后缀(比如/templates/+视图名+.html),返回"Form"会去找Form.html,而非你写的addPret.html,这会导致访问表单页面时就出现404。
修改控制器的返回值为正确的视图名:
@RequestMapping(value = "/form", method = RequestMethod.GET) public String formPret(Model model) { Pret pretFormulaire = new Pret(); model.addAttribute("pretFormulaire", pretFormulaire); List<Lecteur> listLecteurs = lecteurRepository.findAll(); List<Livre> listLivres = livreRepository.findAll(); model.addAttribute("listLecteurs", listLecteurs); model.addAttribute("listLivres", listLivres); // 返回正确的视图名 return "addPret"; }
4. 其他细节修正
- 控制器的
@ModelAttribute名称要和表单的th:object一致:表单用的是${pretFormulaire},所以控制器里应该写@ModelAttribute("pretFormulaire"),而非"pret",否则参数绑定会失败。 - 检查控制器类是否添加了
@Controller注解,如果有类级别的@RequestMapping前缀(比如@RequestMapping("/pret")),表单的action要加上前缀,比如@{/pret/savePret}。
按照上面的步骤修改后,应该能解决404问题,同时让表单提交和数据保存功能正常运行。
内容的提问来源于stack exchange,提问作者Antseva

