AJAX详解

ajax详解
参考:https://www.cnblogs.com/dongfangshenhua/p/6858833.html

什么是 ajax

全称:Asynchronous JavaScript And XML(异步的JavaScript和XML)

作用:实现异步请求的技术。

什么是同步请求:
场景:页面上有一个a标签,用户点击a标签,浏览器就发出一个请求,然后服务器给出一个响应。
(请求,其实是用户自己操作的,触发的)

什么是异步请求:
场景:用户在注册的时候,用户首先输入用户名,接下来用户继续填写其他注册信息,与此同时,浏览器会自动发送一个请求,将用户输入的用户名传送给服务器,去验证是否可用。
(请求,是浏览器自动发送的,不是用户操作的,与用户没有关系)

同步与异步的区别和理解:
1.同步请求:之前我们写的注册案例,依次写完用户名、密码等等信息之后,手动点击提交按钮,浏览器才会把数据传到服务器去进行校验用户名是否重复,然后服务器返回响应的数据,浏览器接收数据并在浏览器上提示用户名重复信息。这种方式一是速度慢,需要将全部信息填完后点击提交按钮才能提交到服务器,如果验证不通过害得重新提交,比较浪费流量;二是点击提交后页面会进行刷新,填写的数据会全部清除,如果当用户名等校验不通过,还需要把所有信息在填一遍,太麻烦。

2.异步请求:使用ajax的话,将用户文本框绑定一个鼠标离焦事件,事件里用ajax提交用户名到服务器去校验,这个验证是鼠标离开用户名文本框时浏览器自动向服务器发送一个请求,我们在填写别的信息的时候,服务器会将校验信息发送给浏览器提示用户名是否重复信息,这样一来,可以只修改验证失败的信息(用户名),最后全部数据验证通过了才可以提交,即节省了流量,又减少了重复填写的麻烦。

为什么需要异步请求,或者说哪些功能必须使用异步请求技术来实现?
在不刷新页面的情况下,发送请求,接收响应,然后修改部分的页面,这样的需求需要异步请求实现。
(使用a标签和form表单发送请求,都会刷新页面)
总结:在不使用a标签和form表单发送请求的情况下,使用异步请求。

在这个需求中,发送请求应该由谁来做?
JavaScript。

企业为什么特别喜欢使用ajax?
钱。企业的网络通信费用,是按流量计费,使用ajax它的数据量少,所以省钱;
ajax它的数据量少——因为他不用加载整个页面(加载部分)
ajax因为数据量小,响应速度快,用户体验好。

ajax的运行机制

在页面不刷新的情况下,向服务器发送请求,达到页面和后台的异步交互。

现在主流(IE、谷歌、火狐,其他的国产浏览器一般都会使用谷歌浏览器的内核)的浏览器都有ajax引擎实现——现在ajax技术,都被主流浏览器实现,我们自己不用去写Ajax引擎,这个引擎已经存在我们的浏览器中, 我们可以理解为浏览器都内置有ajax的核心对象,我们不需要自己创建核心对象,只要获取对象使用即可;

相当于大家已经有了法拉利,不用自己再造一个,只需学会使用就可以。
image

ajax的快速入门

Ajax代码步骤:

1. 获取核心对象
2. 发送请求,使用open和send方法
3. 设置等待服务器响应,给onreadystatechange属性设置函数,并且在函数中做判断,保证readyState==4 && status==200,才是请求已经完成,响应已经就绪。
4.获取响应的数据,根据需求,做Dom操作。

1、获取核心对象 XMLHttpRequest(ajax擎对象)

jsp代码:
<script type="text/javascript">
        //演示1:获取ajax的核心对象
        //此为固定代码,因为浏览器不同则获取对象的方式处理也是不同的;
        function getXHR(){
            var xmlhttp;
            if(window.XMLHttpRequest){
                //如果使用的浏览器是 IE7+, Firefox, Chrome, Opera, Safari
                xmlhttp = new XMLHttpRequest();
            }else{
                //如果使用的浏览器是 IE6, IE5
                xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
            }
            return xmlhttp;
        }
        //演示效果
        //alert(getXHR());  
    </script>

2.向服务器发送请求(open方法和send方法)

如需将请求发送到服务器,我们使用XMLHttpRequest对象的open()和send()方法。

image

jsp代码:
      //演示2,使用 ajax 向服务器发送请求
        function test1(){
            //先获取 ajax 核心对象(这个方法我们上面写过了,调用即可)
            var xhr = getXHR();
            //使用open(method,url,async)方法发送请求
            //参数一,method:请求的类型;GET 或 POST 
            //参数二,url:文件在服务器上的位置 
            //参数三:async:true(异步)或 false(同步) 
            xhr.open("get","${root}/ajax",true);
            //使用send()方法发送请求
            //注意;此处是get提交,所以使用send方法没有参数
            xhr.send();
        }
        //test1();

