一篇解决springMVC前后端参数传递问题

一、先来看一个常见的异常

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、请求的数据格式的区别

  1. 因为content-Type是用来表示请求体的类型的,默认值为默认为application/x-www-form-urlencoded; charset=UTF-8,这个称为MIME类型。get请求没有请求体,所以就没有content-Type属性;post请求有请求体,所以就会有content-Type属性。
  2. form表单的默认MIME类型也是application/x-www-form-urlencoded,即enctype="application/x-www-form-urlencoded",如果是文件上传则enctype="multipart/form-data"
  3. 键值对格式: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的占位符参数,绑定到处理器方法的入参处

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方法为该对象填充属性值,且支持级联属性

       json格式

     1.@RequestBody User user(推荐)

             用实体类接收,json的key要和实体类属性一致。

     2.@RequestBody Map map(次推荐)

             用map接收,json的key要和map的key一致

     3.@RequestBody String str (这样是将整个json字符串赋值给str,不推荐)

             用字符串接收,然后在自己解析json字符串

 

 

 

ok,结束,吃饭去。

 

 

 

 

 

你可能感兴趣的:(日常开发小问题,springMVC,json格式,参数传递,contentType)