Ajax原生实现
AJAX的实现方式:
- 原生的JS实现方式
- 原生的JS方式实现AJAX很麻烦, 所以我们后期是不会使用这种方式发送请求的, 后期我们向后端发送请求的时候一般都是使用AJAX封装之后的方式
- JQuery
- $.ajax()
- $.get()
- $.post()
- 之后我们还会讲一种axios方式, axios也是ajax封装之后的一个框架
这里我们先来将最原生态的Ajax实现方式:
1. HTML内容(包括JS):
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>原生AJAX实现</title>
<script>
function change(){
//我们虽然AJAX名字是异步的JavaScript And XML, 但是我们的AJAX也是可以发送同步请求的, 但是我们以后由于绝大多数情况之下都是异步请求, 所以这里我们发送异步请求
//1.创建XMLHttpRequest代理对象, 此代理对象用来向后端发送请求并接收响应
var xmlHttpRequest = new XMLHttpRequest();
//2. 建立连接, 使用XMLHttpRequest代理对象调用open()方法建立连接
/*
注意: 这个open()方法中有三个参数
参数1 : 请求方式(GET/post等等)
参数2 : 请求的URL
参数3 : 是否为异步请求?
如果是true就是异步请求, 如果是false就是同步请求
显然我们此时选择了发送一个异步请求
*/
xmlHttpRequest.open("GET","http://localhost:8080/webback/ajaxServlet?username=tom",true);
/*
注意: 如果我们是使用AJAX发送POST请求并且提交的是表单数据的时候我们一定要设置一个请求头
xmlHttpRequest.setRequestHeader("content-type","application/x-www-form-urlencoded");
*/
//3. 发送请求
xmlHttpRequest.send();
/*
注意: 对于get请求方式我们的请求参数直接拼接到了URL后面, 所以send()方法就用空参方法即可
但是对于post请求方式的请求参数我们是要写到send()方法的方法体中的, 以字符串的形式, 请求参数的格式也是
和get方式一样的 username=zs&age=23的形式
*/
//4. 接受并处理来自服务器的响应结果
//获取方式: xmlHttpRequest.responseText;
/*
注意: 我们获取请求的时候是什么时候获取? 我们是要在onreadystatechange()事件中获取, 这个事件表示的就是我们的请求状态改变之后获取,
但是我们获取的时候显然也不能是每一次请求状态改变之后都获取, 我们获取对应的响应数据的时候一定是先要判断xmlHttpRequest的状态,
也就是xmlHttpRequest.readystate,这个就是请求状态, 当其值为4的时候就表示请求已经完成了, 我们就可以在前端获取响应结果了
*/
xmlHttpRequest.onreadystatechange = function(){
if(xmlHttpRequest.readyState == 4 && xmlHttpRequest.status == 200){
//获取服务器响应结果
alert(xmlHttpRequest.responseText)
}
}
}
</script>
</head>
<body>
<form></form>
<!-- 创建一个按钮用来触发一个事件 , 我们在对应事件中完成AJAX发送请求过程的实现 -->
<input type="button" value="点击我向服务器发送请求" onclick="change()">
</body>
</html>
- 注意: webback是我们的后端的项目访问路径
后端服务器内容:
package com.ffyc.demo.原生Ajax请求;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet("/ajaxServlet")
public class AjaxServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//获取请求参数之后并且响应数据
String username = req.getParameter("username");
System.out.println(username);
//响应数据给前端
resp.setCharacterEncoding("utf-8");
resp.getWriter().write("miaomiao笑了!");
}
}
- 我们后端中会输出一个tom, 并且前端中会以弹框的形式输出一个喵喵笑了
然后这个请求还涉及到了一个跨域的问题:
- 因为前端和后端的程序我们是分离开发的, 所以肯定是不同的两个服务, 也就是这个时候就肯定是不同源的, 所以就会有跨域问题: 所以我们就在后端中使用CORS的方式将跨域问题解决了
- 因为我们是前后端分离开发的,我的前端内容是在8848端口上运行的, 而后端Servlet是在8080端口上运行的, 所以对于这种只要是: ①协议, ②地址, ③端口中有一个不相同的服务, 我们的浏览器都会将响应回来的内容进行一个拦截, 也就是请求是发送到了服务器的, 服务器响应也是没有问题的, 但是浏览器会将不同源的响应内容拦截下来
package com.ffyc.filter;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
//注意: 这个时候导包的时候一定要注意, 有很多的Filter接口, 我们这个时候要实现的的javax.servlet包之下的Filter接口
//这个时候我们配置的拦截路径是"/*", 表示的意思是访问任何资源的时候都会被该过滤器进行拦截
@WebFilter("/*")
public class FilterDemo2 implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
//不做实现
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
//放行前逻辑
System.out.println("放行前逻辑");
/*
编写解决跨域请求的代码
*/
HttpServletResponse servletResponse1 = (HttpServletResponse)servletResponse;
//针对复杂请求时设置为允许跨域请求
servletResponse1.setHeader("Access-Control-Allow-Origin","*");
//设置哪种方式的HTTP请求可以访问
servletResponse1.setHeader("Access-Control-Allow-Methods","GET,POST,PUT,DELETE,OPTIONS");
//设置允许携带Cookie
servletResponse1.setHeader("Access-Control-Allow-Credentials","true");
//允许携带哪些头
servletResponse1.setHeader("Access-Control-Allow-Headers","Context-Type");
//放行 使用FilterChain接口实现类对象调用doFilter()方法
filterChain.doFilter(servletRequest, servletResponse);
//放行后逻辑
System.out.println("放行后逻辑");
}
@Override
public void destroy() {
//不做实现
}
}
补充:
XMLHttpRequest类中的readyState取值:
- 用来表示请求状态, 从0到4之间变化
0 : 请求尚未初始化
1 : 服务器连接建立
2 : 请求已接收
3 : 请求处理中
4 : 请求已完成
- 注意: 只有4状态的时候就说明请求完成了, 那么我们就可以获取服务器的响应数据了
XMLHttpRequest类中的status取值
200 : OK
404 : 未找到页面
onreadystatechange()是一个回调函数, 会在readyState属性值发生改变之后调用
补充二:
同步请求会刷新当前页面, 也就是会覆盖当前页面, 而异步请求则是不会覆盖当前页面, 所以我们使用异步请求可以实现页面的局部更新
- 并且同步请求期间浏览器是不能执行其他操作的, 必须要等到同步请求完成之后才能执行下一步操作