• 1 介绍

    • 1.1 同步和异步

      • 1.1.1 基于AJAX的异步传输与传统同步传输的对比

      • 1.1.2 使用时间线表示同步和异步在过程上的区别

    • 1.2 JS与AJAX的关系

    • 1.3 AJAX用到的技术

    • 1.4 AJAX支持的三种数据类型(MIME)

  • 2 在原生JS中使用AJAX的步骤

    • 2.1 以上代码中需要注意的部分

      • 2.1.1 AJAX回调函数

      • 2.1.2 Content-Type(setRequestHeader()中的参数)(了解)

  • 3 在原生JS中使用AJAX处理XML数据以及DBUtils的使用

    • 3.1 例:使用AJAX异步请求读取数据库信息画出表格并填入信息

    • 3.2 例:使用AJAX异步请求实现假删除(标记删除)

1 介绍

AJAX(Asynchronized Javascript And Xml,异步的JS与XML)。

1.1 同步和异步

同步和异步是B/S架构的两种重要模式,异步多了一个JS发出请求的函数和一个接收响应的回调(callback)函数,耗资源大但是效率较高。而同步虽然低效,但是耗资源少。异步与同步配合工作。

同步
用户发出请求,必须等待响应的返回,在响应返回前,用户必须等待,
不能进行任何操作,当响应返回整个页面全部刷新异步
用户发出请求,不需要等待响应的返回,用户可以继续自己的操作,在未来的
一个时间段,响应应该返回,返回之后不影响用户当前的操作,页面部分更新

1.1.1 基于AJAX的异步传输与传统同步传输的对比

大多数情况下,传统同步传输尽管可能只改变了一行文本或者一个图像,但还是不能避免完全的页面刷新。如图:

使用基于AJAX的异步传输,用户不必等候页面长时间加载,甚至服务器处理请求时,用户还可以继续使用页面。如图:

1.1.2 使用时间线表示同步和异步在过程上的区别

  • 同步:

  • 异步:

1.2 JS与AJAX的关系

JS中并没有异步相关的技术,AJAX是使用JS语法的一个衍生技术,专门用来实现异步操作,严格地说AJAX不能算是JS的类库之一。

  • 常见的JS类库
    protoType YUI ExtJs jQuery dojo node.js Angular React VUE

1.3 AJAX用到的技术

  • 核心语法 JS
  • 用来封装和解析数据 XML
  • 解析XML DOM4j
  • 封装大量数据 JSON
  • 动态页面表现技术囊括了CSS XHTML HTML5等前端技术 DHTML

1.4 AJAX支持的三种数据类型(MIME)

  • 字符串 text/plain
  • JSON text/plain
  • XML text/xml

2 在原生JS中使用AJAX的步骤

以查重这个应用为例,学习在原生JS中使用AJAX的步骤。

checkName.html

<!DOCTYPE html>
<html><head><title>查重</title>   <meta charset="utf-8" /></head><body><form action="#" method="get"><label for="nameid">用户姓名:</label><input type="text" name="name" required id="nameid" onblur="checkName(this.value)" /><span id="name_msg"></span><br /><input type="submit" value="提交" id="sub" disabled /></form><script>//1):创建异步请求let request;function create(){/*以下写法为level2版本的创建异步请求的方式如果遇到较为陈旧的浏览器 例如IE6 7 8 甚至更老的浏览器推荐使用level1版本的创建方式if(window.XMLHttpRequest){request = new XMLHttpRequest();}else{request = new ActiveXObject("Microsoft.XMLHttp");}*/request = new XMLHttpRequest();}//2):此函数为主函数,用来发送异步请求function checkName(value){//a:创建异步请求create();//b:设置发送异步请求的目的地//request.open(method, url, async, user, password)/*method:异步请求的提交方式 get或者posturl:提交到哪里,注意如果是get方式则从此处传递值 url?key=valueasync:表示是否使用异步,默认为true使用异步,如果更改为false则使用同步,请求发出之后响应返回前浏览器锁死等待响应返回user与password:表示是否开启服务器安全策略,如果不填写表示不开启,tocmat等WEB服务器默认不开启*/request.open("post","servlet/Check",true);//c:如果请求方式为post,则必须指定字符流来传递数据(request.send())//get请求方式不需要书写此句//因为get传递的参数在地址后面拼(虚拟地址),直接以字符解析request.setRequestHeader("Content-Type","application/x-www-form-urlencoded");//d:声明回调函数//这里的函数名为callback也可以随意书写但是注意不能添加括号,//添加括号表示调用,不加表示声明request.onreadystatechange = callback;//另外一种写法,直接等于一个匿名方法/*request.onreadystatechange = function(){}*///e:如果请求方式为post,在此处传递值,即使不传递值也必须书写此句,内部填写null即可request.send("name="+value);}//回调函数的写法之一,另外一种可以直接把这个方法匿名地写在//onreadystatechange的等号后面function callback(){//保证返回的响应完整if(request.readyState==4){//保证服务器没有任何异常if(request.status==200){//接受服务器返回的数据let value = request.responseText;//拿取spanlet dom_sp = document.getElementById("name_msg");//拿取submitlet dom_sub = document.getElementById("sub");//根据响应数据显示span和submit按钮的内容if(value=="exist"){dom_sp.innerHTML="用户名已经被占用";dom_sp.style.color="red";dom_sub.disabled = true;return;}dom_sp.innerHTML="用户名可以使用";dom_sp.style.color="green";dom_sub.disabled = false;}}}            </script></body>
</html>

