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

Spring Boot中HttpRequest绑定POJO时部分字段出现空值问题排查

Twilio回调Webhook字段绑定失败问题解决

问题描述

搭建接收Twilio消息投递回调POST请求的Webhook服务器,尝试将请求数据绑定到StatusDeliveryModel对象(使用Lombok生成getter/setter),但ToNumber和FromNumber两个字段始终为空,其他字段绑定正常。通过HttpServletRequest可确认请求中To和From参数值有效,不想手动从request取值赋值,需排查问题原因并解决。

代码示例

StatusDeliveryModel.java

@Data
@Getter
@Setter
public class StatusDeliveryModel {

    @JsonProperty("SmsSid")
    private String SmsSid;
    @JsonProperty("SmsStatus")
    private String SmsStatus;
    @JsonProperty("MessageStatus")
    private String MessageStatus;
    @JsonProperty("To")
    private String ToNumber;
    @JsonProperty("MessageSid")
    private String MessageSid;
    @JsonProperty("From")
    private String FromNumber;
    @JsonProperty("ApiVersion")
    private String ApiVersion;

}

PostController.java

@RestController
public class PostController {

    @Autowired
    private MyDataService myDataService;

    @PostMapping("/insert")
    public void insertIntoDatabase(@ModelAttribute StatusDeliveryModel statusDeliveryModel, HttpServletRequest request){

        System.out.println(statusDeliveryModel.toString());

        Enumeration<String> parameterNames = request.getParameterNames();
        while (parameterNames.hasMoreElements()) {
            String paramName = parameterNames.nextElement();
            String paramValue = request.getParameter(paramName);
            System.out.println(paramName + "': " + paramValue);
        }
    }
}

打印结果

StatusDeliveryModel(SmsSid=XXXXXXXXXXXXXXXXXXXXXXX, SmsStatus=queued, MessageStatus=queued, ToNumber=null, MessageSid=XXXXXXXXXXXXXXXXXXXXXXX, FromNumber=null, ApiVersion=2010-04-01)

SmsSid': XXXXXXXXXXXXXXXXXXXXXXX
SmsStatus': queued
MessageStatus': queued
To': +1518XXXXXXX
MessageSid': XXXXXXXXXXXXXXXXXXXXXXX
From': +1213XXXXXXX
ApiVersion': 2010-04-01

问题原因

核心问题是注解使用场景不匹配:

  • @JsonProperty是Jackson框架的注解,仅用于JSON格式数据的序列化/反序列化,对Spring的表单参数绑定(@ModelAttribute)完全不起作用。
  • 当前请求是Twilio发送的表单格式(application/x-www-form-urlencoded),Spring通过@ModelAttribute绑定参数时,会根据JavaBean的属性名(或对应的setter方法名)与请求参数名精确匹配。你的属性名是ToNumber/FromNumber,而请求参数名是To/From,两者无法匹配,导致字段为空。

解决办法

方案1:修改属性名与请求参数一致(推荐)

直接将JavaBean中的属性名改为和请求参数名相同,Spring的@ModelAttribute会自动完成绑定:

@Data
public class StatusDeliveryModel {

    private String SmsSid;
    private String SmsStatus;
    private String MessageStatus;
    private String To; // 与请求参数名一致
    private String MessageSid;
    private String From; // 与请求参数名一致
    private String ApiVersion;

}

如果后续需要同时处理JSON格式请求,可保留@JsonProperty注解,不影响表单绑定。

方案2:配置Twilio发送JSON格式回调

如果不想修改JavaBean属性名,可以在Twilio控制台配置回调请求为JSON格式,然后将Controller中的@ModelAttribute替换为@RequestBody,此时@JsonProperty注解会生效:

@PostMapping("/insert")
public void insertIntoDatabase(@RequestBody StatusDeliveryModel statusDeliveryModel, HttpServletRequest request){
    // 业务逻辑不变
}

方案3:自定义表单参数绑定规则(复杂场景)

如果既不想改属性名,也不想修改Twilio配置,可以通过@InitBinder自定义参数绑定规则,将请求参数To/From映射到ToNumber/FromNumber:

@RestController
public class PostController {

    @Autowired
    private MyDataService myDataService;

    @InitBinder
    public void initBinder(WebDataBinder binder) {
        // 将请求参数"To"绑定到ToNumber属性
        binder.registerCustomEditor(String.class, "ToNumber", new PropertyEditorSupport() {
            @Override
            public void setAsText(String text) {
                setValue(text);
            }
        });
        // 将请求参数"From"绑定到FromNumber属性
        binder.registerCustomEditor(String.class, "FromNumber", new PropertyEditorSupport() {
            @Override
            public void setAsText(String text) {
                setValue(text);
            }
        });
    }

    @PostMapping("/insert")
    public void insertIntoDatabase(@ModelAttribute StatusDeliveryModel statusDeliveryModel, HttpServletRequest request){
        // 业务逻辑不变
    }
}

内容的提问来源于stack exchange,提问作者Mehsum Naqvi

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 17:47:03