1. 程式人生 > 其它 >AJAX GET、POST和複雜請求程式碼樣例

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.*;
    
    /**
     * @author likefeng
     * @date 2021/3/11 21:01
     */
    
    @RestController
    @RequestMapping("ajax")
    public class AjaxController {
    
        @CrossOrigin
        @GetMapping("get1")
        public String get1() {
            return "這是get無參方法";
        }
    
        @CrossOrigin
        @GetMapping("get2")
        public String get2(@RequestParam("name") String name, @RequestParam("age") String age) {
            return "my name is " + name + " and my age is " + age;
        }
    
        @CrossOrigin
        @PostMapping("post1")
        // UserVO 是一個空vo,裡面啥屬性也沒
        public String post1(@RequestBody UserVO vo) {
            return "這是post無參方法";
        }
    
        @CrossOrigin
        @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)