• 【原创】浅谈ajax和axios的使用不同点和,以及SpringMvc接收参数的形式


    引言

    有很多人的误区就是使用axios或者ajax传递json参数时,后端必须要用某种手段处理,例如 很多人认为axios传递json必须用mvc的@RequestBody处理,因为axios默认的ContentType为 application/json ,这种‘必须’的表述是错误的,是对编程的误解,程序不是一成不变的。

    我们在入门时常用form表单进行数据提交操作,此时的请求头中使用的 content-type 是 application/x-www-form-urlencoded 也就是formData 表单格式数据,表单格式的数据传递特点就是key value形式的键值对,form表单会进行处理成 "name=xxx&age=xxx" 的形式。如下

    <form action="http://localhost:8080/user/login1.do" method="post">
       用户名<input type="text" v-model="formData.username" name="username"><br>
       密码<input type="password" v-model="formData.password" name="password" ><br>
       <input type="submit" value="提交">
    </form>

     

    后端使用springmvc取值,这也是最常规的取值方案了

    @RequestMapping("/login1")
    @ResponseBody
    public Result login1(String username,String password){
       System.out.println("login1>>>>>>>u:"+username+",p:"+password);
       return new Result(true,"登录成功");
    }

     Ajax

    我们在引言中清楚的知道了form表单的传参特性,下面来讲一下ajax,此时我们来试一下

     var vue = new Vue({
       .....
       data: {
       //  提交给后台的数据 都是在data中声明的
           formData: {
              username: '',
              password: ''
           },
      .....    
     let baseUrl = "http://localhost:8080/user/login1.do";
    // 发送 post 请求
    $.ajax({
         url: baseUrl,
         async: true,
         data: this.formData,
         success: function (res) {
             console.log(res)
          },
          type: "post",
          dataType: "json"
    })

    后端接收

    @RequestMapping("/login2")
    @ResponseBody
    public Result login2(LoginParam param) {
      System.out.println("login2>>>>>>>u:" + param.getUsername() + ",p:" + param.getPassword());
      return new Result(true, "登录成功");
    }

    从案例中我们发现 ajax 的默认的contentType 也是 application/x-www-form-urlencoded,并且和form标签做了相同的事情,那就是对一个json格式的数据进行了格式转换,也变成了form标签中的处理格式 "name=xxx&age=xxx" ,这里也是很多人的误区,很多人认为json只能用@RequestBody 搭配 application/json使用,却没有注意到ajax默认的ConentType也是formData,后端也是常规的接收方式不多赘述。 springmvc传参 https://www.cnblogs.com/xiaozhang666/p/13657846.html

    扩展  ajax对应@RequestBody的接收

    在使用是必须将contentType改为  application/json 并且 json转为json字符串,如下

    $.ajax({
        url: baseUrl,
        async: true,
        data: JSON.stringify(this.formData),
        contentType: "application/json",
        success: function (res) {
           console.log(res)
        },
        type: "post",
        dataType: "json"
    })

     后端接受

        @RequestMapping("/login3")
        @ResponseBody
        public Result login3(@RequestBody LoginParam param) {
            System.out.println("login3>>>>>>>u:" + param.getUsername() + ",p:" + param.getPassword());
            return new Result(true, "登录成功");
        }

    Axios

    使用过的人知道 axios的contentType默认为  application/json

    对于get方式的query传值并没有多大影响,只是data字段换为params

    let baseUrl = "http://localhost:8080/user/login1.do";
    // 发送 get 请求
    axios({
      method: 'get',
      url: baseUrl,
      params: this.formData
    }).then((res) => {
      console.log(res);
    })

    我们发现此时的 contentType在 axios 中的get请求并没有明确的指定,其实ajax的get时也没有明确指出。

    如图 params 给我们做的事就是把一个json格式的数据转换为 键值对并且把它拼接到url地址上,等效于

    "http://localhost:8080/user/login1.do?username=" + this.formData.username + "&password=" + this.formData.password

    重点

    一、axios   的 application/json 传递参数

    上面说过 axios的contentType默认为  application/json 那么我们试验一下post传递json格式

    let baseUrl = "http://localhost:8080/user/login3.do";
    // 发送 post 请求
    axios({
      method: 'post',
      url: baseUrl,
      data: this.formData
    }).then((res) => {
      console.log(res);
    })

     后端接收

    @RequestMapping("/login3")
    @ResponseBody
    public Result login3(@RequestBody LoginParam param) {
      System.out.println("login3>>>>>>>u:" + param.getUsername() + ",p:" + param.getPassword());
      return new Result(true, "登录成功");
    }

    我们此时发现这种axios写法完全等效于ajax的以下写法。。

    $.ajax({
        url: baseUrl,
        async: true,
        data: JSON.stringify(this.formData),
        contentType: "application/json",
        success: function (res) {
           console.log(res)
        },
        type: "post",
        dataType: "json"
    })

    就连后端接收参数都相同,那此时很明显 axios替我们做了ajax中的 JSON.stringify(this.formData) 的功能,就是将json 转换成为json字符串。

    二、axios   的 application/x-www-form-urlencoded  传递参数 也就是 表单formData

    上面的ajax默认为表单传递参数,直接传json时ajax把json转为键值对模仿了表单传递。那么我们有一个大胆的假设,将axios的contentType设置为 application/x-www-form-urlencoded ,这样我们是不是也可以用标准的json格式和常规的springmvc获取参数的形式获取到参数呢,而不再使用  application/json 搭配 @RequestBody了。

    直接开搞,将请求头 Content-Type 重新设置

    let baseUrl = "http://localhost:8080/user/login1.do";
    // 发送 post 请求
    axios({
      headers: {'Content-Type': 'application/x-www-form-urlencoded'},
      method: 'post',
      url: baseUrl,
      data: this.formData
    }).then((res) => {
      console.log(res);
    })

    java常规接收

    @RequestMapping("/login2")
    @ResponseBody
    public Result login2(LoginParam param) {
       System.out.println("login2>>>>>>>u:" + param.getUsername() + ",p:" + param.getPassword());
       return new Result(true, "登录成功");
    }

    第一次结果

    我们发现ContentType的值修改了,但是formData的格式却成了一个json字符串格式,并不是from表单标准的键值对 "name=xxx&age=xxx" 格式,所以常规的参数绑定无法接收到参数,这里查了一下资料,这里需要手动的转换一下,将json转换为键值对,用axios文档提供的第三方 Qs.stringify() 方法转换。

    https://github.com/ljharb/qs  下的 dist  的 qs.js 进行引入到你的项目中。

    let baseUrl = "http://localhost:8080/user/login1.do";
    // 发送 post 请求
    axios({
       headers: {'Content-Type': 'application/x-www-form-urlencoded'},
       method: 'post',
       url: baseUrl,
       data: Qs.stringify(this.formData)
    }).then((res) => {
       console.log(res);
    })

    这样我们再试一下

     此时发现不同了,那就是原本的json串被转换成了键值对的形式,那么现在已经符合了form表单的发送数据的格式,我们再看看后端

     已经取到了。

    最后总结几点

    1. axios替我们做了json 转 json串的工作,JSON.stringify(this.formData)。
    2. ajax替我们做了 json转键值对的工作  ,Qs.stringify(this.formData)。
    3. 两种异步请求方法都没有硬性的要求,只不过是ContentType的转变。
    4. application/x-www-form-urlencoded 属性要传键值对,application/json 属性传值为 json字符串

     补充一种请求

    axios.post("http://localhost:8080/user/login1.do", "username=" + this.formData.username + "&password=" + this.formData.password, {
        headers: {'content-type': 'application/x-www-form-urlencoded'},
    }).then((response) => {
        //response.data就是服务器端返回的内容(例如json)
        console.log(response.data);
    }).catch((error) => {
        console.log(error);
        this.$message.error("网络异常");
    });

    此请求虽然是url拼接,但是不会出现在url中,因为是post

  • 相关阅读:
    推荐随笔
    搭建http服务
    python之numpy和pandas
    eclipse项目打包
    keras安装
    eclipse设置快速提示符
    linux常用命令
    Webpack3 从入门到放弃
    【ES6】Generator+Promise异步编程
    【Vue】删除数组元素,导致剩余元素被重新渲染
  • 原文地址:https://www.cnblogs.com/xiaozhang666/p/13693123.html
Copyright © 2020-2023  润新知