平时写 CRUD 接口,大部分人对参数接收的认知停留在:@RequestParam 接普通参数、@RequestBody 接 JSON。
但线上很多 400、参数为空、类型转换异常、接收不到数据的问题,都不是写错注解导致的,是对 Spring MVC 参数绑定规则细节不了解。
记录近期项目迭代遇到的几个隐蔽问题,全部可稳定复现,针对性规避即可。
- @RequestParam 接收空字符串自动转 null
前端传参为空字符串 “”,后端用String 参数接收,大部分场景会直接变成 null。
坑点:业务中如果需要区分「未传参」和「传空字符串」,这个默认行为会直接打乱校验逻辑。
解决方式: - 全局关闭字符串自动trim(不推荐,影响范围大)
- 业务层手动判空,区分 null 和空字符串:
// null 代表未传参,“” 代表主动传空
if (name == null) {
// 未携带该参数
} else if (“”.equals(name)) {
// 主动传空字符串
}
- @RequestBody 无法接收 form-data 数据
新手最容易混淆的传参方式:
前端 form-data 表单提交,后端用 @RequestBody 接收,直接报 400 错误。
根因:
@RequestBody 只能解析 application/json、application/xml 这类请求体数据,依赖 MappingJackson2HttpMessageConverter。
而 form-data / x-www-form-urlencoded 属于表单请求,走的是参数绑定流程,不走 JSON 解析器。
正确对应关系:
- JSON 格式 → @RequestBody
- 表单/URL 参数 → 实体类参数、@RequestParam
如果接口需要同时兼容 JSON 和表单,不要用 @RequestBody,直接用实体类接收参数即可。
-
实体类参数首字母大写导致接收不到值
非常隐蔽的字段绑定问题,很多人排查半小时找不到原因。
实体类字段定义:
public class UserDTO {
// 首字母大写
private String UserName;// getter/setter
public String getUserName() { return UserName; }
public void setUserName(String userName) { UserName = userName; }
}
前端传参userName: “test”,后端始终接收不到。
根因:Spring 参数绑定遵循 Java 驼峰规范,通过 setter 方法反射赋值。
字段 UserName、setter setUserName,Spring 解析对应的参数名为 u serName,和前端传入的 userName 不匹配,直接绑定失败。
规范:实体类字段必须小驼峰命名,绝对不能首字母大写。
- 基本类型参数不传参直接报错 400
接口使用基本类型接收参数,不赋默认值,前端不传参直接 400。
@GetMapping(“/page”)
public void page(@RequestParam int pageNum, @RequestParam int pageSize) {
// 分页逻辑
}
问题:基本类型 int 不能为 null,Spring 检测到参数缺失,直接抛出参数缺失异常。
很多人习惯用包装类,但不知道根本区别:
// 推荐写法
@GetMapping(“/page”)
public void page(
@RequestParam(required = false, defaultValue = “1”) Integer pageNum,
@RequestParam(required = false, defaultValue = “10”) Integer pageSize
) {
// 兜底赋值
pageNum = pageNum == null ? 1 : pageNum;
}
核心原则:所有对外接口参数,数值类型统一用包装类,设置非必传+默认值,避免空参报错。 - @RequestParam 接收数组参数的格式坑
前端传数组参数,两种格式后端接收效果完全不同。
后端代码:
@GetMapping(“/ids”)
public void getIds(@RequestParam List ids) {
System.out.println(ids);
}
支持格式:/ids?ids=1&ids=2&ids=3
不支持格式:/ids?ids=1,2,3
第二种写法会被当成单个字符串,不会自动分割成数组,导致集合长度为1,数据异常。
解决方案:
如果前端只能传逗号分隔字符串,后端手动分割:
@GetMapping(“/ids”)
public void getIds(@RequestParam String ids) {
List idList = Arrays.stream(ids.split(“,”))
.map(Long::valueOf)
.collect(Collectors.toList());
}
- 时间参数无格式化注解报错
非 JSON 传参场景下,时间字符串无法自动转换 Date 对象。
错误写法:
@GetMapping(“/time”)
public void time(@RequestParam Date createTime) {
}
前端传 2025-09-01 12:00:00,直接类型转换异常。
根因:Spring 默认只能解析 yyyy/MM/dd 格式,不支持横杠+时分秒格式。
正确写法:
@GetMapping(“/time”)
public void time(@RequestParam @DateTimeFormat(pattern = “yyyy-MM-dd HH:mm:ss”) Date createTime) {
}
补充:@RequestBody 接收 JSON 时间参数,用 @JsonFormat,不要混用两个注解。
收尾
Spring MVC 参数绑定的大部分问题,都不是代码写错了,是默认机制不熟悉。
这类问题本地测试很难全覆盖,基本都是上线后才暴露。把这些细节固化成编码习惯,能规避 80% 的接口参数异常。

4014

被折叠的 条评论
为什么被折叠?



