Java之Ajax技术
ajax(asynchronouse javascript and xml) 异步的javascript 和 xml(现在常把xml换成json):
ajax是2005年提出的,在2006,2007年迅速的发展,目前很多网站都使用了ajax技术,在招聘软件工程师时,ajax技术是必须要求掌握的。ajax技术包含了几种技术:javascript、xml、css、xstl、dom、xhtml和XMLHttpRequest七种技术,所以ajax就像是粘合剂把七种技术整合到一起,从而发挥各个技术的优势,威力惊人。[新瓶装旧酒,组合拳]ajax是一个与服务端语言无关的技术. 即可以使用在(php/java ee/.net网站/ asp)ajax可以给客户端返回三种格式数据(文本格式 ,xml , json格式)
为什么ajax会如此流行,必然有它的道理。ajax技术解决了很多其它技术解决不了的问题,比如:
(1)页面无刷新的动态数据交换
(2)局部刷新页面【验证用户名唯一】
(3)界面的美观 【增强用户体验】
(4)对数据库的操作
(5)可以返回简单的文本格式,也可以返回 xml文件格式, json数据格式
ajax技术的意义:
互联网的连接是不稳定,谁也不愿意看着自己的电脑从服务器一点一滴的下载数据,那么,ajax是不是解决了这个问题呢,说实话,与其说ajax解决了这个问题,倒不如它只是掩盖了这个问题,它只是在服务器和客户端之间充当了一个缓冲器,让用户误以为服务没有中断。精确的说,ajax并不能提高从服务器端下载数据的速度,而只是使这个等待不那么令人沮丧。但是正是这一点就足以产生巨大的影响和震动,它实际上也对桌面软件产生了巨大的冲击。
ajax在什么地方用的多
1 动态加载数据,按需取得数据。【树形菜单、联动菜单…/省市联动】
2 改善用户体验。【输入内容前提示、带进度条文件上传…】
3 电子商务应用。 【购物车、邮件订阅…】
4 访问第三方服务。 【访问搜索服务、rss阅读器】
ajax 的运行原理分析:
PS:最重要的就是要弄透这四道线,其中4号线需要一个回调函数来实现。
Ajax的原理简单来说通过XmlHttpRequest对象来向服务器发异步请求,从服务器获得数据,然后用javascript来操作DOM而更新页面。这其中最关键的一步就是从服务器获得请求数据。要清楚这个过程和原理,我们必须对 XMLHttpRequest有所了解。XMLHttpRequest是ajax的核心机制,它是在IE5中首先引入的,是一种支持异步请求的技术。简单的说,也就是javascript可以及时向服务器提出请求和处理响应,而不阻塞用户。达到无刷新的效果。
我们先来看看XMLHttpRequest这个对象的属性。
它的属性有:
onreadystatechange 每次状态改变所触发事件的事件处理程序。
responseText 从服务器进程返回数据的字符串形式。
responseXML 从服务器进程返回的DOM兼容的文档数据对象(document)。
status 从服务器返回的数字代码,比如常见的404(未找到)和200(已就绪)
status Text 伴随状态码的字符串信息
readyState 对象状态值
0 (未初始化) 对象已建立,但是尚未初始化(尚未调用open方法)
1 (初始化) 对象已建立,尚未调用send方法
2 (发送数据) send方法已调用,但是当前的状态及http头未知
3 (数据传送中) 已接收部分数据,因为响应及http头不全,这时通过responseBody和responseText获取部分数据会出现错误,
4 (完成) 数据接收完毕,此时可以通过通过responseXml和responseText获取完整的回应数据
- 数据的布局刷新
使用ajax与服务器通信的的步骤
创建一个XMLHttpRequest对象(第一道线)
不同的浏览器创建 XMLHttpRequest 对象的方法是有差异的.我们使用js 的try..catch..
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
function getXmlHttp()
{
var xmlHttp;
try{
// Firefox, Opera 8.0+, Safari
xmlHttp=new XMLHttpRequest();}
catch (e){
// Internet Explorer
try{
xmlHttp=new ActiveXObject("Msxml2.XMLHTTP");}
catch (e){
try{
xmlHttp=new ActiveXObject("Microsoft.XMLHTTP");}
catch (e){
alert("您的浏览器不支持AJAX!");
return false;}}
}}
|
创建url,data,通过 send(),发送请求。(第二道线)
服务器端接收 ajax的请求,做相应处理(操作数据库),然后返回结果。(第三道线)
客户端通过xmlHttpRequest的属性 reponseText , responseXML 取的数据,然后就完成局部刷新当前页面任务。(第四道线)
经典案例:
■ ajax经典案例—无刷新验证用户名
在用户注册时:
1 传统的方法是把用户填写的所有信息都提交到服务器,如果用户名重复,就会出异常。
2 如果使用ajax我们可以只提交用户名,确认用户名是否存在,再让用户点击注册。
配置文件(仅使用了servlet):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
<?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">
<servlet>
<servlet-name>ZMC</servlet-name>
<servlet-class>com.Register</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ZMC</servlet-name>
<url-pattern>/register</url-pattern>
</servlet-mapping>
</web-app>
|
服务端:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
package com;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class Register extends HttpServlet {
private static final long serialVersionUID = 1L;
public Register() {
super();
// TODO Auto-generated constructor stub
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html");
response.setCharacterEncoding("utf-8");
if(!request.getParameter("user").equals("zmc")){
response.getWriter().println("这个名字可以注册");//三号线
}
else{
response.getWriter().println("这个名字不可以注册");//三号线
}
}
}
|
客户端请求页面:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
|
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>无刷新验证用户名</title>
<script type="text/javascript">
//创建ajax引擎
//原理图中的一号线
function getXmlHttpObject(){
var xmlHttpRequest;
//不同的浏览器获取对象XmlHttpRequest 对象方法不一样
if(window.ActiveXObject){
xmlHttpRequest=new ActiveXObject("Microsoft.XMLHTTP");
}else{
xmlHttpRequest=new XMLHttpRequest();
}
return xmlHttpRequest;
}
var myXmlHttpRequest=null;//设置全局变量
//验证用户名是否存在
function checkName(){
myXmlHttpRequest=getXmlHttpObject();
//判断XMLHttpRequest对象是否创建成功
if(myXmlHttpRequest){
//通过myXmlHttpRequest对象发送请求到服务器的某个页面
//第一个参数表示请求的方式, "get" / "post"
//第二个参数指定url,对哪个页面发出ajax请求(本质仍然是http请求)
//第三个参数表示 true表示使用异步机制,如果false表示不使用异步
var data="user="+$('username').value;
var url="/AjaxDemo/register";
//打开请求.
myXmlHttpRequest.open("post",url,true);
myXmlHttpRequest.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
myXmlHttpRequest.setRequestHeader("RequestType","ajax");
//指定回调函数.chuli是函数名
//注意在Ajax中函数是调用,函数()是引用函数地址
//状态改变的事件触发器,共四种状态
myXmlHttpRequest.onreadystatechange=chuli;
//真的发送请求,如果是get请求则填入 null即可
//如果是post请求,则填入实际的数据
//这就是原理图中的二号线
//如果是get方法,参数写null
myXmlHttpRequest.send(data);
}
}
//回调函数
//一次请求回调函数会被调用四次,分为四种状态,我们关心的是第四种状态即:完成
//原理图中的四号线
function chuli(){
//window.alert("处理函数被调回"+myXmlHttpRequest.readyState);
//我要取出从registerPro.php页面返回的数据
if(myXmlHttpRequest.readyState==4){//最好把响应状态码为200也加入判断
//取出值,根据返回信息的格式定.text
//window.alert("服务器返回"+myXmlHttpRequest.responseText);
$('myRes').value=myXmlHttpRequest.responseText;
}
}
//这里我们写一个函数,一般根据id取元素函数名都写为$
function $(id){
return document.getElementById(id);
}
</script>
</head>
<body>
<!--
onkeyup:键入一个字符便会触发它,在这个例子中便是调用checkName()函数。
-->
<form action="???" method="post">
用户名字:<input type="text" onkeyup="checkName();" name="username1" id="username">
<input type="button" onclick="checkName();" value="验证用户名">
<input style="border-width: 0;color: red" type="text" id="myRes">
<br/>
用户密码:<input type="password" name="password"><br>
电子邮件:<input type="text" name="email"><br/>
<input type="submit" value="用户注册">
</form>
<form action="???" method="post">
用户名字:<input type="text" name="username2" >
<br/>
用户密码:<input type="password" name="password"><br>
电子邮件:<input type="text" name="email"><br/>
<input type="submit" value="用户注册">
</form>
</body>
</html>
|
响应结果图:
PS:使用get方式发出请求,如果提交的用户名不变化,浏览器将不会真的发请求,而是缓存取数据., url解决方法
- url 后带一个总是变化的参数,比如当前时间
1
|
var url="/ajax/registerProcess.php?mytime="+new Date()+"&username="+$("username").value;
|
- 在服务器回送结果时,禁用缓存.
//这里两句话很重要,第一讲话告诉浏览器返回的数据是xml格式
header(“Content-Type: text/xml;charset=utf-8”);
//告诉浏览器不要缓存数据
header(“Cache-Control: no-cache”);
AJAX 可以在php项目,java ee项目,.net项目使用。在服务器端的业务逻辑层使用何种服务器端语言都可以。
从服务器端接收数据的时候,那些数据必须以浏览器能够理解的格式来发送。服务器端的编程语言一般以如下 3 种格式返回数据:Text(又称Html格式)、XML、JSON。
返回Html格式
HTML 由一些普通文本组成。如果服务器通过 XMLHttpRequest 发送 HTML, 文本将存储在 responseText 属性中。
不必从 responseText 属性中读取数据。它已经是希望的格式,可以直接将它插入到页面中。
插入 HTML 代码最简单的方法是更新这个元素的 innerHTML 属性。
innerHTML 并非 DOM 标准。
■ 返回xml格式优点:
XML 是一种通用的数据格式。不必把数据强加到已定义好的格式中,而是要为数据自定义合适的标记。利用 DOM 可以完全掌控文档。
缺点:如果文档来自于服务器,就必须得保证文档含有正确的首部信息。若文档类型不正确,那么 responseXML 的值将是空的。当浏览器接收到长的 XML 文件后, DOM 解析可能会很复杂
PS:不管是返回的何种类型,影响的只是三四号线
上面的那个例子便是返回了text格式,现在还是拿上面那个例子返回xml 格式:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
function chuli(){
if(myXmlHttpRequest.readyState==4){
//看看如果取出 xml格式数据,返回的是document对象,xml //dom
//获取mes节点
var mes=myXmlHttpRequest.responseXML.getElementsByTagName("mes");
//取出mes节点值
//mes[0]->表示取出第一个mes节点
//mes[0].childNodes[0]->表示第一个mes节点的第一个子节点
var mes_val=mes[0].childNodes[0].nodeValue;
$('myres').value=mes_val;
}
}
//这里两句话很重要,第一讲话告诉浏览器返回的数据是xml格式
header("Content-Type: text/xml;charset=utf-8");
//告诉浏览器不要缓存数据
header("Cache-Control: no-cache");
response.setContentType("text/html");
response.setCharacterEncoding("utf-8");
if(!request.getParameter("user").equals("zmc")){
response.getWriter().println("<res><mes>用户名不可以用,对不起</mes></res>");//三号线
}
|
返回JSON格式:(推荐)
JSON 只是一种文本字符串。它被存储在 responseText 属性中。为了读取存储在 responseText 属性中的 JSON 数据,需要根据 JavaScript 的 eval 语句。函数 eval 会把一个字符串当作它的参数。然后这个字符串会被当作 JavaScript 代码来执行。因为 JSON 的字符串就是由 JavaScript 代码构成的,所以它本身是可执行的
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html");
response.setCharacterEncoding("utf-8");
String str="{'ceshi':'这个名字可以注册'}";
String str2="{'ceshi':'这个名字不可以注册'}";
if(!request.getParameter("user").equals("zmc")){
response.getWriter().println(str);//三号线
}
else{
response.getWriter().println(str2);//三号线
}
}
}
function chuli(){
if(myXmlHttpRequest.readyState==4){
//取出值,根据返回信息的格式json字符串 //window.alert("服务器返回"+myXmlHttpRequest.responseText);
var str = myXmlHttpRequest.responseText;
var json = eval("("+str+")");
$('myRes').value=json.ceshi;
}
|
小结:
当一个ajax请求到服务器,服务器可以根据需求返回 三种格式的数据,那么我们应当选择哪一个?
- 如果你的项目经理没有特殊的要求,建议使用json
- 若应用程序不需要与其他应用程序共享数据的时候, 使用 HTML 片段来返回数据时最简单的
- 如果数据需要重用, JSON 文件是个不错的选择, 其在性能和文件大小方面有优势
- 当远程应用程序未知时, XML 文档是首选, 因为 XML 是 web 服务领域的 “世界语”
■ ajax经典案例—省市联动
ajax一个最重要的用途就是,动态的从服务器取需要的数据,并在页面无刷新的显示,我们来看一个经典的用法:省市联动菜单:
1 传统的b/s中,显示省市联动菜单是一次性把数据全部取出,并在客户端显示,这样做数据传输量大,不灵活。
2 使用ajax技术,可以根据用户需求从服务器取数据,当用户点击某个按钮时,才从服务器取数据并显示,灵活。让学生从数据库取出数据,县城级别联动做出.
ajax的省市联动案例(如何动态的从服务器取得数据),这里只贴了一部分代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
|
function getCities(){
myXmlHttpRequest=getXmlHttpObject();
if(myXmlHttpRequest){
var url="/ajax/showCitiesPro.php";//post
var data="province="+$('sheng').value;
myXmlHttpRequest.open("post",url,true);//异步方式
myXmlHttpRequest.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
//指定回调函数
myXmlHttpRequest.onreadystatechange=chuli;
//发送
myXmlHttpRequest.send(data);
}
}
function chuli(){
if(myXmlHttpRequest.readyState==4){
if(myXmlHttpRequest.status==200){
//取出服务器回送的数据
var cities=myXmlHttpRequest.responseXML.getElementsByTagName("city");
$('city').length=0;
var myOption=document.createElement("option");
myOption.innerText="--城市--";
//添加到
$('city').appendChild(myOption);
//遍历并取出城市
for(var i=0;i<cities.length;i++){
var city_name=cities[i].childNodes[0].nodeValue;
//创建新的元素option
var myOption=document.createElement("option");
myOption.value=city_name;
myOption.innerText=city_name;
//添加到
$('city').appendChild(myOption);
}
}
}
}
//这里我们写一个函数
function $(id){
return document.getElementById(id);
}
</script>
</head>
<body>
<select id="sheng" onchange="getCities();">
<option value="">---省---</option>
<option value="zhejiang">浙江</option>
<option value="jiangsu" >江苏</option>
<option value="sichuan" >四川</option>
</select>
<select id="city">
<option value="">--城市--</option>
</select>
<select id="county">
<option value="">--县城--</option>
</select>
</body>
</html>
**showCitiesProcess.php**
<?php
//服务器端
//这里两句话很重要,第一讲话告诉浏览器返回的数据是xml格式
header("Content-Type: text/xml;charset=utf-8");
//告诉浏览器不要缓存数据
header("Cache-Control: no-cache");
//接收用户的选择的省的名字
$province=$_POST['province'];
file_put_contents("d:/mylog.log",$province."\r\n",FILE_APPEND);
//如何在调试过程中,看到接收到的数据 。
//到数据库去查询省有那些城市(现在先不到数据库)
$info="";
if($province=="zhejiang"){
$info="<province><city>杭州</city><city>温州</city><city>宁波</city></province>";
}else if($province=="jiangsu"){
$info="<province><city>南京</city><city>徐州</city><city>苏州</city></province>";
}
echo $info;
?>
|
PS:服务器不可能主动给客户端发消息,拿手机收到短信举例,其实是手机上有一个发射器,它会在规定时间内如2秒定时去服务器上的数据库中查找是否有自己未接收的短信,如果有就接收到。