AJAX GET、POST和複雜請求程式碼樣例
阿新 • • 發佈:2021-10-18
目錄
1 概述
- 同步和非同步
- 前提條件:客戶端和伺服器端相互通訊的前提下
- 同步:客戶端必須等待伺服器端的響應。在等待的期間客戶端不能做其他操作。
- 非同步:客戶端不需要等待伺服器端的響應。在伺服器處理請求的過程中,客戶端可以進行其他的操作。
- AJAX 是 ASynchronous JavaScript And XML 的簡寫,即 AJAX = 非同步 JavaScript 和 XML。
- 其他基礎知識參考部落格 AJAX入門介紹
2 普通請求
- 前臺
<!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>
- 後臺
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(); } }
- 注:
- ajax 更多屬性介紹參考部落格 ajax 方法詳解
- 此處使用的是 SpringBoot @CrossOrigin 後臺解決跨域問題,也可以使用 Nginx 反向代理解決跨域問題。
3 複雜請求
-
複雜請求介紹可參考 ajax跨域簡單請求和複雜請求
-
最常見的情況,一是 Content-Type = application/json ; 二是向 header 中新增自定義資訊,如 token 等。
- ajax 往 header 中新增資訊有兩種方法,直接在 headers 屬性中寫 或者 使用 beforeSend() 方法,可參考下面程式碼。
-
複雜請求首先會先發送一次 options 預請求,用於試探服務端是否能接受真正的請求,如果 options 獲得的迴應是拒絕性質的,比如 404 \ 403 \ 500 等 http 狀態,就會停止接下來 post、put 等請求的發出
-
解決辦法
- springboot / ssm 專案,在配置檔案 application.properties 中解決
spring.mvc.dispatch-options-request=true
- 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; }
- springboot / ssm 專案,在配置檔案 application.properties 中解決
-
樣例程式碼
- 前臺
<!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>
- 後臺
@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; } }
- application.properties配置檔案
server.port=8081 spring.mvc.dispatch-options-request=true
- 瀏覽器控制檯輸出結果
(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)
- 前臺