Ajax(Asynchronous JavaScript and XML) 异步JavaScript和XMLjavascript
Ajax其实是下面这几种技术的融合:html
客户端与服务器,能够在【没必要刷新整个浏览器】的状况下,与服务器进行异步通信的技术前端
在咱们以前的开发,每当用户向服务器发送请求,哪怕只是须要更新一点点的局部内容,服务器都会将整个页面进行刷新。java
Ajax就是可以作到局部刷新!node
XMLHttpRequest对象是Ajax中最重要的一个对象。使用Ajax更多的是编写客户端代码,而不是服务端的代码。web
传统的web前端与后端的交互中,浏览器直接访问Tomcat的Servlet来获取数据。Servlet经过转发把数据发送给浏览器。ajax
当咱们使用AJAX以后,浏览器是先把请求发送到XMLHttpRequest异步对象之中,异步对象对请求进行封装,而后再与发送给服务器。服务器并非以转发的方式响应,而是以流的方式把数据返回给浏览器数据库
XMLHttpRequest异步对象会不停监听服务器状态的变化,获得服务器返回的数据,就写到浏览器上【由于不是转发的方式,因此是无刷新就可以获取服务器端的数据】编程
要建立XMLHttpRequest对象是要分两种状况考虑的:json
<script type="text/javascript"> var httpRequest; if(window.XMLHttpRequest) { //在IE6以上的版本以及其余内核的浏览器(Mozilla)等 httpRequest = new XMLHttpRequest(); }else if(window.ActiveXObject) { //在IE6如下的版本 httpRequest = new ActiveXObject(); } </script>
经常使用的方法就是黑色粗体的前三个
open():该方法建立http请求
setRequestHeader(String header,String value):设置消息头(使用post方式才会使用到,get方法并不须要调用该方法)
send(content):发送请求给服务器
readyState:请求状态readyState一改变,回调函数被调用,它有5个状态
上面有两个地方都说起了回调函数,回调函数是什么??
回调函数就是接收服务器返回的内容!
检测用户输入的用户名是否为"zhongfucheng",只要不是zhongfucheng,就可使用!
<input type="text" id="username"> <input type="button" onclick="checkUsername()" value="检测用户名是否合法"> <div id="result"> </div>
<script type="text/javascript"> var httpRequest; function checkUsername() { if(window.XMLHttpRequest) { //在IE6以上的版本以及其余内核的浏览器(Mozilla)等 httpRequest = new XMLHttpRequest(); }else if(window.ActiveXObject) { //在IE6如下的版本 httpRequest = new ActiveXObject(); } //建立http请求 httpRequest.open("POST", "Servlet1", true); //由于我使用的是post方式,因此须要设置消息头 httpRequest.setRequestHeader("Content-type", "application/x-www-form-urlencoded"); //指定回调函数 httpRequest.onreadystatechange = response22; //获得文本框的数据 var name = document.getElementById("username").value; //发送http请求,把要检测的用户名传递进去 httpRequest.send("username=" + name); } function response22() { //判断请求状态码是不是4【数据接收完成】 if(httpRequest.readyState==4) { //再判断状态码是否为200【200是成功的】 if(httpRequest.status==200) { //获得服务端返回的文本数据 var text = httpRequest.responseText; //把服务端返回的数据写在div上 var div = document.getElementById("result"); div.innerText = text; } } } </script>
实现了局部更新,不须要刷新整一个页面
在传统的Web中咱们已经解决过中文乱码问题了。
接下来,要介绍的是:咱们能够屏蔽任何浏览器和任何服务器的编码格式,浏览器发送给服务器的数据不形成乱码问题!
具体咱们是这样作的:
为啥我能说这种方式屏蔽任何浏览器和服务器的编码格式,都不会乱码呢??
在传统的Web中咱们也解决过缓存的问题,经过设置response的头信息,返回给浏览器就能够实现不缓存页面了。
可是呢,如今咱们使用XMLHttpRequest,拿到的不是全新的页面,仅仅是服务器端发送过来的数据!!
那咱们要怎么解决缓存的问题呢??产生缓存的缘由就是:咱们请求了同一个地址,作了相同的操做。服务端认为个人操做并无什么变化,就直接把缓存的信息给我了。这样的话,我就不能更换验证码图片了(等等应用)。
咱们能够这样作:
加入时间戳参数到url时,也分两种状况
if(url.indexOf("?") >= 0){ url = url + "&t=" + (new Date()).valueOf(); } else{ url = url + "?t=" + (new Date()).valueOf(); }
使用XMLHttpRequest去跨域访问是会出现错误的。
咱们要怎么解决呢??这时候就要用代理思想了
这个时候,XMLHttpRequest跨域访问就分两种(GET和POST)状况了,由于这两种提交数据的方式是不同的!
GET方式是直接把参数的信息都放在url地址上,因此处理起来会相对简单。
步骤:
BufferedReader reader = new BufferedReader(new InputStreamReader(URL对象.openSteam(),"UTF-8"));
POST方式把参数的信息都封装到HTTP请求中,在URL进行链接的时候,须要把数据写给远程服务器
步骤:
URL url = new URL(url); URLConnection connection = url.openConnection; connection.setDoOutPut(true);
OutputSteamWriter writer = new OutputSteamWriter(conncetion.getOutputSteam)
BufferedReader reader = new BufferedReader(new InputSteamReader(conncetion.inputSteamReader,"UTF-8"));
咱们在购物的时候,经常须要咱们来选择本身的收货地址,先选择省份,再选择城市...
有没有发现:当咱们选择完省份的时候,出现的城市所有都是根据省份来给咱们选择的。这是怎么作到的呢???其实就是经过AJAX来完成的。使用AJAX技术让咱们看起来网页很是“智能”,会根据省份来给出对应的城市信息。
咱们这里就不读取数据库了,直接在Servlet写死数据来进行模拟测试。
咱们知道AJAX与服务器之间的交互经常使用的传输载体格式有三种:
因为省份与城市是有层级关系的,所以咱们只能用XML或者JSON。
咱们这里首先就用XML来进行,后面会使用JSON,来看看他俩有什么不一样的地方。。
当用户选择了某个省份以后,就使用AJAX与服务器进行交互,那么在选择城市的时候就出现对应的城市信息。
<%-- Created by IntelliJ IDEA. User: ozc Date: 2017/5/17 Time: 19:38 To change this template use File | Settings | File Templates. --%> <%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>多级联动</title> <script type="text/javascript" src="js/ajax.js"></script> </head> <body> <%--############前台页面###################--%> <select name="province" id="provinceId"> <option value="-1">请选择省份</option> <option>广东</option> <option>湖南</option> </select> <select name="city" id="cityId"> <option>请选择城市</option> </select> <%--############AJAX###################--%> <script type="text/javascript"> document.getElementById("provinceId").onchange = function () { /**********定位到下拉框,获取下拉框的值***************/ // 获取选中的下拉框索引值 var index = this.selectedIndex; // 获得下拉框的值 var province = this.options[index].innerHTML; //下拉框的值要是“请选择”,那么咱们是不会访问服务器的 if ("请选择省份" != province) { /********因为每次都会自动添加,所以每次在调用的时候清除***********/ var citySelect = document.getElementById("cityId"); //每次都将option变成长度只有1的 citySelect.options.length = 1; /*************ajax代码*********************/ //建立AJAX对象 var ajax = createAJAX(); //准备发送请求 var method = "post"; var url = "${pageContext.request.contextPath}/ProvinceServlet?time=" + new Date().getTime(); ajax.open(method, url); //因为是POST方式,所以要设置头 ajax.setRequestHeader("content-type", "application/x-www-form-urlencoded"); ajax.send("province=" + province); /************ajax回调函数*********************/ ajax.onreadystatechange = function () { if (ajax.readyState == 4) { if (ajax.status == 200) { //获得服务器端带过来的XML var XMLDocument = ajax.responseXML; /**********解析XML文档,使用DOM写到下拉框中****************/ var cities = XMLDocument.getElementsByTagName("city"); //获得每个cities节点的值,动态生成下拉框,添加到下拉框中 for (var i = 0; i < cities.length; i++) { var value = cities[i].firstChild.nodeValue; //动态生成下拉框 var optionElement = document.createElement("option"); optionElement.innerHTML = value; //添加到下拉框中 citySelect.appendChild(optionElement); } } } }; } }; </script> </body> </html>
import java.io.IOException; import java.io.PrintWriter; /** * Created by ozc on 2017/5/17. */ @javax.servlet.annotation.WebServlet(name = "ProvinceServlet",urlPatterns = "/ProvinceServlet") public class ProvinceServlet extends javax.servlet.http.HttpServlet { protected void doPost(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response) throws javax.servlet.ServletException, IOException { //设置中文编码 request.setCharacterEncoding("UTF-8"); String province = request.getParameter("province"); //这里是返回的是XML,所以指定XML数据! response.setContentType("text/xml;charset=UTF-8"); PrintWriter printWriter = response.getWriter(); /****************返回XML文件给前台**************/ printWriter.write("<?xml version='1.0' encoding='UTF-8'?>"); printWriter.write("<root>"); if("广东".equals(province)){ printWriter.write("<city>广州</city>"); printWriter.write("<city>深圳</city>"); printWriter.write("<city>中山</city>"); }else if("湖南".equals(province)){ printWriter.write("<city>长沙</city>"); printWriter.write("<city>株洲</city>"); printWriter.write("<city>湘潭</city>"); printWriter.write("<city>岳阳</city>"); } printWriter.write("</root>"); System.out.println("1111"); /*******过后操做*******/ printWriter.flush(); printWriter.close(); } protected void doGet(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response) throws javax.servlet.ServletException, IOException { this.doPost(request, response); } }
异步对象解析服务器带过来的数据,使用DOM编程把数据动态添加到页面上
前面咱们已经使用过了XML做为数据载体在AJAX中与服务器进行交互。当时候咱们的案例是二级联动,使用Servlet进行控制
此次咱们使用JSON做为数据载体在AJAX与服务器交互,使用三级联动,使用Action进行控制....
与上次是同样的,只不过此次换了用JSON,使用Action控制罢了...
监听下拉框的变更,使用异步对象与服务器进行交互。
<%-- Created by IntelliJ IDEA. User: ozc Date: 2017/5/18 Time: 13:36 To change this template use File | Settings | File Templates. --%> <%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>使用JSON数据载体与服务器进行交互</title> <script type="text/javascript" src="js/ajax.js"></script> </head> <body> <%--############前台页面##############################--%> <select name="province" id="provinceId"> <option>请选择省份</option> <option>广东</option> <option>北京</option> </select> <select name="city" id="cityId"> <option>请选择城市</option> </select> <select name="area" id="areaId"> <option>请选择区域</option> </select> <%--############监听省份##############################--%> <script type="text/javascript"> document.getElementById("provinceId").onchange= function () { // 获得选中的下拉框的值 var provinceValue = this.options[this.selectedIndex].innerHTML; /***************ajax代码*************************/ if("请选择省份" != provinceValue) { //每次访问的时候,都要清空select的值 var citySelect = document.getElementById("cityId"); citySelect.options.length = 1; var ajax = createAJAX(); var method = "post"; var url = "${pageContext.request.contextPath}/province_findCityByProvince?time=" + new Date().getTime(); ajax.open(method, url); ajax.setRequestHeader("content-type", "application/x-www-form-urlencoded"); //顾及到发送的key、value值有不少,因而咱们使用对象吧。 ajax.send("bean.name=" + provinceValue); /***************等待服务器的响应,获得服务器返回的数据************************/ ajax.onreadystatechange = function () { if(ajax.readyState==4) { if(ajax.status==200) { var jsonJava = ajax.responseText; //解析成是JS类型的JSON var json = eval("(" + jsonJava + ")"); //获得每一个城市的值 for(var i=0;i<json.city.length;i++) { var city = json.city[i]; //动态建立option控件 var option = document.createElement("option"); option.innerHTML = city; citySelect.appendChild(option); } } } }; } }; </script> </body> </html>
要想Struts2可以把Action的数据封装成JSON,就须要导入Struts2的开发包
在Action中对应的成员属性须要给getter方法
import com.opensymphony.xwork2.ActionSupport; import java.util.ArrayList; import java.util.List; /** * Created by ozc on 2017/5/18. */ public class ProvinceAction extends ActionSupport{ //自动封装数据 private Bean bean; public Bean getBean() { return bean; } public void setBean(Bean bean) { this.bean = bean; } //封装城市的集合 private List<String> city = new ArrayList<>(); public List<String> getCity() { return city; } public String findCityByProvince() throws Exception { if ("广东".equals(bean.getName())) { city.add("广州"); city.add("珠海"); city.add("从化"); } else if ("北京".equals(bean.getName())) { city.add("一环"); city.add("二环"); city.add("三环"); city.add("四环"); } else { System.out.println("没有你选择的地区"); } return "ok"; } }
返回给前端的时候,数据是这样子的:
<%--############监听城市##############################--%> <script type="text/javascript"> document.getElementById("cityId").onchange = function () { //清空值 var areaSelect = document.getElementById("areaId"); areaSelect.options.length = 1; //获得选择选中的下拉框的值 var cityValue = this.options[this.selectedIndex].innerHTML; if(cityValue!="请选择城市"){ var ajax = createAJAX(); var method = "post"; var url = "${pageContext.request.contextPath}/province_findAreaByCity?time=" + new Date().getTime(); ajax.open(method, url); ajax.setRequestHeader("content-type", "application/x-www-form-urlencoded"); //顾及到发送的key、value值有不少,因而咱们使用对象吧。 ajax.send("bean.name=" + cityValue); /***************等待服务器的响应,获得服务器返回的数据************************/ ajax.onreadystatechange = function () { if(ajax.readyState==4) { if(ajax.status==200) { var jsonJava = ajax.responseText; var json = eval("(" + jsonJava + ")"); //获得每一个地区的值 for(var i=0;i<json.area.length;i++) { var area = json.area[i]; //动态建立option控件 var option = document.createElement("option"); option.innerHTML = area; areaSelect.appendChild(option); } } } } }; }; </script>
public String findAreaByCity() throws Exception { if ("广州".equals(bean.getName())) { area.add("白云区"); area.add("黄浦区"); area.add("萝岗区"); } else if ("珠海".equals(bean.getName())) { area.add("香江"); area.add("拱北"); area.add("EE"); area.add("xx"); } else { System.out.println("没有你选择的地区"); } return "ok"; }
此次使用的是JSON做为数据载体与服务器进行交互,和XML本质上是没有区别的。
只不过JSON是更加轻量级文本数据,在JavaScript可以方便地获取返回的数据
在Struts2中把Action数据封装成JSON格式,返回给异步对象
若是文章有错的地方欢迎指正,你们互相交流。习惯在微信看技术文章的同窗,能够关注微信公众号:Java3y