Content-Type+前端axios传值方式---springboot接收前端参数方式

知识巩固

先来熟悉下,前端给后端传值的时候有哪几种方式呢?

  • HTML标签的form表单提交(GET、POST方式提交)
  • Jquery中的ajax方式提交
  • 其他的一些如axios(其实就是封装了ajax)

GET、POST区别

那么说到了Form表单提交,有必要再去了解下,form表单中,提交方式get和post的区别,这里借用一下网上的图来说明一下。

一个HTTP请求,一般包含以下几个内容:

  • 请求行(请求地址…)

  • 请求头(头部信息…)

  • 请求体(可存储数据)

  • 请求空行(HTTP协议数据规范)

在这里插入图片描述

那么GET和POST提交方式的区别如上图所示:

  • 在请求行中,POST方式不会把数据暴露出来,GET会暴露数据,但是GET方式处理数据的效率优于POST方式,根据情况取舍
  • POST方式会把数据处理好后,放入到请求体中

Content-Type

Content-Type,内容类型,一般是指网页中存在的Content-Type,用于定义网络文件的类型和网页的编码,决定文件接收方将以什么形式、什么编码读取这个文件 --百度百科

说白了,就是比如两个人要进行数据的传递,那么这两个人定义好一个内容类型,一方以这种内容类型传递数据,另一方要遵守规定也以这种内容类型进行读取传输过来的数据。

Content-Type有哪些类型:(常见的)

  • application/x-www-form-urlencoded: 标准表单编码类型

    请求体中的数据会以普通表单形式(键值对)发送到后端

  • multipart/form-data:类型

    它会将请求体的数据处理为一条消息,以标签为单元,用分隔符分开。既可以上传键值对,也可以上传文件

  • application/json: json类型

    请求体中的数据会以json字符串的形式发送到后端

  • application/xml: xml类型

前端知识 使用axios时怎么传值

  • Content-Type: application/json时

    let params = {
          
          'title':'test', 'sub' : [1,2,3]}
    axios({
          
          
        method: 'post',
        url: '/api/lockServer/search',
        params
    })
    
    最终发送的请求是 
    {
          
          "title":"test","sub":[1,2,3]}
    
  • Content-Type: application/x-www-form-urlencoded 时

    不设置Content-Type,使用URLSearchParams

    const params = new URLSearchParams();
    params.append('param1', 'value1');
    params.append('param2', 'value2');
    axios.post('/foo', params);
    

    使用qs库编码数据(需要设置Content-Type)

    import qs from 'qs';
    const data = {
          
           'bar': 123 };
    const options = {
          
          
      method: 'POST',
      headers: {
          
           'content-type': 'application/x-www-form-urlencoded' },
      data: qs.stringify(data),
      url,
    };
    axios(options);
    
  • Content-Type: multipart/form-data时

    采用FormData方式

    import axios from 'axios'
    let data = new FormData();
    data.append('code','1234');
    data.append('name','yyyy');
    axios.post(`${
            
            this.$url}/test/testRequest`,data)
    .then(res=>{
          
          
        console.log('res=>',res);            
    })
    

request的Content-Type

一般我们在开发的过程中需要注意客户端发送请求(Request)时的Content-Type设置,特别是使用ajax的时候,如果设置得不准确,很有可能导致请求失败。比如在spring中,如果接口使用了@RequestBody,spring强大的自动解析功能,会将请求实体的内容自动转换为Bean,但前提是请求的Content-Type必须设置为application/json,否正就会返回415错误。
注:415 错误是 Unsupported media type,即不支持的媒体类型。
建议:

  • 如果是一个restful接口(json格式),一般将Content-Type设置为application/json; charset=UTF-8;
  • 如果是文件上传,一般Content-Type设置为multipart/form-data
  • 如果普通表单提交,一般Content-Type设置为application/x-www-form-urlencoded

response的Content-Type

服务端响应(Response)的Content-Type最好也保持准确,虽然一般web开发中,前端解析响应的数据不会根据Content-Type,并且服务端一般能自动设置准确的Content-Type,但是如果乱设置某些情况下可能会有问题,比如导出文件,打开图片等。如果在spring项目里使用@ResponseBody,spring会将响应的Content-Type设置为application/json;charset=UTF-8;,可能会导致文件无法导出,需要注意下。

建议:

  • 一般情况下不需要显示设置;
  • 如果是文件导出,Content-Type 设置为 multipart/form-data,并且添加一个Content-Disposition设置为attachment;fileName=文件.后缀。(用springboot做过文件下载的应该比较熟悉这点)
  • 注:Content-Disposition是Content-Type的扩展,告诉浏览器弹窗下载框,而不是直接在浏览器里展示文件。因为一般浏览器对于它能够处理的文件类型,如txt,pdf 等,它都是直接打开展示,而不是弹窗下载框。

SpringBoot接收参数几种方式

进入正题。。

首先,学过springmvc应该知道,后端常用接收参数的几种方式有:

  • 无注解 (普通类型、对象类型)

  • @RequestParam

  • @RequestBody

  • @PathVariable

  • HttpServletRequest

其中有一个小细节,可能大多数人都忽略了,那就是:

​ 当使用注解方式+限制必传(默认的就是必传)时,前端必须给我传这个参数,否则直接告诉他4xx(客户端错误),这个大家应该都知道。当使用无注解HttpServletRequest时,如果前端没有把值传过来或者数据丢了,那么后端不会去报错,而是给一个默认值(普通类型(比如int类型默认0)和引用类型的默认值(null)),继续执行代码。

