AJAX 发送GET、POST和复杂请求

1 概述

  1. 同步和异步
    • 前提条件:客户端和服务器端相互通信的前提下
    1. 同步:客户端必须等待服务器端的响应。在等待的期间客户端不能做其他操作。
    2. 异步:客户端不需要等待服务器端的响应。在服务器处理请求的过程中,客户端可以进行其他的操作。
  2. AJAX 是 ASynchronous JavaScript And XML 的简写,即 AJAX = 异步 JavaScript 和 XML。
  3. 其他基础知识参考博客 AJAX入门介绍

2 普通请求

  1. 前台
    <!DOCTYPE html>
    <html lang="zh-cn">
    
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>ajax请求测试</title>
    </head>
    
    <body>
        <input id="btn1" type="button" value="get无参请求"></input>
        <input id="btn2" type="button" value="get有参请求"></input>
        <input id="btn3" type="button" value="post无参请求"></input>
        <input id="btn4" type="button" value="post有参请求"></input>
    
        <script src="https://code.jquery.com/jquery-3.1.1.min.js"></script>
        <script>
            $(function () {
                $('#btn1').click(function () {
                    $.ajax({
                        type: "get",
                        url: "http://localhost:8080/ajax/get1",
                        data: {},
                        dataType: "json",
                        success: function (res) {
                            console.log(res);
                        },
                        error: function (err) {
                            console.log(JSON.stringify(err));
                        }
                    })
                });
                
                $('#btn2').click(function () {
                    $.ajax({
                        type: "get",
                        url: "http://localhost:8080/ajax/get2",
                        data: {
                            "name": "newlife",
                            "age": 18
                        },
                        dataType: "json",
                        success: function (res) {
                            console.log(res);
                        },
                        error: function (err) {
                            console.log(JSON.stringify(err));
                        }
                    })
                });
                
                $('#btn3').click(function () {
                    $.ajax({
                        type: "post",
                        url: "http://localhost:8080/ajax/post1",
                        /**
                         * 后台 java 用 @RequestBody 接收参数
                         * 即使参数为空vo,也不能写成 data: {}, 
                         * 因为 @RequestBody 接收的是 json 字符串
                         * 而 type: "post" 默认发送的是 json 对象
                         * 因此造成参数类型不匹配错误,无法请求到预期结果!!!
                         * 
                         * 若是报 HttpMediaTypeNotSupportedException 错误
                         * 则加上 contentType: "application/json"
                         * 
                         * 总结:ajax 请求后台带有 @RequestBody 时
                         * contentType 、 dataType 和 JSON.stringify( obj ) 这三个最好都写上
                         */
                        // data: {},
                        data: JSON.stringify({}),
                        contentType: "application/json",
                        dataType: "json",
                        success: function (res) {
                            console.log(res);
                        },
                        error: function (err) {
                            console.log(JSON.stringify(err));
                        }
                    })
                });
                
                $('#btn4').click(function () {
                    $.ajax({
                        type: "post",
                        url: "http://localhost:8080/ajax/post2",
                        data: JSON.stringify({
                            "address": "luoyang",
                            "hobbies": "dance"
                        }),
                        contentType: "application/json",
                        dataType: "json",
                        success: function (res) {
                            console.log(res);
                        },
                        error: function (err) {
                            console.log(JSON.stringify(err));
                        }
                    })
                });
    
            })
        </script>
    </body>
    </html>
    
  2. 后台
    package cn;
    
    import org.springframework.web.bind.annotation.*;
    
    @RestController
    @RequestMapping("ajax")
    @CrossOrigin
    public class AjaxController {
    
        @GetMapping("get1")
        public String get1() {
            return "这是get无参方法";
        }
    
        @GetMapping("get2")
        public String get2(@RequestParam("name") String name, @RequestParam("age") String age) {
            return "my name is " + name + " and my age is " + age;
        }
    
        @PostMapping("post1")
        // UserVO 是一个空vo,里面啥属性也没
        public String post1(@RequestBody UserVO vo) {
            return "这是post无参方法";
        }
    
        @PostMapping("post2")
        // UserInVO里面有 address 和 hobbies 俩属性,都为String类型
        public String post2(@RequestBody UserInVO inVO) {
            return "my address is " + inVO.getAddress() + " and my hobby is " + inVO.getHobbies();
        }
    }
    
  • 注:

    1. ajax 更多属性介绍参考博客 ajax 方法详解
    2. 此处使用的是 SpringBoot @CrossOrigin 后台解决跨域问题,也可以使用 Nginx 反向代理解决跨域问题。
  • 运行截图

