Content-Type详解&SpringBoot中如何根据Content-Type解析数据

本文详细介绍了HTTP中Content-Type的作用,包括它的格式和在POST请求中的常见类型。此外,通过实例展示了SpringBoot如何根据Content-Type解析GET和POST请求中的数据,涉及实体类、参数、Map等不同接收方式。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Content-Type详解

Content-Type是什么?

在HTTP协议消息头中,使用Content-Type来表示媒体类型信息。它被用来告诉服务端如何处理请求的数据,以及告诉客户端(一般是浏览器)如何解析响应的数据,比如显示图片,解析html或仅仅展示一个文本等。

Post请求的内容放置在请求体中,Content-Type定义了请求体的编码格式。数据发送出去后,还需要接收端解析才可以。接收端依靠请求头中的Content-Type字段来获知请求体的编码格式,最后再进行解析。

Content-Type的格式

Content-Type:type/subtype ;parameter

type:主类型,任意的字符串,如text,如果是号代表所有;
subtype:子类型,任意的字符串,如html,如果是
号代表所有,用“/”与主类型隔开;
parameter:可选参数,如charset,boundary等。
例如:

  • Content-Type: text/html;
  • Content-Type: application/json;charset:utf-8;
  • Content-Type: application/x-www-form-urlencoded;charset:utf-8;

Post请求中常见的Content-Type类型的结构

(1)application/x-www-form-urlencoded

这是浏览器原生的form表单类型,或者说是表单默认的类型。

下面是一个请求实例:

img

请求报文:

img

可以看得出,post将请求参数以key1=value1&key2=value2这种键值对的方式进行组织,并放入到请求体中。其中中文或某些特殊字符,如"/“、”,“、“:” 等会自动进行URL转码。

(2)application/json

现在绝大部分的请求都会以json形式进行传输,post会将序列化后的json字符串直接塞进请求体中。

下面是一个请求实例:

img

请求报文:(postman查看请求报文,点击Send下面一行的code,然后点击HTTP即可)

img

可以看到,请求体中就是Json字符串。

(3)multipart/form-data

用于在表单中上传文件,先看一个请求实例:img

请求报文:

img

可以看得出,首先随机生成了一个boundary字段,这个boundary用来分割不同的字段。

一个请求的参数,会以boundary开始,然后是附加信息(参数名称,文件路径等),再空一行,最后是参数的内容。

请求体最后再以boundary结束。

当然,response中也会有Content-Type为multipart/form-data的响应头。如果此时是导出文件,则响应头还需要添加一个

Content-Disposition:attachment;fileName=文件.后缀

注:Content-Disposition是Content-Type的扩展,告诉浏览器弹窗下载框,而不是直接在浏览器里展示文件。因为一般浏览器对于它能够处理的文件类型,如txt,pdf 等,它都是直接打开展示,而不是弹窗下载框。


SpringBoot中如何根据Content-Type解析数据

首先定义一个User实体类:

@Data
class User {
    String name;
    int age;
 
    User() {
    }
 
    User(String name, int age) {
        this.name = name;
        this.age = age;
    }
}

一、接收get请求

(1)后端用实体类接收

    @GetMapping("/loginByUser")
    public User loginByUser(User user) {
        return user;
    }

前端则调用url:localhost:8080/user/loginByUser?name=tom&age=12

(2)后端用参数接收

    @GetMapping("/loginByParam")
    public User loginByParam(@RequestParam("name1") String name,
                             @RequestParam(value = "age", required = true, defaultValue = "20") int age) {
        return new User(name, age);
    }

前端则调用url:localhost:8080/user/loginByParam?name1=tom

@RequestParam注解将请求参数绑定到方法参数上。它有以下3个常用参数

  • value:用来声明请求参数中的参数名称。例子中将请求参数中的name1绑定到方法参数中的name字段。
  • required:当没声明其required时,默认是true。即如果前端没传入name1的话,后端则会报错。
  • defaultValue:当age参数的required=true时,而前端又没有传入这个参数时,则参数列表中的这个age将会有一个默认值。

此时情况下的@RequestParam注解,可加可不加。

(3)后端使用Map接收

    @GetMapping("/loginByMap")
    public User loginByMap(@RequestParam Map<String, Object> map) {
        String name = (String) map.get("name");
        int age = Integer.parseInt((String) map.get("age"));
        return new User(name, age);
    }

前端则调用url:localhost:8080/user/loginByMap?name=tom&age=12

值得注意的是,这里的map参数前需要加@RequestParam注解,用于将请求参数注入到map中。

(4)后端用路径接收

    @GetMapping("/loginByPath/{name}/{age}")
    public User loginByPath(@PathVariable("name") String name, @PathVariable("age") int age) {
        return new User(name, age);
    }

前端则调用url:localhost:8080/user/loginByPath/tom/12

@PathVariable注解用于将路径中的参数绑定到方法参数中

(5)后端用数组接收

    @GetMapping("/array")
    public Integer[] array(Integer[] a) {
        return a;
    }

前端则调用url:localhost:8080/user/array?a=1&a=2&a=3

