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

Spring MVC控制器无法获取JSP form:hidden隐藏域值问题

问题现象

测试支付相关代码时,需要接收表单传入的隐藏金额字段,但使用<form:hidden>标签定义的隐藏域值无法传递到后端控制器,其余普通表单字段均可正常获取,唯独该隐藏域取值失败。将字段改为带readonly属性的普通输入框时,所有字段值均可正常获取。

相关代码

JSP表单代码

<form:form id="frmCard" method="post" action="${payment_url}"
   align="center" modelAttribute="payment">
   <div id="my-card" class="card-js"  data-capture-name="true"
       data-icon-colour="#337ab7">

   <form:input path="card_number" class="card-number" placeholder="Card Number" />
   <form:input path="card_name" class="name englishonly" placeholder="Name On Card" maxlength="21" />
   <form:input path="card_expiry_month" class="expiry-month" />
   <form:input path="card_expiry_year" class="expiry-year" />
   <form:input path="card_cvc" class="cvc" />
           
   <form:hidden path="amount" value="10" /> <!-- 异常字段 -->
   <p>
       <div>
           <img src="../img/cards.png">
       </div>
   <p>
   <input type="submit" name="Pay" />
</form:form>

控制器方法代码

@PostMapping("/addPayment")
public String payment(@ModelAttribute("payment") Payment payment ) {
    System.out.println(""+payment.getCard_number()); // 正常获取值
    System.out.println("$ "+payment.getAmount()); // 无法获取值
    String status = "error";
    try {
        status = paymentService.process(payment);
    } catch (Exception e) {
        e.printStackTrace();
    }
    return status;
}
原因说明
  1. 前端DOM重构问题:当前使用的card-js银行卡号输入组件,初始化时会扫描容器内的表单元素,仅保留带指定类名(card-number、expiry-month等组件识别类)的输入项做自定义渲染,未被识别的<form:hidden>元素会被组件移出表单甚至直接删除,导致表单提交时请求参数中根本不包含amount字段,后端自然无法获取值。这也是把字段改成带readonly的普通输入框(属于组件识别的input类型)时可以正常传值的核心原因。
  2. Spring表单标签绑定逻辑问题:<form:hidden>标签的渲染逻辑会优先读取modelAttribute绑定对象的对应属性值,手动写在标签上的value属性不会强制覆盖绑定值。如果跳转页面时没有提前给model中payment对象的amount属性赋值,即使标签上写了value="10",渲染出的隐藏input实际value也可能为空。
解决方案
  • 方案1:将隐藏域移出card-js组件容器
    把<form:hidden path="amount" />标签移到id="my-card"的div外部,作为<form:form>的直接子节点,避免被前端组件修改DOM。同时在跳转到支付页面的控制器方法中,提前给绑定的payment对象设置amount值,不要手动在标签上硬写value:
    // 跳转到支付页的接口示例
    @GetMapping("/toPayPage")
    public String toPayPage(Model model) {
        Payment payment = new Payment();
        payment.setAmount(10); // 提前赋值
        model.addAttribute("payment", payment);
        return "payPage";
    }
    
  • 方案2:使用原生HTML隐藏域
    不使用Spring的<form:hidden>标签,在card-js容器内直接写原生隐藏输入框,确保name属性和实体类字段名一致即可正常绑定:
    <input type="hidden" name="amount" value="10" />
    
  • 方案3:用隐藏样式的只读输入框替代
    保留输入框的readonly属性,通过CSS设置为不可见,实现和隐藏域一致的效果,同时不会被card-js组件过滤:
    <form:input path="amount" readonly="true" style="display: none;" value="10" />
    

内容的提问来源于stack exchange,提问作者J. Doe

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.03 02:27:28