AJAX 发送GET、POST和复杂请求
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.*; @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(); } }
-
注:
- 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)
- 前台
- 代码参考链接 blogs-ajax