一、先来看一个常见的异常
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、请求的数据格式的区别
- 因为content-Type是用来表示请求体的类型的,默认值为默认为application/x-www-form-urlencoded; charset=UTF-8,这个称为MIME类型。get请求没有请求体,所以就没有content-Type属性;post请求有请求体,所以就会有content-Type属性。
- form表单的默认MIME类型也是application/x-www-form-urlencoded,即enctype="application/x-www-form-urlencoded",如果是文件上传则enctype="multipart/form-data"
- 键值对格式:name=www&url=www&checked=true&pId=6
常见场景
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格式
2、获取请求参数(总结一下)
键值对格式
1、只要保证请求的参数名和处理器方法的形参名称一致,自动绑定成功。
2、获取单个请求参数
1)@RequestParam注解:获取一个请求参数,并赋值给一个形参
属性
@RequestParam(value="password",required=false,defaultValue="0") int password
required:设置属性是否为必须的,默认为true。可以设置其值为false,即当没有该属性时也不会报错。
defaultValue:当required=false时使用,设置请求参数的默认值,不能单独使用。
2)@PathVariable 注解:针对rest风格的url,可以将url的占位符参数,绑定到处理器方法的入参处
<a href="/springmvc/testPathvariable/12/tom">testPathvariable</a>
@RequestMapping("/testPathvariable/{id}/{name}")
public String testPathVariable(@PathVariable("id") Integer id,@PathVariable("name") String name) {
System.out.println(id);
return "success";
}
3)@RequestHeader注解:获取请求头中的参数。
如:@RequestHeader(value="Accept-Language") 这是获取请求头中Accept-Language属性的值。
4)@CookieValue注解:获取cookie中某个键值对的值。
@CookieValue("JSESSIONID")获取JSESSIONID属性的值。
3、获取多个请求参数
使用POJO(普通的Java类)作为参数:按照请求参数名(name属性名)和POJO属性名进行自动匹配,自动通过setter方法为该对象填充属性值,且支持级联属性。
json格式
1.@RequestBody User user(推荐)
用实体类接收,json的key要和实体类属性一致。
2.@RequestBody Map<String,Object> map(次推荐)
用map接收,json的key要和map的key一致
3.@RequestBody String str (这样是将整个json字符串赋值给str,不推荐)
用字符串接收,然后在自己解析json字符串
ok,结束,吃饭去。