不同的contentType下SpringMVC如何获取到参数

版本:Java + Springboot2.0
快速测试环境:github地址

1. Jquery版本Ajax请求的格式

代码如下:

    $.ajax({
        type: "get"
        , url: "/test"
        , data: ""
        ,contentType: "application/json; charset=utf-8"
        , dataType: 'json'
        , success: function (res) {
           
        }
    });
  • type 控制请求的方式
  • url 是请求的链接
  • data 发送的数据
  • contentType 发送数据的格式
  • dataType 服务端返回数据的格式

可以看得到我们怎么发送数据,服务端怎么接收数据最直接的影响就是contentType的设置,我们下面以两种常见的ContentType为界限,来看各种类型(type:post/get等)的请求如何发送参数。

2. 默认(不写)ContentType

在jquery的ajax方法中,默认的ContentType的值为:application/x-www-form-urlencoded; charset=UTF-8
此格式为表单提交格式,最终提交给后台的数据为key1=value1&key2=value2的格式 。
虽然ajax的data属性值格式为:{key1:value1,key2:value2},但最后会转为key1=value1&key2=value2的格式提交到后台 ,如果ajax要和springmvc交互,key1=value1&key2=value2的格式,后台springmvc只需要定义对象或者参数就行了,框架会自动映射。
下面是一个例子:
发送的数据是data变量,ajax请求如下,注意没有写contentType

function test() {
    var data = {
        code : "code",
        name : "name"
    };
    $.ajax({
        type: "get"
        , url: "/test"
        , data: data
        , dataType: 'json'
        , success: function (res) {
        }
    });
}

我们用chrome浏览器看看到底发给后台的数据是什么,截图如下:
1.png

注意看URL,由于是GET请求,所以会把参数拼接在后面,或者看下面的红框中的参数也是同样的。
后台的接收方式如下:

@RequestMapping(value = "/test", method = RequestMethod.GET)
public void test(String code, String name) {
    System.out.println(code);
    System.out.println(name);
}

并且打印出来了

code
name

上面是GET方式请求的例子,那么我们再继续测试RESTFUL风格中的其他请求方式。
其中RESTFUL风格的写法如下:

  • 获取:使用GET方法获取资源。GET请求从不改变资源的状态。无副作用。GET方法是幂等的。GET方法具有只读的含义。因此,你可以完美的使用缓存。
  • 创建:使用POST创建新的资源。
  • 更新:使用PUT更新现有资源。
  • 删除:使用DELETE删除现有资源。

具体的可以参考这篇博客[译] RESTful API 设计最佳实践

2.1 POST请求 (用复杂对象接收)

发送的请求和数据如下:
可以看到我们把数据变化了下,code传入的是一个js object对象了

	function test() {
        var code = {
          key : "11",
          value : 12
        };
        var data = {
            code : code,
            name : "name"
        };
        $.ajax({
            type: "post"
            , url: "/test"
            , data: data
            // ,contentType: "application/json; charset=utf-8"
            , dataType: 'json'
            , success: function (res) {
            }
        });
    }

看一下请求头发送的都是什么:
2.png

所以这样后台获取code就获取不到了,分析一下上面传递过去的格式,明显code是一个键值对的格式,我们用一个对象去接收。对象代码如下:

public class ViewModel {
    private Map<String, Object> code;
    private String name;
   }

后台接收如下:

@RequestMapping(value = "/test", method = RequestMethod.POST)
    public void test(Map<String, Object> viewModel) {
        System.out.println(iewModel);
    }
// 打印结果:
// 值为:ViewModel{code={key=11, value=12}, name='name'}

这样可以接收到传递过去的数据,但是如果直接在参数把code写成一个Map的形式式获取不到值的:

	@RequestMapping(value = "/test", method = RequestMethod.POST)
    public void test(Map<String, Object> code, String name) {
        System.out.println("code为:" + code);
        System.out.println("name为:" + name);
    }
    // 打印结果:
    //  code为:{}
	//  name为:name

原因后面继续追踪。

2.2 PUT请求 (如何获取Json字符串)

这次我们用put进行请求,并且我们想获取到的code不再是一个js对象,而是一个JSON字符串,我们需要用**JSON.stringify(code)**方法把一个js对象处理成字符串。

	function test() {
        var code = {
          key : "11",
          value : 12
        };
        var data = {
            code : JSON.stringify(code),
            name : "name"
        };
        $.ajax({
            type: "put"
            , url: "/test"
            , data: data
            , dataType: 'json'
            , success: function (res) {
            }
        });
    }