当然,这里也可用List来接收,不过需要加上@RequestParam(“a”)注解

如果直接使用List来接收,也不加上@RequestParam(“a”)注解的话,则会报错

No primary or default constructor found for interface java.util.List


二、接收Post请求

(1)后端使用实体类进行接收,前端传入Content-Type:application/json格式的数据

    @PostMapping("/loginByUser")
    public User loginByUser(@RequestBody User user) {
        return user;
    }

@RequestBody注解用于将请求体中的json字符串转化为java对象

值得注意的是

  • 由于get无请求体,那么@RequestBody不能使用在get请求上。
  • @RequestBody与@RequestParam可以同时使用,@RequestBody最多只能有一个,而@RequestParam可以有多个。

如果这里的User对象,只有一个参数,比如name。那么这里也可以直接这样接收

    @PostMapping("/loginByUser")
    public User loginByUser(@RequestBody String name) {
        return user;
    }

postman传参则直接这样传参

img

但其实并不推荐这样,一个参数也是可以用get传参的。

(2)后端使用实体类进行接收,前端传入Content-Type:application/x-www-form-urlencoded格式的数据

    @PostMapping("/loginByUser")
    public User loginByUser(User user) {
        return user;
    }

Content-Type:application/x-www-form-urlencoded格式的数据,数据会以key/value格式进行传输,SpringMvc会直接将请求体中的参数直接注入到对象中。

(3)后端使用参数进行接收,前端传入Content-Type:application/x-www-form-urlencoded格式的数据

    @PostMapping("/loginByParam")
    public User loginByParam(@RequestParam("name1") String name,
                             @RequestParam(value = "age", required = true, defaultValue = "20") int age) {
        return new User(name, age);
    }

此时的@RequestParam注解加不加都无所谓

(4)后端使用Map来接收,前端传入Content-Type:application/x-www-form-urlencoded格式的数据

    @PostMapping("/loginByMap")
    public User loginByMap(@RequestParam Map<String, Object> map) {
        String name = (String) map.get("name");
        int age = Integer.parseInt((String) map.get("age"));
        return new User(name, age);
    }

这里类似于get请求的(3),同样,map参数前需要加@RequestParam注解,用于将请求参数注入到map中。

值得注意的是,由于form表单形式是以key/value形式存储,都是字符串类型,因此需要将map.get(“age”)转化为String,再转化为Integer,最后再自动拆箱。

不可以将map.get(“age”)直接转化为Integer类型,因为其本质是String类型,String不能直接强转为Integer。

(5)后端使用Map来接收,前端传入Content-Type:application/json格式的数据

    @PostMapping("/loginByMap")
    public User loginByMap(@RequestBody Map<String, Object> map) {
        String name = (String) map.get("name");
        int age = (Integer) map.get("age");
        return new User(name, age);
    }

这里类似于post请求的(1),同样,@RequestBody注解用于将请求体中的json字符串转化为对象属性,并注入到map中。

由于请求体中json中的age类型为number类型,因此注入到map中时,age是Integer类型,那么可以直接强转为Integer类型。

(6)后端使用JSONObject来接收,前端传入Content-Type:application/json格式的数据

    @PostMapping("/loginByJSONObject")
    public User loginByJSONObject(@RequestBody JSONObject jsonObject) {
        String name = jsonObject.getString("name");
        int age = jsonObject.getInteger("age");
        return new User(name, age);
    }

@RequestBody注解用于将请求体中的json字符串转化为JSON对象。

(7)后端使用数组来接收

    @PostMapping("/array")
    public Integer[] array(Integer[] a) {
        return a;
    }

前端传入Content-Type:application/x-www-form-urlencoded格式的数据,后端可以直接接收到。如图

img

但传入Content-Type:application/json格式的数据[1,2,3],后端则接收不到,需要加入@RequestBody注解。

当然(@RequestBody List a)也是可以的。


总结:

@PathVariable、@RequestParam与@RequestBody注解三者的区别

注解支持的类型支持的请求类型支持的Content-Type请求示例
@PathVariableurlGET所有/test/{id}
@RequestParamurlGET所有/test?id=1
BodyPOST/PUT/DELETE/PATCHform-data或x-www.form-urlencodedid:1
@RequestBodyBodyPOST/PUT/DELETE/PATCHjson{“id”:1}

如果前端传入Content-Type:application/json格式的数据,直接使用@RequestBody注解将json字符串转化为对象。

如果前端传入Content-Type:application/x-www-form-urlencoded格式的数据,如果能够得出方法参数具有的属性和请求参数一样的属性时,则不需要@RequestParam注解。例如注入到Map中,则需要@RequestParam注解。

如果后端已经使用了@RequestBody注解,代表只接收application/json类型的数据,此时若再传入application/x-www-form-urlencoded类型的数据,则后台会报错

“status”: 415,

“error”: “Unsupported Media Type”,

“message”: “Content type ‘application/x-www-form-urlencoded;charset=UTF-8’ not supported”

另外,get请求的请求头没有Content-Type字段。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值