3.接收响应数据

接收步骤:
1.设置onreadystatechange()事件执行函数(等待服务器响应)
2.判断请求是否完成,且响应就绪,状态码是否为200(xhr.readyState==4 && xhr.status==200)
3.获取响应数据(var data = xhr.responseText,响应的数据为文本类型)

image

jsp代码:
        //演示4,设置等待服务器响应
        function test3(){
            //先获取ajax核心对象
            var xhr = getXHR();
            //第一,method:请求的类型;GET 或 POST 
            //第二,url:文件在服务器上的位置 
            //第三:async:true(异步)或 false(同步) 
            xhr.open("get","${root}/ajax",true);
            //将请求发送到服务器。
            xhr.send();
            //在接收响应前,设置等待服务器响应
            xhr.onreadystatechange = function(){
                if(xhr.readyState == 4 && xhr.status == 200){
                    //保证请求已经完成,且响应已经就绪
                    //接受响应
                    var data = xhr.responseText ;
                    alert(data);
                }
            };
        }
        //test3();

注意事项:

内容不会直接显示到浏览器页面上,从ajax发送的请求到服务器,从服务器返回的响应也会传到ajax中,由ajax做出处理

友情提示:

以后再工作中,一般不使用原生(今天学习的)的ajax代码,一般使用的是js框架(Jquery、ext js 、node js)发送ajax请求

问题:

Get发送请求与post发送请求的代码不同,我们还没有具体的分析,后文继续;

XMLHttpRequest API详解

1、onreadystatechange属性

是什么:存储函数(或函数名),每当readyState发生改变的时候,都会调用该函数;

image

执行机制图解:

image

2.open()方法

是什么:做发送请求之前准备工作的方法

image

一般使用post方式还是get方式?

官方解释:
image

我推荐:POST

POST,没有数据长度限制(注意:很多时候,提供功能给用户使用,用户输入的数据长度,有时是没法控制的)
POST,解决乱码比较简单
POST,方式更加安全

3.setRequestHeader方法

image

image

注意:这个方法相当于,设置了表单的enctype属性的默认值,来模拟表单发送数据

4.send()方法

是什么:发送请求的方法
image

注意:Post方式提交请求,请求参数写在send方法中。如果是get请求,参数,直接写在url中

5. 总结:Get请求与post请求的对比

Post请求格式:

xhr.open("post","${root}/ajaxTest",true);
xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded");
xhr.send("username=张三");

Get请求格式:

 xhr.open("get","${root}/ajax?username=haha",true);
 xhr.send();

区别:

1.post提交的url中不可以带参数

2.Post提交需要设置:xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded");

3.Post提交的send方法参数就是post提交的参数,而get提交的send方法不可以有参数;

6.readyState属性

是什么:存有 XMLHttpRequest 的状态。从 0 到 4 发生变化

注意:我们只需要关注状态==4的时候,请求已经完成,而且响应已经就绪

image

7. status属性

是什么:存有响应状态码的属性

image

响应状态码:

404:请求找不到

500:服务器异常

302:重定向

200:ok

401:权限不足,做应用,对用户的界面(使用淘宝的时候买家看到的页面),对管理员界面(只有拥有管理员权限的用户,才能看到——卖家的页面),如果用户访问了管理员界面,那么就需要返回响应码为:401,表示当前用户权限不足。

管理员的页面:卖家(上传商品),客服(用户信息,用户的记录,电商,用户订单),运维(当前服务器的运行状态),老板(钱,当前系统的资金管理)

Shiro安全框架,权限

8. responseText属性

是什么:获取响应的数据,以字符串的形式

image

案例:验证用户名是否重复(重点:必须掌握)

需求:当用户输入完用户名的时候,浏览器发送用户输入的数据(用户名),给服务器,服务器校验用户名,并且给出反馈(用户名可以使用,用户名重复,用户名不能为空,服务器忙)。

思路:

1) 当用户输入完用户名的时候?oblur事件,启动js函数,发送ajax请求

2) 浏览器发送用户输入的数据(用户名),给服务器?Ajax

3) 服务器校验用户名?查询数据库

4) 并且给出反馈。Servelt给出响应,js处理这个响应,具体就是是否限制表单提交和提示用户错误信息

分析案例实现的步骤:

页面上提供功能:

1) 输入框,让用户输入用户名,表单提交数据

