XMLHttpRequest和Ajax的关系
ajax
是一种技术方案,但并不是一种新技术。
ajax
最核心的依赖是浏览器提供的XMLHttpRequest
对象。
所以我用一句话来总结两者的关系:我们使用XMLHttpRequest
对象来发送一个Ajax
请求
XMLHttpRequest的发展历程
XMLHttpRequest
一开始只是微软浏览器提供的一个接口,后来各大浏览器纷纷效仿也提供了这个接口,再后来W3C对它进行了标准化,提出了XMLHttpRequest标准
。XMLHttpRequest
标准又分为Level 1
和Level 2
。
相应的区别和用法参考:
你真的会使用XMLHttpRequest吗?
阮一峰的XMLHttpRequest Level 2 使用指南
实例代码
pom.xml
<!--servlet-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>${servlet.version}</version>
<scope>provided</scope>
</dependency>
<!--json-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.29</version>
</dependency>
<!--上传文件-->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.4</version>
</dependency>
index.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>ajax测试</title>
<script type="text/javascript" src="<%=request.getContextPath()%>/resource/js/jquery3.3.1/jquery.min.js"></script>
<script type="text/javascript" src="<%=request.getContextPath()%>/resource/js/ajax.js"></script>
<script type="text/javascript" src="<%=request.getContextPath()%>/resource/js/jqueryAjax.js"></script>
</head>
<body>
<h1>XMLHttpRequest level 1</h1>
<button onclick="xhr1_get()">xhr level 1 get请求</button>
<button onclick="xhr1_post()">xhr level 1 post请求</button>
<h1>jQuery ajax</h1>
<button id="jquery_ajax_get">jquery get请求</button>
<button id="jquery_ajax_post">jquery post请求</button>
<h1>XMLHttpRequest level 2</h1>
<button onclick="xhr2_get()">xhr level 2 get请求</button>
<button onclick="xhr2_post()">xhr level 2 post请求</button>
</body>
</html>
XMLHttpRequest level 1
ajax.js
//等到所有内容,包括外部图片之类的文件加载完后,才会执行
window.onload = function () {
console.log("文档就绪后执行");
}
GET请求
function xhr1_get() {
var xhr = new XMLHttpRequest();
//默认是异步请求async:true
xhr.open("GET", "./xhr1Servlet?name=zhangsan&age=23", true);
//设置响应数据解析格式(优先级大于后端设置)
// xhr.overrideMimeType('text/html;charset=UTF-8');
xhr.onreadystatechange = function (e) {
if (this.readyState === 4 && this.status === 200) {
console.log(this.response);
}
}
xhr.send();
}
Xhr1Servlet.java
@WebServlet("/xhr1Servlet")
public class Xhr1Servlet extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//和前端设置只一处就可以了,get通常后端设置,后端设置浏览器响应头才能看见
resp.setContentType("text/html;charset=UTF-8");
String name = req.getParameter("name");
String age = req.getParameter("age");
resp.getWriter().print("名字:" + name + "年龄:" + age);
}
}
POST请求
function xhr1_post() {
var data = "name=zhangsan&age=23";
var xhr = new XMLHttpRequest();
xhr.open("POST", "./xhr1Servlet", true);
//必须设置请求头,因为request.getParameter()获取的参数只能是符合URL编码格式的
// ajax的默认请求ContentType:text/plain(纯文本)
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
xhr.onreadystatechange = function (e) {
if (this.readyState === 4 && this.status === 200) {
console.log(this.response);
}
}
//data数据格式必须符合URL编码字符串格式,如:“param1=value1¶m2=value2”
xhr.send(data);
}
Xhr1Servlet .java
@WebServlet("/xhr1Servlet")
public class Xhr1Servlet extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//和前端设置只一处就可以了,get通常后端设置,后端设置浏览器响应头才能看见
resp.setContentType("text/html;charset=UTF-8");
String name = req.getParameter("name");
String age = req.getParameter("age");
resp.getWriter().print("名字:" + name + " 年龄:" + age);
}
}
XMLHttpRequest level 2
xhr.send(data),data可以是什么类型的数据
xhr.responseType用来指定xhr.response的数据类型
跨域资源共享 CORS 详解
GET请求
function xhr2_get() {
var xhr = new XMLHttpRequest();
xhr.responseType = "json";
xhr.open("GET", "./xhr2Servlet?name=zhangsan&age=23", true);
//注册相关事件回调处理函数
xhr.onload = function (e) {
if (this.status == 200 || this.status == 304) {
console.log(this.response);
}
};
xhr.send();
}
Xhr2Servlet.java
@WebServlet("/xhr2Servlet")
public class Xhr2Servlet extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//默认转换成了iso-8859-1的编码格式;和前端设置一处就可以了
resp.setContentType("application/json;charset=UTF-8");
String name = req.getParameter("name");
String age = req.getParameter("age");
JSONObject data = new JSONObject();
data.put("名字:", name);
data.put("年龄:", age);
resp.getWriter().print(data);
}
}
POST请求
function xhr2_post() {
var formData = new FormData();
formData.append('name', 'zhangsan');
formData.append('age', 12);
var xhr = new XMLHttpRequest();
//设置xhr请求的超时时间
xhr.timeout = 30000;
//设置响应返回的数据格式
xhr.responseType = "json";
//创建一个 post 请求,采用异步
xhr.open('POST', './xhr2postServlet', true);
//注册相关事件回调处理函数
xhr.onload = function (e) {
if (this.status == 200 || this.status == 304) {
console.log(this.response);
}
};
//FormData 类型,content-type默认值为multipart/form-data
xhr.send(formData);
}
Xhr2postServlet.java
@WebServlet("/xhr2postServlet")
public class Xhr2postServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//默认转换成了iso-8859-1的编码格式;和前端设置一处就可以了
resp.setContentType("application/json;charset=UTF-8");
JSONObject data = new JSONObject();
DiskFileItemFactory factory = new DiskFileItemFactory();
ServletFileUpload upload = new ServletFileUpload(factory);
InputStream inputStream = null;
try {
List<FileItem> fileItems = upload.parseRequest(req);
for (FileItem item : fileItems) {
//普通字段
if (item.isFormField()) {
String fieldName = item.getFieldName();
String value = item.getString("UTF-8");
if("name".equals(fieldName)){
data.put("名字:", value);
}
if("age".equals(fieldName)){
data.put("年龄:", value);
}
} else {
//文件名称
String fileName = item.getName();
//文件输入流
inputStream = item.getInputStream();
}
}
} catch (FileUploadException e) {
data.put("失败原因:", e.getMessage());
} finally {
IOUtils.closeQuietly(inputStream);
}
resp.getWriter().print(data);
}
}
jQuery ajax
jqueryAjax.js
GET请求
//在 html 所有标签(DOM)都加载之后,就会去执行
//DOM文档对象转换为jQuery对象,然后通过ready(fn)注册页面加载事件,当页面加载完毕后执行fn函数
$(document).ready(function(){
//AJAX 请求完成时运行的函数,$(document)表示DOM对象转换为jQuery对象
$(document).ajaxComplete(function () {
console.log("jqueryAjax请求结束");
});
//为将来的 $.ajax()请求设置默认值,$.get()和$.post()不能触发
$.ajaxSetup({
url:"./xhr1Servlet?name=zhangsan&age=25",
async:true,
type:"GET",
headers: {
"Accept" : "text/html; charset=utf-8",
"Content-Type": "text/html; charset=utf-8"
},
success:function(data){
console.log("ajax()请求结束,结果:" );
console.log(data);
}
});
$("#jquery_ajax_get").click(function() {
$.ajax();
$.get("./xhr1Servlet?name=zhangsan&age=23", function (data) {
console.log(data);
}, "text");
$.get("./xhr2Servlet", {"name": "zhangsan", "age": 23}, function (data) {
console.log(data);
}, "json");
});
});
POST请求
//在 html 所有标签(DOM)都加载之后,就会去执行
//DOM文档对象转换为jQuery对象,然后通过ready(fn)注册页面加载事件,当页面加载完毕后执行fn函数
$(document).ready(function(){
$("#jquery_ajax_post").click(function() {
$.post("./xhr1Servlet?name=zhangsan&age=23", function (data) {
console.log(data);
}, "text");
$.post("./xhr2Servlet", {"name": "zhangsan", "age": 23}, function (data) {
console.log(data);
}, "json");
//运行报错,因为header is application/x-www-form-urlencoded
$.post("./xhr2postServlet", {"name": "zhangsan", "age": 23}, function (data) {
console.log(data);
}, "json");
});
});