无注解接收参数

先准备一个User类,方便后面使用

@Data
public class User {
    
    
    private String name;
    private String age;
}
// 普通类型
@GetMapping("/test1")
public void test1(String name, Integer age) {
    
    
    System.out.println(name);
    System.out.println(age);
}

// 对象类型
@GetMapping("/test2")
public void test2(User user) {
    
    
    System.out.println(user);
}

普通类型

数据放入请求行

还不清楚请求行的,去上面看一下介绍就明白了。

在这里插入图片描述

控制台打印:

zs
21

数据放入请求体

在这里插入图片描述

控制台打印:

zs
21

对象类型

数据放入请求行

在这里插入图片描述

控制台打印:

User(name=zs, age=21)

数据放入请求体

在这里插入图片描述

控制台打印:

User(name=zs, age=21)

结论

无论是普通类型还是对象类型,放入请求行还是请求体,都能把数据读取出来。

@RequestParam注解

使用@RequestParam注解时要注意,此注解一般使用在普通类型的属性上,因为对象类型的时候,你的值根本就不好传,当然像一些好传值的类型是可以用的,比如 List、数组…

@GetMapping("/test3")
public void test3(@RequestParam String name, @RequestParam String age) {
    
    
    System.out.println(name);
    System.out.println(age);
}

@GetMapping("/test4")
public void test3(@RequestParam List<Integer> ids) {
    
    
    System.out.println(ids);
}

普通类型

放入请求行

在这里插入图片描述

控制台打印:

zs
21

放入请求体

在这里插入图片描述

控制台打印:

zs
21

对象类型

放入请求行

在这里插入图片描述

控制台打印:

[1, 2, 3]

放入请求体

在这里插入图片描述

控制台打印:

[1, 2, 3]

结论

使用@RequestParam注解时,和不使用注解一样,都可以接收到请求行请求体中的数据。

但是要注意下,不使用注解时,不传值时会给属性默认值。

@RequestBody

使用@RequestBody,后端接收Content-Type是application/json类型的json数据,且数据都是放入请求体的,Content-Type如果不对,则会报错,一般就是不支持Content-Type类型之类的,协商一下改一下就行。

@GetMapping("/test6")
public void test6(@RequestBody User user) {
    
    
    System.out.println(user.toString());
}

@GetMapping("/test7")
public void test7(@RequestBody Map<String, Object> map) {
    
    
    System.out.println(map.toString());
}

@GetMapping("/test8")
public void test8(@RequestBody List<Integer> ids) {
    
    
    System.out.println(ids);
}

@GetMapping("/test9")
public void test9(@RequestBody int[] ids) {
    
    
    System.out.println(ids);
}

test6(User类型)

请求体中的数据

在这里插入图片描述

控制台输出:

User(name=zs, age=21)

test7(Map类型)

在这里插入图片描述

控制台输出:

{
    
    name=zs, age=21}

test8(集合类型)

在这里插入图片描述

控制台打印:

[1, 2, 3]

这里一定是要注意的:

当我们接收的是集合或者数组的时候,前端传过来的一定不能是json对象,而是一个json数组,切记!!!

test9就不演示了,和test8是一模一样的,也是接收的json数组。

@PathVariable

这种就是直接把参数值给拼接到url中,然后后端直接读取就可以了

当不传值时,由于url匹配不到,就直接404了

@GetMapping("/test5/{id}")
public void test5(@PathVariable Integer id) {
    
    
    System.out.println(id);
}

在这里插入图片描述

控制台打印:

1

HttpServletRequest

接收的参数就是一个HttpServletRequest对象,然后从这个Request对象里取数据即可。

@GetMapping("/test10")
public void test10(HttpServletRequest request) {
    
    
    String name = request.getParameter("name");
    String age = request.getParameter("age");
    String age2 = request.getParameter("age2");
    System.out.println(name);
    System.out.println(age);
    System.out.println(age2);
}

请求行

在这里插入图片描述

控制台打印:

zs
21
null

请求体

在这里插入图片描述

控制台输出:

zs
21
null

结论:

和其他方式一样,都可以从请求行和请求体中读取到数据。数据没有传输过来那就采用默认值的方式。

如果请求行和请求体都传数据

平时应该遇不到这样的问题,但是还是了解下吧,不然后面真遇到了,就直接蒙圈了。

  • 请求行和请求体中传输的数据都是不同名的:

    这种是没有任何问题的,相当于是我一些数据从请求行传过去,一些数据从请求体中传过去,能正常接收

  • 请求行和请求体中传输的数据有同名的:

    这种请求,我试了两个类型,其他的暂时没有试。如果是String类型的参数,那么它会先读取到请求体中的数据,请求行如果有同名的属性,那么会把值 拼接到从请求体读取到的数据上,逗号分割。如zs,ls

    如果是Integer类型,那么它只会以请求体中的数据为准(同样是先读取请求体,然后如果请求行中有同名,直接过滤掉了–个人理解)

    其他类型没有深究,有兴趣的可以去试试。如果后面遇到这种问题,这是一种排错的方式,仅供参考。

参考

Content-Type详解

Form表单的提交方式

SpringBoot 出现 Content type ‘application/x-www-form-urlencoded;charset=UTF-8’ not supported

前端axios配置Content-Type

猜你喜欢

转载自blog.csdn.net/weixin_45248492/article/details/124708386