You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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>

原因分析

  1. 表单未提交email字段:前端表单仅包含otp对应的输入框,没有将email作为表单参数提交到后端。@ModelAttribute从请求参数中绑定数据,未收到email参数自然会返回null。
  2. 实体类缺少无参构造方法:Spring MVC绑定@ModelAttribute对象时,默认需要调用无参构造实例化对象,当前UserVerification只有带参构造,会导致对象实例化异常(框架兼容后可能出现部分字段绑定异常)。
  3. 表单手动指定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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.27 16:30:35