Thymeleaf中Controller传对象至页面后Post请求丢失email值的问题
Thymeleaf中@ModelAttribute接收对象时email为null的问题
问题场景
在Thymeleaf开发场景中,定义了UserVerification实体类,Controller的GetMapping方法将设置好email的该对象存入Model传递到verification.html页面。但通过Post请求的@ModelAttribute接收对象时,otp值正常,email值却为null。
相关代码
实体类
public class UserVerification { private String email; private int otp; public UserVerification(String email, int otp) { this.email = email; this.otp = otp; } }
Controller
@GetMapping(value = "/verification", params = "email") public String verificationPage(@RequestParam("email") String email, Model model) { UserVerification verification = new UserVerification(); verification.setEmail(email); // 为对象设置email值 model.addAttribute("verification", verification); return "verification"; } @PostMapping("/verify") public String verifyUser(@ModelAttribute("verification") UserVerification verification, Model model) { System.out.println(verification.getOtp()); // otp值正常 System.out.println(verification.getEmail()); // email值为null,原因是什么? if (userService.verifyUser(verification)) { return "redirect:/user/login"; } model.addAttribute("verification", verification); return "verification?email=" + verification.getEmail(); }
verification.html
<form id="verifyForm" th:action="@{/user/verify}" th:object="${verification}" method="post"> <label for="verificationCode"></label><input type="text" th:field="*{otp}" id="verificationCode" name="verificationCode" placeholder="Enter code"> <br> <small style="color: #dc3545"></small><br> <button class="btn btn-primary" type="submit" style="margin-top:20px">Verify</button> </form>
原因分析
- 表单未提交email字段:前端表单仅包含otp对应的输入框,没有将email作为表单参数提交到后端。
@ModelAttribute从请求参数中绑定数据,未收到email参数自然会返回null。 - 实体类缺少无参构造方法:Spring MVC绑定
@ModelAttribute对象时,默认需要调用无参构造实例化对象,当前UserVerification只有带参构造,会导致对象实例化异常(框架兼容后可能出现部分字段绑定异常)。 - 表单手动指定name属性冲突:
th:field="*{otp}"会自动生成正确的name属性(应为otp),但手动指定的name="verificationCode"会导致参数名不匹配,虽未影响otp获取,但属于不规范写法。
解决方案
1. 完善实体类
添加无参构造方法及完整的getter、setter方法:
public class UserVerification { private String email; private int otp; // 添加无参构造 public UserVerification() { } public UserVerification(String email, int otp) { this.email = email; this.otp = otp; } // 添加getter和setter public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } public int getOtp() { return otp; } public void setOtp(int otp) { this.otp = otp; } }
2. 在表单中添加email隐藏字段
在表单内添加隐藏输入框,传递email值到后端,同时移除手动指定的name属性:
<form id="verifyForm" th:action="@{/user/verify}" th:object="${verification}" method="post"> <!-- 添加隐藏字段传递email --> <input type="hidden" th:field="*{email}"> <label for="verificationCode"></label><input type="text" th:field="*{otp}" id="verificationCode" placeholder="Enter code"> <br> <small style="color: #dc3545"></small><br> <button class="btn btn-primary" type="submit" style="margin-top:20px">Verify</button> </form>
3. 可选:通过@RequestParam接收email
若不想添加隐藏字段,可在Post方法中通过@RequestParam接收email并设置到对象中:
@PostMapping("/verify") public String verifyUser(@ModelAttribute("verification") UserVerification verification, @RequestParam("email") String email, Model model) { verification.setEmail(email); // 后续逻辑不变 }
同时在表单action中拼接email参数:
<form id="verifyForm" th:action="@{/user/verify(email=${verification.email})}" th:object="${verification}" method="post"> <!-- 表单内容 --> </form>
内容的提问来源于stack exchange,提问作者Aniket_Mishra
相关产品推荐
相关产品推荐

