昨天在写业务代码的时候遇到这样一个问题。
前端提交content-type为application/json并携带参数的查询请求时,后端无法接受到该参数。
下面展示问题如何复现以及如何解决的
一、问题复现
先准备好用于测试的代码
前端代码
$.ajax({
type: 'POST',
url: '${base.contextPath}/queryStudent',
contentType : 'application/json',
data: {
id : id,
name : name
},
success: function (res) {
console.log(res.success);
},
error: function (e) {
console.log('request error');
}
});
后端代码:
@Autowired
private IStudentService studentService;
@RequestMapping(value = "/queryStudent")
@ResponseBody
public ResponseData queryStudent(Student dto) throws MyException {
return new ResponseData(studentService.queryStudent(dto));
}
实体:
@Data //lombok注解 自动生成get set方法
public class Student {
private Long id;
private String name;
}
1、通过Fiddler对请求抓包
打开谷歌浏览器F12,可以看到这条数据是以request payload的形式提交的
后端控制台结果
也就是说,当我使用content-type为application/json的格式发送请求,数据会以request payload的形式进行提交,而HttpMessageConverter无法把这种形式的数据解析成相应的尸体,按照之前Controller的写法也就无法进行接收了。
二、解决问题
现在解决问题有两个方向,一是修改前端提交的content type;二是修改后端的参数接收方式,可以根据编码习惯自行选择。
1、既然上面那种情况无法接收到数据,尝试修改Content Type
把Content-Type修改为application/x-www-form-urlencoded
// 其余js代码同上
contentType: 'application/x-www-form-urlencoded'
使用Fiddler抓包
控制台结果:
发现参数成功获取,并且如果在ajax代码中去掉contentType,也可以得到相同结果,因为ajax默认就是以这种方法提交数据的。
打开F12,发现这是通过Form Data的方式提交数据的
2、通过修改后端接收方式来获取参数
修改回application/json后,抓包看看请求的数据
可以看到,请求中包含一条字符串形式的数据
后台加上@RequestBody注解,并使用字符串类型获取参数。
@PostMapping(value = "/queryStudent")
@ResponseBody
public void queryStudent(@RequestBody String student) {
System.out.println(student);
}
这样就可以成功获取到参数,而不使用@RequestBody同样获取参数失败。