web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1"><display-name>AjaxDay1_check</display-name><servlet><servlet-name>Check</servlet-name><servlet-class>com.test.servlet.Check</servlet-class></servlet><servlet-mapping><servlet-name>Check</servlet-name><url-pattern>/servlet/Check</url-pattern></servlet-mapping><welcome-file-list><welcome-file>index.html</welcome-file><welcome-file>index.htm</welcome-file><welcome-file>index.jsp</welcome-file><welcome-file>default.html</welcome-file><welcome-file>default.htm</welcome-file><welcome-file>default.jsp</welcome-file></welcome-file-list>
</web-app>

servlet/Check.java

package com.test.servlet;import java.io.IOException;
import java.io.PrintWriter;import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;public class Check extends HttpServlet {public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {response.setContentType("text/plain;charset=utf-8");request.setCharacterEncoding("utf-8");PrintWriter out = response.getWriter();String value = request.getParameter("test");System.out.println("接受过来的用户名是:"+value);if(value.trim().equals("eric")){//返回响应给回调函数/** 注意* 1.out.print在这里并不是输出页面,而是给回调函数返回响应* 2.不能使用println,否则返回的字符串会自动添加“\n”* */out.print("exist");out.close();return;}out.print("suc");out.close();}
}
  • 效果图:

2.1 以上代码中需要注意的部分

2.1.1 AJAX回调函数

只要readystate参数从2到4发生变化就执行一次回调函数。在这里readystate到4条件判断才执行,其实值为234时也执行了,只不过这里在上面的程序中没有代码执行。结合AJAX执行顺序见图:

  • 注释:

    • c、d、e步骤:
      c(视请求方式而定).如果请求方式为post,则必须指定字符流来传递数据,指定Content-Type。get请求方式不需要书写此句,因为get只传递字符。

      request.setRequestHeader(“Content-Type”,“application/x-www-form-urlencoded”);

      d.声明回调函数,两种方式,见上面源码。
      e.如果请求方式为post,在此处传递值,即使不传递值也必须书写此句,内部填写null即可。

      request.send(“name=”+value); //这是当post传值时,不传值时填写null

  • 状态码指令集:

1xx 返回消息
2xx 成功
3xx 重定向
4xx 请求错误 如401 403 404 405
5xx 服务器内部错误 如500

2.1.2 Content-Type(setRequestHeader()中的参数)(了解)

注意:需要先调用open方法,之后再调用setRequestHeader方法!

  • 为何要用到setRequestHeader
    在HTTP协议里,客户端向服务器请求取得某个网页的时候,必须发送一个HTTP协议的头文件,告诉服务器客户端要下载什么信息以及相关的参数。 而XMLHTTP就是通过HTTP协议取得网站上的文件数据的,所以也要发送HTTP头给服务器。 但XMLHTTP默认的情况下有些参数可能没有说明在HTTP头里,当我们需要修改或添加这些参数时就用到了setRequestHeader方法。

  • setRequestHeader参数详解
    使用GET下列参数XMLObject.setRequestHeader (“CONTENT-TYPE”, “application/x-www-form-urlencoded” ),得到HTTP头:

POST /bb.asp HTTP/1.1
Accept: /
Accept-Language: zh-cn
UA-CPU: x86
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; SV1; .NET CLR 1.1.4322; .NET CLR 2.0.50727)
CONTENT-TYPE:application/x-www-form-urlencoded
Host: ourys.com
Content-length: 8
Connection: close
Cookie:%C3%F7%CC%EC=%B0%CB;ASPSESSIONIDASDBSDRR=BLEDBIBBCGKBJAKJCFEJKGII

注:

  1. CONTENT-TYPE: application/x-www-form-urlencoded含义是表示客户端提交给服务器文本内容的编码方式是URL编码,即除了标准字符外,每字节以双字节16进制前加个“%”表示。当然还有其他编码方式,如CONTENT-TYPE:multipart/form-data。
  2. Content-length:表示提交的数据字节大小,GET方式是没有提交内容的,GET传参通过虚拟地址传送,如GET /bb.asp?www=1234 HTTP/1.1,参数全部就只有 “www=1234” 这么多。所以 CONTENT-TYPE、Content-length在GET模式下是无效的。如果用POST的话就有些不同,POST将参数放到HTTP后面,以上面的HTTP为例,用POST的方法传参数“www=1234”时,发请求时需要声明编码方式,报头中出现Content-length大小了。
  3. Connection: Close,很明显英文的意思是连接:关闭,只是客户端在提交数据时告诉服务器让谁先关闭连接而已。

本节文字摘自Zero28093@CSDN,感谢大佬分享!

3 在原生JS中使用AJAX处理XML数据以及DBUtils的使用

不再赘述数据库设计以及web.xml、Factory类、po层、dao层的接口,前面的文章中有写。在dao层的实现类代码中介绍DBUtils的使用。

3.1 例:使用AJAX异步请求读取数据库信息画出表格并填入信息

dao/StudentDaoImpl.java

package com.test.dao;import com.test.factory.Factory;
import com.test.po.Student;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanListHandler;import java.sql.Connection;
import java.util.List;public class StudentDaoImpl implements StudentDaoIf{Connection con;//引入DBUtils的查询执行器,QueryRunner是DBUtils框架的核心类QueryRunner qr = new QueryRunner();@Overridepublic List<Student> queryAll() {try{String sql = "select * from student";con = Factory.getCon();/** 进行查询操作,使用DBUtil,减轻增删改查的工作量* 被操作的实体类对应数据库的表,且有空参和全参构造函数* 否则会造成无法取出或取出的字段不全* 不需要再关连接,DBUtils自动关闭。** qr.query(con,sql,ResultSetHandler)* con:表示数据源* sql:表示sql语句* ResultSetHandler:接口 可以通过调用此接口的子接口* 根据不同的sql语句进行操作* 返回 独立实体类       new BeanHandler<实体类名>(实体类名.class)* 返回 多个实体类集合   new BeanListHandler<实体类名>(实体类名.class)* 返回 long类型变量     new scalarHandler(); 返回的query为long类型,*                      若方法返回值为int,需要转换* */     return qr.query(con,sql,new BeanListHandler<Student>(Student.class));}catch(Exception ex){ex.printStackTrace();return null;}}@Overridepublic boolean delStuById(Integer id) {try{con = Factory.getCon();String sql = "delete from student where id = ?";//增删改均用update方法return qr.update(con,sql,id)==1;}catch(Exception ex){ex.printStackTrace();return false;}}
}

servlet/ShowStudent.java

package com.test.servlet;import com.test.dao.StudentDaoIf;
import com.test.dao.StudentDaoImpl;
import com.test.po.Student;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.List;public class ShowStudent extends HttpServlet {protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {request.setCharacterEncoding("utf-8");response.setContentType("text/xml;charset=utf-8");//以字符流将后面定义的XML输出到response中响应到客户端供AJAX解析PrintWriter out = response.getWriter();StudentDaoIf dao = new StudentDaoImpl();List<Student> list = dao.queryAll();//创建一个文档数据模型(document模型)Document doc = DocumentHelper.createDocument();//创建一个根元素/**   <root></root>* */Element root = doc.addElement("root");for(Student stu : list){//以根元素root为根,创建多个一级子元素/**   <root>*       <student></student>*       <student></student>*       <student></student>*       ****   </root>** */Element student = root.addElement("student");//在student标签中创建属性/**   <root>*       <student id="" name=""></student>*       <student id="" name=""></student>*       <student id="" name=""></student>*       ****   </root>** */student.addAttribute("id", stu.getId() + "");student.addAttribute("name", stu.getName());//以一级子元素student为根,创建二级子元素/**   <root>*       <student id="" name="">*          <email>***</email>*          <phone>***</phone>*       </student>*       <student id="" name="">*          <email>***</email>*          <phone>***</phone>*       </student>*       <student id="" name="">*          <email>***</email>*          <phone>***</phone>*       </student>*       ****   </root>** */Element email = student.addElement("email");email.setText(stu.getEmail());Element phone = student.addElement("phone");phone.setText(stu.getPhone());}//直接将document模型转换为XML输出到响应中out.print(doc.asXML());System.out.println(doc.asXML());out.close();}
}

xmlOperation.html

<!DOCTYPE html>
<html lang="zh-CN"><head><meta charset="UTF-8"><title>使用xml处理批量数据</title><style>table{width: 500px;border-collapse: collapse;}table,tr,td{border:solid 2px silver;}</style></head><!--页面加载完成后就执行showAll()--><body onload="showAll()"><!--定义一个空的div,后面使用原生JS写表格和数据到其中--><div id="show"></div><script>let request;function create(){request = new XMLHttpRequest();}function showAll(){create();request.open("post", "showStudent", true);request.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");//匿名回调函数request.onreadystatechange = function(){//前面写到的readyState过程if(request.readyState==4) {if (request.status == 200) {//返回一个xml标准格式的文档数据模型let doc = request.responseXML;/**   <root>*       <student id="" name="">*          <email>***</email>*          <phone>***</phone>*       </student>*       <student id="" name="">*          <email>***</email>*          <phone>***</phone>*       </student>*       <student id="" name="">*          <email>***</email>*          <phone>***</phone>*       </student>*       ****   </root>** *///根据标签名拿取多个元素let array = doc.getElementsByTagName("student");//在页面显示表格,先画表头let table = "<table><tr><td>ID</td><td>姓名</td><td>邮箱</td><td>手机</td><td>操作</td></tr>";for (let i = 0; i < array.length; i++) {//逐个拿取student标签let student = array[i];//拿取student标签中的id属性let id = student.getAttribute("id");//拿取同上的name属性let name = student.getAttribute("name");//拿取student内部email元素内部的值,//这种取法虽然啰嗦但是浏览器适配性高(里面就一个文本内容但还要以第一个子元素的身份取,还要再获取一下节点值)let email = student.getElementsByTagName("email")[0].firstChild.nodeValue;let phone = student.getElementsByTagName("phone")[0].firstChild.nodeValue;//画表格,将获取到的值画在表格体中,相当于拼字符串table += "<tr><td>" + id + "</td><td>" + name + "</td><td>"+ email + "</td><td>" + phone + "</td><td><label onclick='delStu(" + id + ")' style='cursor:pointer'>删除</label></td></tr>";}table += "</table>";document.getElementById("show").innerHTML = table;}}};request.send(null);}</script></body>
</html>

效果图:

3.2 例:使用AJAX异步请求实现假删除(标记删除)

所谓的假删除是只在页面上删除,而数据库中依然存在。这就要求在数据库实体类对应的表中新增一个默认为0(也可以默认为其他数字)的字段,当用户删除一条信息时即更新这个字段为1,表示已删除。指定dao层SQL语句中查询全部数据并显示的方法加入过滤条件,当这个字段为0时可以查出,1时表示已删除不能显示。

更新3.1中dao层实现类的queryAll方法中的SQL语句

String sql = “select * from student where isdeleted = 0”;

新增3.1中dao层实现类delStuById方法

    @Overridepublic boolean delStuById(Integer id) {try{con = Factory.getCon();String sql = "update student set isdeleted = 1 where id = ?";QueryRunner qr = new QueryRunner();//增删改均用update方法return qr.update(con,sql,id)==1;}catch(Exception ex){ex.printStackTrace();return false;}}

更新xmlOperation.html中的JS函数

   function delStu(id){if(confirm("确定删除这条数据吗?")){create();request.open("post", "del", true);request.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");request.onreadystatechange = function(){if(request.readyState == 4){if(request.status == 200){let value = request.responseText;if(value == "suc"){//执行上面的显示方法再次异步查询显示数据showAll();return;}alert("删除失败!");}}};// <a href="目的地?key=value">request.send("id=" + id);}}

servlet/DelStudent.java

package com.test.servlet;import com.test.dao.StudentDaoIf;
import com.test.dao.StudentDaoImpl;import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;public class DelStudent extends HttpServlet {protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {request.setCharacterEncoding("utf-8");response.setContentType("text/plain;charset=utf-8");StudentDaoIf dao = new StudentDaoImpl();PrintWriter out = response.getWriter();if(dao.delStuById(Integer.parseInt(request.getParameter("id")))){out.print("suc");out.close();return;}out.print("err");out.close();}
}

【第48天】AJAX在原生JS中的使用,处理XML数据以及DBUtils的使用,假删除(标记删除)相关推荐

  1. 原生JS中的Ajax

    所谓Ajax,就是在网页中利用 XMLHttpRequest 对象和服务器进行数据交互的方式.而我们常说的原生JS中的Ajax就是围绕XMLHttpRequest对象进行发送请求. 1.XMLHttp ...

  2. 进一步封装axios并调用其读取数据(吐槽~在安卓9.0以下或者IOS10.X以下手机端H5页面不支持,在这两种情况下的系统只能使用ajax或者原生js请求后台数据)

    注意!!!(修改于2020年7月18日) 在安卓9.0以下或者IOS10.X以下手机端H5页面不支持,在这两种情况下的系统只能使用ajax或者原生js请求后台数据 报错截图如下 报错内容: {&quo ...

  3. 原生js中如果有多个onload事件解决方案

    原生js中如果有多个onload事件解决方案 参考文章: (1)原生js中如果有多个onload事件解决方案 (2)https://www.cnblogs.com/happy-8090/p/11830 ...

  4. 【温故知新】——原生js中常用的四种循环方式

    一.引言 本文主要是利用一个例子,讲一下原生js中常用的四种循环方式的使用与区别: 实现效果: 在网页中弹出框输入0   网页输出"欢迎下次光临" 在网页中弹出框输入1   网页输 ...

  5. 原生js中attributes属性

    原生js中attribute属性 <div id="box" title="盒子" class="big"></div&g ...

  6. 原生JS中DOM节点相关API合集

    原生JS中DOM节点相关API合集 节点属性 Node.nodeName //返回节点名称,只读 Node.nodeType //返回节点类型的常数值,只读 Node.nodeValue //返回Te ...

  7. 原生js中nextSibling和nextElementSibling的坑

    作者:拓海老师,公众号:拓海老师 一直以来js的随性让初学者蛋疼菊紧,但是真正玩熟了之后,还是非常有意思的! 今天拓海老师跟大家说一下原生js中获取元素的下一个直接兄弟元素的坑! 业务场景:点击当前元 ...

  8. php xmlreader 读xml,PHP中使用xmlreader读取xml数据示例

    这篇文章主要介绍了PHP中使用xmlreader读取xml数据示例,本文示例相对简单,只包含了一个读取功能,需要的朋友可以参考下 有一个XML文件,,内容如下: 复制代码 代码如下: Simpsons ...

  9. AJAX初识(原生JS版AJAX和Jquery版AJAX)

    一.什么是JSON 1.介绍JSON独立于语言,是一种与语言无关的数据格式.JSON指的是JavaScript对象表示法(JavaScript Object Notation)JSON是轻量级的文本数 ...

最新文章

  1. 打分矩阵Scoring Matrices
  2. 社交网络图挖掘3--重叠社区的发现及Simrank
  3. 饶毅坚守教育学者的风骨,网友鼓励:远离精致利己主义的舒适区
  4. python常用内置函数总结-python常见的内置函数
  5. leetcode 816. Ambiguous Coordinates | 816. 模糊坐标(Java)
  6. springmvc请求返回一个字符_SpringMVC系列之Web利器SpringMVC
  7. 聊一聊Docker与时区
  8. python字典合并几种方式对比,Python合并两个字典的常用方法与效率比较
  9. 实现原理 扫描枪_条码扫描枪工作原理
  10. membercache java_Java开发中的Memcache原理及实现
  11. Java类的方法的理解
  12. 【游戏开发指路】Unity学习路线,三万字大纲(面试题大纲 | 知识图谱 | Unity游戏开发工程师)
  13. 京东领取京豆助力、京喜活动
  14. 安卓开发仿微信图片拖拽_仿微信朋友圈发表图片拖拽和删除功能
  15. PCIe物理层详细总结-PCIe专题知识(一)
  16. 父与子的编程之旅--EasyGui安装问题解决
  17. 3. LaTeX图片的排版、引用与格式
  18. 邦纳光电开关MIAD9R
  19. TypeScript保存代码时自动编译并运行
  20. 野火嵌入式开发板通过pc电脑连接到外网

热门文章

  1. 洛谷P5207 [WC2019]远古计算机
  2. 蓝桥杯Java大学C组近三年真题解析(三)——暴力、模拟题
  3. scanf()函数的详解以及使用时需要注意的一些细节-C语言基础
  4. 【农业科研】改进检测梨树花序算法
  5. MariaDB基础知识和基础命令的使用
  6. 软考项目管理师(高级)快速通过分享
  7. Vue实现放大镜效果
  8. Java基础:(2)变量及数据类型
  9. 省选游记暨后期基础规划
  10. 风险意识,决定了是事半功倍,还是事倍功半,甚至决定了...