观察请求头的内容如下:

3.png

可见我们以及发送一个String类型的code过去了,我们用老方式去接收,如下:

@RequestMapping(value = "/test", method = RequestMethod.PUT)
    public void test(String code, String name) {
        System.out.println("code为:" + code);
        System.out.println("name为:" + name);
    }
    // 打印结果
    // code为:{"key":"11","value":12}
	// name为:name

拿到了JSON字符串我们在利用Gson等工具包处理成我们想要的类即可。

2.3 DELETE请求(和其他的不太一样)

我们按照以上的方式去请求,一切都和以前一样,结果居然后台code和name都获取不到。

	function test() {
        var data = {
            code : "code"
            name : "name"
        };
        $.ajax({
            type: "delete"
            , url: "/test"
            , data: data
            , success: function (res) {
            }
        });
    }

很奇怪,去网上查了一下资料发现,jquery对delete处理比较独特,DELETE请求方式是基于POST请求方式,必须在表单提交中写上一个隐藏域,而且必须将name设置为**_method**,value属性值写上对应的请求方式。
具体写法如下,注意看与上面代码不同的地方:

function test() {
        var data = {
            code : "code",
            name : "name"
        };
        // DELETE方式独有
        data["_method"] = 'DELETE';
        $.ajax({
	        // 注意改为了post
            type: "post"
            , url: "/test"
            , data: data
            , success: function (res) {
            }
        });
    }

这样按照原来的后台,结果如下:

	@RequestMapping(value = "/test", method = RequestMethod.DELETE)
    public void test(String code, String name) {
        System.out.println("code为:" + code);
        System.out.println("name为:" + name);
    }
    // 打印结果:
    // code为:code
    // name为:name
3. ContentType 设置为 application/json; charset=UTF-8

如果springmvc的参数有@RequestBody注解(接收json字符串格式数据),则ajax请求必须将data属性值转为json字符串,不能为json对象(js对象,会自动转为key=value形式)。
然后再修改contentType的值为:application/json; charset=UTF-8,这样加了@RequestBody注解的属性才能自定映射到值。

3.1 以POST请求为例

我们发送请求的数据如下:
这其中需要注意的是

  • 设置了contentTpye
  • data是一个js对象,传过去必须要JSON.stringify(data),转化成json字符串才行。
	function test() {
        var code = {
          key : "11",
          value : 12
        };
        var data = {
            code : code,
            name : "name"
        };
        $.ajax({
            type: "post"
            , url: "/test"
            , data: JSON.stringify(data)
            ,contentType: "application/json; charset=utf-8"
            , success: function (res) {
            }
        });
    }

以这样为请求方式,我们看一下发送的请求头的样子:
4.png
可以看到,发送过去的数据确确实实变成了json格式的,然后springmvc会自动调用Jackson,将json字符串转化成我们想要的格式。所以我们后头接收如下:

	@RequestMapping(value = "/test", method = RequestMethod.POST)
    public void test(@RequestBody Map<String, Object> viewModel) {
        System.out.println("值为:" + viewModel);
    }
    // 打印结果:
    // 值为:{code={key=11, value=12}, name=name}

同样,如果我们想用自定义的类去接收,去定义好类,并且把json中的健和值对应上即可。

4. HTTP头 Content-Type

  • 作用:contentType的作用是用来标识发送或者接收数据的MIME类型。
  • 格式:type/subtype(;parameter)? type
    • 样例:Content-Type:application/json;charset=GBK
    • type代表主类型,比如application
    • subtype代表副类型,比如json
    • parameter可选,比如charset
    • 其中*代表所有类型
5. 常见的contentType类型

  1. 主类型为text的
    text/html : HTML格式
    text/plain :纯文本格式
    text/xml : XML格式
    image/gif :gif图片格式
    image/jpeg :jpg图片格式
    image/png:png图片格式
  2. 以application开头的媒体格式类型:
    application/xml : XML数据格式
    application/atom+xml :Atom XML聚合格式
    application/json : JSON数据格式
    application/pdf :pdf格式
    application/msword : Word文档格式
    application/octet-stream : 二进制流数据(如常见的文件下载)
END
参考

Http协议之Content-Type
Ajax发送PUT/DELETE请求时出现错误的原因及解决方案
@RequestBody, @ResponseBody 注解详解
SpringMVC中ajax传值的几种接收方式

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值