org.springframework.web.HttpMediaTypeNotSupportedException: Content type 'application/x-www-form-urlencoded;charset=UTF-8' not supported
前端代码:
$.ajax({
type:"post",
url:"/test",
data:JSON.stringify({id:1,name:"小明",gender:true}),
success:function (result) {
console.log(result);
}
});
后端代码:
@ResponseBody
@RequestMapping("/test")
public Object testJson(@RequestBody User user){
System.out.println(user);
return user;
}
前后端用json字符串做数据交互。一运行就报了上面的异常了。
先说一下解决方法:
ajax中加上一个键值对:contentType:"application/json" 就行了。
原因:前端用 JSON.stringify({id:1,name:"小明",gender:true}) 将一个js对象转换成了json字符串,后端通过@RequestBody注解表示要解析json字符串(相当于fastJson来解析json字符串)并赋值给User对象,我们发送的是http请求,后端在解析请求参数时并不是直接解析内容,若是post请求的话,他会先检查HTTP请求的Content-type属性值,根据这个属性值来判断请求体中的数据格式。前端我们发的ajax请求默认的contentType属性值为:application/x-www-form-urlencoded;charset=UTF-8,这个contentType表示的数据格式是键值对格式。所以我后端需要json格式的数据,你给我传递个键值对格式,我肯定说不支持啊。
所以我们用contentType:"application/json"来改变http请求,表示我发送的数据是json格式的,后端就可以识别了呗。
常见场景
1)form表单默认MIME类型时
2)serialize()方法
3)ajax中的js对象(根据ajax文档显示,最终js对象在发送时会被转化成键值对格式)
4)get请求
5)FormData对象
4.Json格式:{"name":"www","url":"www","checked":true,"pId":6}
data:JSON.stringify({name:name,url:url,checked:checked,pId:pId}), //将js对象转换成json字符串格式
contentType:"application/json" //设置请求的MIME类型为application/json格式,即json格式
5.请求体的区别:Form data 和Request Payload
1、当post请求的content-Type属性的值为application/x-www-form-urlencoded; charset=UTF-8时,数据封装在Form data中,键值对格式
2、当post请求的content-Type属性的值为application/json或text/plain时,数据封装在Request Payload中,json格式
1、只要保证请求的参数名和处理器方法的形参名称一致,自动绑定成功。
2、获取单个请求参数
1)@RequestParam注解:获取一个请求参数,并赋值给一个形参
属性
@RequestParam(value="password",required=false,defaultValue="0") int password
required:设置属性是否为必须的,默认为true。可以设置其值为false,即当没有该属性时也不会报错。
defaultValue:当required=false时使用,设置请求参数的默认值,不能单独使用。
2)@PathVariable 注解:针对rest风格的url,可以将url的占位符参数,绑定到处理器方法的入参处
testPathvariable
@GetMapping("/testPathvariable/{id}/{name}")
public String testPathVariable(@PathVariable("id") Integer id,@PathVariable("name") String name) {
System.out.println(id);
return "success";
}
这里说一下rest风格的URL,rest风格的URL强调用不同的请求方式代表服务器端不同的操作,可以大致概括为服务器端的增删改查四个操作,即get请求代表查询、post请求代表增加、put请求代表更新、delete请求代表删除。但是在传递参数上面,键值对的参数格式也完全适用于rest风格的URL,比如说对应post的添加请求,前端将参数封装在请求体中,后端完全可以像以前一样,使用一个对象来接收参数,我曾经见过一个据说采用rest风格URL的项目中所有的请求方式全是post,这样完全可以进行操作,只是不太符合rest强调的优雅的URL的风格,而且要知道,post请求是要比get请求慢的,这一点感兴趣的可以自行百度。所以,总结来说,rest风格的URL也就两种传参方式:一种是像这样 /testPathvariable/user/1,后端就用占位符+@PathVariable("参数名")来接收参数,一般适用于get请求和delete请求,当然参数较多时,可以考虑适用post请求将参数封装到请求体中发送;另一种是像之前一样,在请求体中使用键值对格式,后端用对象或者多个参数来接收,只要保证键值对的参数key和入参的参数名一致就行。
目前,rest风格的URL还没有普及开来,前后端对接时大部分还是使用键值对或传递json字符串的形式,不过因为微服务和springCloud的流行,springCloud默认的服务调用组件ribbon,默认就是采用rest风格的URL来进行服务调用的,不过这种URL都是在各服务的内部进行调用,用户是看不到这种URL的。
3)@RequestHeader注解:获取请求头中的参数。
如:@RequestHeader(value="Accept-Language") 这是获取请求头中Accept-Language属性的值。
4)@CookieValue注解:获取cookie中某个键值对的值。
@CookieValue("JSESSIONID")获取JSESSIONID属性的值。
3、获取多个请求参数
使用POJO(普通的Java类)作为参数:按照请求参数名(name属性名)和POJO属性名进行自动匹配,自动通过setter方法为该对象填充属性值,且支持级联属性。
1.@RequestBody User user(推荐)
用实体类接收,json的key要和实体类属性一致。
2.@RequestBody Map
用map接收,json的key要和map的key一致
3.@RequestBody String str (这样是将整个json字符串赋值给str,不推荐)
用字符串接收,然后在自己解析json字符串
ok,结束,吃饭去。