【第48天】AJAX在原生JS中的使用,处理XML数据以及DBUtils的使用,假删除(标记删除)
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或者post url:提交到哪里,注意如果是get方式则从此处传递值 url?key=value async:表示是否使用异步,默认为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; //拿取span let dom_sp = document.getElementById("name_msg"); //拿取submit let 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
注:
- CONTENT-TYPE: application/x-www-form-urlencoded含义是表示客户端提交给服务器文本内容的编码方式是URL编码,即除了标准字符外,每字节以双字节16进制前加个“%”表示。当然还有其他编码方式,如CONTENT-TYPE:multipart/form-data。
- 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大小了。
- 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(); @Override public 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; } } @Override public 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方法
@Override public 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(); } }
- ajax使用原生js获取xml数据
- 使用原生Ajax处理HTML,XML,JSON数据
- AJAX 原生js以及Jquery解析html,xml,txt,json格式文本
- Jquery学习笔记(10)--ajax删除用户,使用了js原生ajax
- ajax使用原生js获取json数据
- Ajax 使用XMLHttpRequest对象发送数据和接收处理XML源代码
- ajax 传值,Ajax: Asynchoronous Javascript and xml (异步的js和xml). 异步刷新,异步传递.替代表单提交数据,回调函数处理返回的数据
- JS使用ajax从xml文件动态获取数据显示的方法
- JS使用ajax从xml文件动态获取数据显示的方法
- AJAX提交数据时 中文处理 以及js url 中文处理
- 原生JS的ajax处理json数据格式的异步请求完整例子
- 使用原生JavaScriptAjax以及jQuery的Ajax结合SpringMVC发送和获取json数据
- 习惯了使用jQuery的ajax方法,看看原生js使用xmlhttpRequest实现ajax请求
- AJAX学习笔记之XML对象原生JS使用方法
- 原生js如何实现柱状图以及原生js柱状图结合ajax循环动态数据_JavaScript_柱状图(原生JavaScript做的柱状图)(03)_ajax获取数据
- 使用原生JS编写ajax操作XMLHttpRequst对象
- 【菜鸟学WCF】使用js+ajax调用WCF以及返回数据类型的控制
- ajax使用原生js获取html数据
- [jQuery] 关于使用 ajax 时处理返回的数据
- 取从textarea中存到MYSQL的数据以原格式显示问题以及解决MySQL日期处理和标签的使用