2) 提交按钮,提交数据

Ajax:

1) 获取用户输入的用户名

2) 发送请求

3) 等待响应

4) 根据响应做不同处理(可以提交表单和不可以提交)

Servlet:

1) 校验请求参数

2) 调用service方法查询

Service:

调用dao查询数据

Dao:

操作数据;

Select * from user where username = ?

画图分析:

image

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@taglib prefix="c"  uri="http://java.sun.com/jsp/jstl/core"%>
<c:set var="root" value="${pageContext.request.contextPath}"/>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <title>My JSP 'index.jsp' starting page</title>
    <meta http-equiv="pragma" content="no-cache">
    <meta http-equiv="cache-control" content="no-cache">
    <meta http-equiv="expires" content="0">    
    <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
    <meta http-equiv="description" content="This is my page">
    <script type="text/javascript">
    
        //获取ajax核心对象
        function getXHR() {
            var xmlhttp;
            if (window.XMLHttpRequest) {
                // code for IE7+, Firefox, Chrome, Opera, Safari
                xmlhttp = new XMLHttpRequest();
            } else {
                // code for IE6, IE5
                xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
            }
            return xmlhttp;
        }
        
        //_this 是绑定此事件的对象,注意因为参数是具体的标签对象,所以不可以使用关键字this
        function _check(_this){
            //获取输入的用户名值
            var username = _this.value;
            //发送到服务器校验是否有重名
            
            
            //1.获取核心对象
            var xhr = getHXR();
            //2.发送请求
            xhr.open("post","${root }/check",true);
            //模拟表单发送数据
            xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded");
            //注意:js代码,如果代码中的某一行错了,它是不报错的
            xhr.send("username=" + username);
            
            //设置等待服务器响应
            xhr.onreadystatechange = function(){
                if(xhr.readyState == 4 && xhr.status == 200){
                    var data = xhr.responseText;//获取响应回来的数据
                    
                    
                    //做响应的dom操作
                    //注意:为了防止和js内置的全局变量,重名,所以加_
                    var _msg = document.getElementById("msg");
                    var _f = document.getElementById("_f");
                    if(data == 1){
                        //提示用户名可以注册
                        _msg.innerHTML = "用户名可以注册";
                        //onsubmit:表单提交事件
                        //只要onsubmit的值为true,表单才可以提交
                        _f.onsubmit = function (){
                            return true;
                        };
                    } else if(data == -1){
                        _msg.innerHTML = "重复";
                        _f.onsubmit = function (){
                            return false;
                        };
                    }else if(data == -3){
                        _msg.innerHTML = "用户名不能为空";
                        _f.onsubmit = function (){
                            return false;
                        };
                    }else{
                        _msg.innerHTML = "服务器忙";
                        _f.onsubmit = function (){
                            return false;
                        };
                    }
                }
        };
    }
    </script>
  </head>
  
  <body>
  <form id="_f" action="${root }/register" method="post">
        <!-- this:表示当前标签对象 -->
        用户名:<input type="text" name="username" onblur="_check(this);"><span id="msg"></span> <br>
        <input type="submit" value="注册">
  </form>
  </body>
</html>

CheckNameServlet:

import java.io.IOException;
import java.io.PrintWriter;
import java.sql.SQLException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanHandler;
import cn.itcast.domain.User;
import cn.itcast.utils.JDBCUtils;

public class CheckNameServlet extends HttpServlet {
    public void doGet(HttpServletRequest request, HttpServletResponse response) 
    throws ServletException, IOException {
        request.setCharacterEncoding("utf-8");
        //获取请求参数
        String username = request.getParameter("username");
        //获取输出流
        PrintWriter writer = response.getWriter();
        
        //先校验用户名的格式
        //用户名不能不写,也不能写空字符串
        if(username == null || username.trim().equals("")){
            //返回-3
            writer.write("-3");
            return;
        }
        
        //再校验用户名是否重复
        //我们这里演示,就不使用service和dao,方法直接在servlet中实现,仅供演示使用
        QueryRunner qr = new QueryRunner(JDBCUtils.getDataSource());
        String sql = "select * from user where name = ?";
        try {
            User user = qr.query(sql, new BeanHandler<User>(User.class), username);
            if(user == null){
                writer.write("1");
                return;
            }else {
                writer.write("-1");
                return;
            }
        } catch (SQLException e) {
            e.printStackTrace();
            writer.write("-2");
            return;
        }
    }

    public void doPost(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {
        doGet(request, response);
    }
}
posted @ 2022-09-12 22:57  huangchun0121  阅读(183)  评论(0)    收藏  举报