3 复杂请求

  1. 复杂请求介绍可参考 ajax跨域简单请求和复杂请求

  2. 最常见的情况,一是 Content-Type = application/json ; 二是向 header 中添加自定义信息,如 token 等。

    • ajax 往 header 中添加信息有两种方法,直接在 headers 属性中写 或者 使用 beforeSend() 方法,可参考下面代码。
  3. 复杂请求首先会先发送一次 options 预请求,用于试探服务端是否能接受真正的请求,如果 options 获得的回应是拒绝性质的,比如 404 \ 403 \ 500 等 http 状态,就会停止接下来 post、put 等请求的发出

  4. 解决办法

    1. springboot / ssm 项目,在配置文件 application.properties 中解决
      spring.mvc.dispatch-options-request=true
      
    2. springcloud 项目,在网关中解决
      // 在 public class TokenFilter extends ZuulFilter 类中
      public boolean shouldFilter() {
          HttpServletRequest request = RequestContext.getCurrentContext().getRequest();
          if (request.getMethod().equals(RequestMethod.OPTIONS.name())) {
              System.out.println("OPTIONS请求不做拦截操作");
              return false;
          }
          /**
           * 其他是否拦截的业务操作
           */
          return true;
      }
      
  5. 样例代码

    1. 前台
      <!DOCTYPE html>
      <html lang="zh-cn">
      <head>
          <meta charset="UTF-8">
          <meta name="viewport" content="width=device-width, initial-scale=1.0">
          <title>复杂请求测试3</title>
      </head>
      <body>
          <input id="btn5" type="button" value="复杂请求"></input>
      
          <script src="https://code.jquery.com/jquery-3.1.1.min.js"></script>
          <script>
              $(function () {
                  $('#btn5').click(function () {
                      $.ajax({
                          type: "post",
                          url: "http://localhost:8081/ajax/complexRequest",
                          /**
                           * 根据上面介绍可以,当 contentType: "application/json" 或者往 header 中添加自定义属性时,为复杂请求
                           * 注:下面 headers 中直接塞值 (eg. 塞 name) 或者使用 beforeSend() 塞值 (eg. 塞 token) 均可
                           * 
                           * beforeSend() 介绍如下
                           * beforeSend()是发送请求前可以修改 XMLHttpRequest 对象的函数,例如添加自定义HTTP头。
                           * 在 beforeSend() 中如果返回 false 则可以取消本次 ajax 请求。XMLHttpRequest 对象是惟一的形参。
                           */
                          headers: {
                              "name": "newlife"
                          },
                          beforeSend: function (XMLHttpRequest) {
                              XMLHttpRequest.setRequestHeader("token", "abc422-45afds-hkjdhk4");
                          },
                          data: JSON.stringify({
                              "address": "luoyang",
                              "hobbies": "dance"
                          }),
                          contentType: "application/json",
                          dataType: "json",
                          success: function (res) {
                              console.log(res);
                          },
                          error: function (err) {
                              console.log(JSON.stringify(err));
                          }
                      })
                  });
      
              })
          </script>
      </body>
      </html>
      
    2. 后台
      @RestController
      @RequestMapping("ajax")
      public class AjaxController {
          @CrossOrigin
          @PostMapping("complexRequest")
          // UserInVO里面有 address 和 hobbies 俩属性,都为String类型
          public List<String> complexRequest(@RequestBody UserInVO inVO, HttpServletRequest request) {
              List<String> result = new ArrayList<>();
              // 取前台 headers 中自定义的属性 name
              result.add(("my name is " + request.getHeader("name")));
              // 取前台 data 中的数据
              result.add("my address is " + inVO.getAddress());
              result.add("my hobby is " + inVO.getHobbies());
              // 取 beforeSend 中自定义的属性 token
              result.add("my token is " + request.getHeader("token"));
              return result;
          }
      }
      
    3. application.properties配置文件
      server.port=8081
      spring.mvc.dispatch-options-request=true
      
    4. 浏览器控制台输出结果
      (4) ["my name is newlife", "my address is luoyang", "my hobby is dance", "my token is abc422-45afds-hkjdhk4"]
      0: "my name is newlife"
      1: "my address is luoyang"
      2: "my hobby is dance"
      3: "my token is abc422-45afds-hkjdhk4"
      length: 4
      __proto__: Array(0)
      
posted @ 2021-10-18 20:50  lkf-newlife  阅读(392)  评论(0编辑  收藏  举报