【JavaWeb】异步请求——AJAX

目录

Ajax(Asynchronous JavaScript and XML)

  • 使用JavaScript 和 XML实现的异步刷新技术
  • Ajax不是新的编程语言,而是一种使用现有标准的新方法
  • Ajax是一种在无需重新加载整个网页的情况下,能够与服务器交换数据并更新部分网页的技术
  • Ajax最大的优点是页面无刷新,用户的体验非常好。并且使用异步方式与服务器通信,具有更加迅速的响应能力

优点

  • 我们可以使用Ajax进行无刷新,无刷新是指不刷新整个页面,只刷新局部。
  • 无刷新的好处: 只更新部分页面,有效利用带宽,提高用户体验
    • 只更新部分页面,有效利用带宽
    • 提供连续的用户体验
    • 提供类似C/S的交互效果,
    • 操作更方便

传统Web与Ajax的差异

差异 说明
发送请求方式不同 传统Web 浏览器发送同步请求 Ajax技术 异步引擎对象发送请求
服务器响应不同 传统Web 响应内容是一个完整页面 Ajax技术 响应内容只是需要的数据
客户端处理方式不同 传统Web 需等待服务器响应完成并重新加载整个页面后用户才能进行操作 Ajax技术 可以动态更新页面中的部分内容,不影响用户在页面进行其他操作

Ajax工作流程

Ajax 经典应用场景

  • 搜索引擎根据用户输入关键字,自动提示检索关键字
  • 动态加载数据,按需取得数据【树形菜单、联动菜单...】
  • 改善用户体验。【输入内容前提示、带进度条文件上传...】
  • 电子商务应用。 【购物车、邮件订阅...】
  • 访问第三方服务。【访问搜索服务、rss 阅读器】
  • 页面局部刷新

XMLHttpRequest

  • 整个Ajax技术的核心
  • 提供异步发送请求的能力

常用方法

方 法 说 明
open( String method, String url, boolean async, String user, String password ) 创建一个新的HTTP请求
send( String data ) 发送请求到服务器端
abort( ) 取消当前请求
setRequestHeader( String header, String value ) 设置请求的某个HTTP头信息
getResponseHeader( String header ) 获取响应的指定HTTP头信息
getAllResponseHeader( ) 获取响应的所有HTTP头信息

事件

  • onreadystatechange:指定回调函数

常用属性

  • readyState:XMLHttpRequest的状态信息
就绪状态码 说 明
0 XMLHttpRequest对象未完成初始化
1 XMLHttpRequest对象开始发送请求
2 XMLHttpRequest对象的请求发送完成
3 XMLHttpRequest对象开始读取响应
4 XMLHttpRequest对象读取响应结束
  • status:HTTP的状态码
状态码 说 明
200 服务器正确返回响应
404 请求的资源不存在
500 服务器内部错误
403 没有访问权限
... ......
  • statusText:返回当前请求的响应状态
  • responseText:以文本形式获得响应的内容
  • responseXML:将XML格式的响应内容解析成DOM对象

ajax: GET请求和POST请求的区别

步 骤 请求方式 实 现 代 码
初始化组件 GET xmlHttpRequest.open( "GET", url, true );
初始化组件 POST xmlHttpRequest.open( "POST", url, true ); xmlHttpRequest.setRequestHeader( "Content-Type","application/x-www-form-urlencoded" );
发送请求 GET xmlHttpRequest.send( null );
发送请求 POST xmlHttpRequest.send("key=xxx&type=12&year=20124" );

传统Ajax实现

html 复制代码
<!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" src="js/jquery-1.12.4.min.js"></script>
<script type="text/javascript">
	function validate() {
		var name = $("#name").val();
		if (name == null || name == "") {
			$("#nameDiv").html("用户名不能为空!");
		} else {
			//1.创建XMLHttpRequest对象
			xmlHttpRequest = createXmlHttpRequest();
			//2.设置回调函数
			xmlHttpRequest.onreadystatechange = callBack;
			//3.初始化XMLHttpRequest组件
			var url = "userServlet?name=" + name;//服务器端URL地址,name为用户名文本框获取的值
			xmlHttpRequest.open("GET", url, true);
			//4.发送请求
			xmlHttpRequest.send(null);
			/* 使用POST方式发送请求
			var url = "userServlet";//服务器端URL地址
			xmlHttpRequest.open("POST", url, true);
			xmlHttpRequest.setRequestHeader("Content-Type",
					"application/x-www-form-urlencoded");
			var data = "name=" + name;//需要发送的数据信息,name为用户名文本框获取的值
			xmlHttpRequest.send(data);
            */
			//Ajax 回调函数
			function callBack() {
				if (xmlHttpRequest.readyState == 4
						&& xmlHttpRequest.status == 200) {
					var data = xmlHttpRequest.responseText;
					if (data == "true") {
						$("#nameDiv").html("用户名已被使用!");
					} else {
						$("#nameDiv").html("用户名可以使用!");
					}
				}
			}//end of callBack()
		}
	}//end of validate()

	/*
	 *创建XMLHttpRequest对象
	 */
	function createXmlHttpRequest() {
		if (window.XMLHttpRequest) {//返回值为true时说明是新版本IE或其他浏览器
			return new XMLHttpRequest();
		} else {//返回值为false时说明是老版本IE浏览器(IE5和IE6)
			return new ActiveXObject("Microsoft.XMLHTTP");
		}
	}
</script>
</head>
<body>
	<form action="" id="form1">
		<table>
			<tr>
				<td>用 户 名:</td>
				<td><input type="text" name="name" id="name"
					onblur="validate();" />&nbsp;<font color="#c00fff">*</font></td>
				<td>
					<div id="nameDiv" style="display: inline"></div></td>
			</tr>
		</table>
	</form>
</body>
</html>

传统方式实现Ajax的不足

  1. 步骤繁琐
  2. 方法、属性、常用值较多不好记忆
  3. 处理复杂结构的响应数据(如XML格式)比较烦琐
  4. 浏览器兼容问题

jQuery将Ajax相关操作都进行了封装

$.ajax()

语法

$.ajax( [settings] );

javascript 复制代码
$.ajax( {
      "url"      :  "url",      	// 要提交的URL路径
      "type"     :  "get",        	// 发送请求的方式
      "data"     :  data,         	// 要发送到服务器的数据
      "dataType" :  "text",           	// 指定传输的数据格式
      "success"  :  function(result) {  // 请求成功后要执行的代码
	   },
      "error"    :  function() {  	// 请求失败后要执行的代码
	   }
} );

常用属性参数

参 数 类 型 说 明
url String 发送请求的地址,默认为当前页地址
type String 请求方式,默认为GET
data PlainObject或 String或Array 发送到服务器的数据
dataType String 预期服务器返回的数据类型,包括:XML、HTML、Script、JSON、JSONP、text
timeout Number 设置请求超时时间
global Boolean 表示是否触发全局Ajax事件,默认为true

常用函数参数

参 数 类 型 说 明
beforeSend Function ( jqXHR jqxhr,PlainObject settings ) 发送请求前调用的函数
success Function( 任意类型 result,String textStatus, jqXHR jqxhr ) 请求成功后调用的函数 参数result:可选,由服务器返回的数据
error Function ( jqXHR jqxhr, String textStatus, String errorThrown) 请求失败时调用的函数
complete Function ( jqXHR jqxhr,String textStatus ) 请求完成后(无论成功还是失败)调用的函数
html 复制代码
<!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" src="js/jquery-1.12.4.min.js"></script>
<script type="text/javascript">
$(document).ready(function() {
	$("#name").blur(function() {
		var name = this.value;
		if (name == null || name == "") {
			$("#nameDiv").html("用户名不能为空!");
		} else {
			$.ajax({
                "url"       : "userServlet",   //要提交的URL路径
                "type"      : "GET",           //发送请求的方式
                "data"      : "name="+name,    //要发送到服务器的数据
                "dataType"  : "text",          //指定返回的数据格式
                "success"   : callBack,        //响应成功后要执行的代码
                "error"     : function() {     //请求失败后要执行的代码
                    alert("用户名验证时出现错误,请稍后再试或与管理员联系!");
                }
            });

			//响应成功时的回调函数
			function callBack(data) {
				if (data == "true") {
					$("#nameDiv").html("用户名已被使用!");
				} else {
					$("#nameDiv").html("用户名可以使用!");
				}
			}//end of callBack()
		}
	});//end of blur()
});
</script>
</head>
<body>
	<form action="" id="form1">
		<table>
			<tr>
				<td>用 户 名:</td>
				<td><input type="text" name="name" id="name" />&nbsp;<font color="#c00fff">*</font></td>
				<td>
					<div id="nameDiv" style="display: inline"></div></td>
			</tr>
		</table>
	</form>
</body>
</html>

后台servlet:

java 复制代码
	public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        String name = request.getParameter("name");
        boolean used = false;
        if("ajax".equals(name)){
            used = true;
        }else{
            used = false;
        }
        response.setContentType("text/html;charset=UTF-8");
        PrintWriter out = response.getWriter();
        out.print(used);
        out.flush();
        out.close();
    }

Ajax的其他方法

$.get()

语法

$.get( url [, data] [, success] [, dataType] );

javascript 复制代码
$.get( url, data, function( result ) {
	// 省略将服务器返回的数据显示到页面的代码
} );

以上代码等价于

javascript 复制代码
$.ajax( {
	"url"           : url,
	"data"        : data,
	"type"        : "get",
	"success" : function( result ) {
		   // 省略代码
	      }
} );

$.post()

语法

$.post( url [, data] [, success] [, dataType] );

javascript 复制代码
$.post( url, data, function( result ) {
	// 省略将服务器返回的数据显示到页面的代码
} );

以上代码等价于

javascript 复制代码
$.ajax( {
	"url"           : url,
	"data"        : data,
	"type"        : "post",
	"success" : function( result ) {
		   // 省略代码
	      }
} );

$.getJson()

语法

$.getJSON( url [, data] [, success] );

javascript 复制代码
$.getJSON( url, data, function( result ) {
	// 省略将服务器返回的数据显示到页面的代码
} );

以上代码等价于

javascript 复制代码
$.ajax( {
	"url"            : url,
	"data"         : data,
	"type"         : "get",
	"dataType" : "json",
	"success"   : function( result ) {
		   // 省略代码
	      }
} );

.load() [了解]

  • 返回HTML内容并设置到元素中
  • 不是全局函数
  • 匿名的回调函数
  • 默认使用GET方式

JSON(JavaScript Object Notation)

  • 一种轻量级的数据交换格式
  • 采用独立于语言的文本格式
  • 通常用于在客户端和服务器之间传递数据

JSON的优点

  • 轻量级交互语言
  • 结构简单
  • 易于解析

定义JSON对象

var JSON对象 = { "name" : value, "name" : value, ...... };

javascript 复制代码
var person = { "name" : "张三",   "age" : 30,  "spouse" : null };

定义JSON数组

var JSON数组 = [ value, value, ...... ];

javascript 复制代码
var countryArray = [ "中国",  "美国",  "俄罗斯" ];
var personArray = [ { "name":"张三",  "age":30 },{ "name":"李四",  "age":40 } ];

JSON使用综合案例

html 复制代码
<!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" src="js/jquery-1.12.4.min.js"></script>
<script type="text/javascript">
$(document).ready(function() {
	//1、定义JSON格式的user对象,并在div中输出
	var user = {
		"id" : 1,
		"name" : "张三",
		"pwd" : "000"
	};
	$("#objectDiv").append("ID:" + user.id + "<br>")
	               .append("用户名:" + user.name + "<br>")
	               .append("密码:" + user.pwd + "<br>");
	//2、定义JSON格式的字符串数组,并在ul和select中输出
	var ary = [ "中", "美", "俄" ];
	var $ary = $(ary);
	var $ul = $("#arrayUl"); // 展示数据的ul元素
	var $sel = $("#arraySel"); // 展示数据的select元素
	$ary.each(function() { $ul.append("<li>"+this+"</li>"); });
	$ary.each(function(i) {
	   $sel.append("<option value='"+(i+1)+"'>"+this+"</option>");
    });
	//3、定义JSON格式的user对象数组,并使用<table>输出
	var userArray = [ {
		"id" : 2,
		"name" : "admin",
		"pwd" : "123"
	}, {
		"id" : 3,
		"name" : "詹姆斯",
		"pwd" : "11111"
	}, {
		"id" : 4,
		"name" : "梅西",
		"pwd" : "6666"
	} ];
	var $table = $("<table border='1'></table>").append(
	       "<tr><td>ID</td><td>用户名</td><td>密码</td></tr>");
	$(userArray).each(function() {
	   $table.append("<tr><td>" + this.id + "</td><td>"
                    + this.name + "</td><td>"
                    + this.pwd + "</td></tr>");
	});
	$("#objectArrayDiv").append($table);

});
</script>
</head>
<body>
一、JSON格式的user对象:<div id="objectDiv"></div><br>
二、JSON格式的字符串数组:&nbsp;&nbsp;<select id="arraySel"></select>
<ul id="arrayUl"></ul>
三、JSON格式的user对象数组:<div id="objectArrayDiv"></div>
</body>
</html>

在Ajax中使用JSON数据格式

javascript 复制代码
jQuery(document).ready(function($) {
	function initNews() {//使用Ajax技术获取新闻列表数据
		$.ajax({
			"url"		: "../util/news",
			"type"		: "GET",
			"data"		: "opr=list",
			"dataType"	: "json",
			"success"	: processNewsList
		});
	}
	function processNewsList(data) {//展示新闻列表
		var $newsList = $("#opt_area>ul");
		for (var i = 0; i < data.length;) {
			$newsList.append("<li>" + data[i].ntitle + "<span> 作者:"
				+ data[i].nauthor + " &#160;&#160;&#160;&#160; "
				+ "<a href='#'>修改</a> &#160;&#160;&#160;&#160; "
				+ "<a href='#' οnclick='return clickdel()'>删除</a>" 
				+ "</span></li>");
			if ((++i) % 5 == 0) {
				$newsList.append("<li class='space'></li>");
			}
		}
	}
	initNews();//执行新闻列表初始化工作
});

后台servlet代码:

java 复制代码
List<News> list = newsService.findAllNews();
News news = null;
StringBuffer newsJSON = new StringBuffer("[");
for (int i = 0;;) {
	news = list.get(i);
  newsJSON.append("{\"nid\":" + news.getNid() + ",");
  newsJSON.append("\"ntitle\":\""
      + news.getNtitle().replace("\"", "&quot;") + "\",");
  newsJSON.append("\"nauthor\":\""
      + news.getNauthor().replace("\"", "&quot;") + "\"}");
  if ((++i) == list.size()) {
      break;
  } else {
      newsJSON.append(",");
  }
}
newsJSON.append("]");
out.print(newsJSON);
out.flush();
out.close();

FastJSON

  • 随着JSON的广泛使用,在服务器端生成JSON字符串成了一件麻烦的工作,效率低且易出错
  • FastJSON:一个性能很好的、Java实现的JSON解析器和生成器
    • 将Java对象序列化成JSON字符串
    • 将JSON字符串反序列化得到Java对象
  • 官网:https://github.com/alibaba/fastjson/releases

入口类:com.alibaba.fastjson.JSON

方 法 说 明
public static String toJSONString ( Object object ) 将Java对象序列化成JSON字符串
public static String toJSONString (Object object, boolean prettyFormat ) prettyFormat为true时生成带格式的JSON字符串
public static String toJSONString ( Object object, SerializerFeature... features ) 可以通过参数features指定更多序列化规则
public static String toJSONStringWithDateFormat (Object object, String dateFormat, SerializerFeature... features ) 可以通过参数dateFormat指定日期类型的输出格式

枚举类型 SerializerFeature 定义了多种序列化属性

枚 举 值 说 明
QuoteFieldNames 为字段名加双引号,默认即使用
WriteMapNullValue 输出值为null的字段,默认不输出
WriteNullListAsEmpty 将值为null的List字段输出为[ ]
WriteNullStringAsEmpty 将值为null的String字段输出为""
WriteNullNumberAsZero 将值为null的数值字段输出为0
WriteNullBooleanAsFalse 将值为null的Boolean字段输出为false
SkipTransientField 忽略transient字段,默认即忽略
PrettyFormat 格式化JSON字符串,默认不格式化
java 复制代码
// 包含值为 null 的字段,数值为 null  输出0,String 为 null 输出""
String  strJSON = JSON.toJSONString ( javaObject,
                                     SerializerFeature.WriteMapNullValue,
                                     SerializerFeature.WriteNullNumberAsZero,
                                     SerializerFeature.WriteNullStringAsEmpty );

代码示例

java 复制代码
List<News> list = newsService.findAllNews();
String newsJSON = JSON.toJSONStringWithDateFormat(list,
out.print(newsJSON);
out.flush();
out.close();

基于表单数据的Ajax请求

  • 需要发送表单数据时,提取表单元素的值并构造成合适的数据格式是件很烦琐的事。
  • 使用jQuery提供的方法简化处理
    • .serializeArray()
    • $.param()

.serializeArray()

检测一组表单元素中的有效控件

  • 没有被禁用
  • 必须有name属性
  • 选中的checkbox或radio
  • 触发提交事件的submit按钮
  • file元素不会被序列化

将有效控件序列化为JSON对象数组

  • 包含name和value两个属性

$.param()

将由. serializeArray()生成的对象数组序列化成请求字符串的形式

jQuery还提供了.serialize()方法。.serialize()内部使用$.param()对.serializeArray()做了一个简单包装。不需要中间环节时,可以更简便地完成表单数据的序列化

代码示例

javascript 复制代码
jQuery(document).ready(function($) {
	function initNews() {//使用Ajax技术获取新闻列表数据
		$.getJSON("../util/news", "opr=list", processNewsList);
	}
	function processNewsList(data) {//展示新闻列表
		var $newsList = $("#opt_area>ul").empty();
		for (var i = 0; i < data.length;) {
			$newsList.append("<li>" + data[i].ntitle + "<span> 作者:"
					+ data[i].nauthor + " &#160;&#160;&#160;&#160; "
					+ "<a href='#'>修改</a> &#160;&#160;&#160;&#160; "
					+ "<a href='#' οnclick='return clickdel()'>删除</a>" 
					+ "</span></li>");
			if ((++i) % 5 == 0) {
				$newsList.append("<li class='space'></li>");
			}
		}
	}
	/*
	function initNews() {//使用Ajax技术获取新闻列表数据
		$("#opt_area>ul").load("../util/news", "opr=listHtml");
	}
	*/
	initNews();//执行新闻列表初始化工作
	function initTopics() {//使用Ajax技术获取主题列表数据
		$.getJSON("../util/topics", "opr=list", processTopicsList);
	}
	function processTopicsList(data) {//展示主题列表
		var $topicsList = $("#opt_area>ul").empty();
		for (var i = 0; i < data.length; ++i) {
			$topicsList.append("<li> &#160;&#160;&#160;&#160; "
					+ data[i].tname + " &#160;&#160;&#160;&#160; "
					+ "<a href='../newspages/topic_modify.jsp?tid="
					+ data[i].tid + "&tname=" + data[i].tname + "'>修改</a>"
					+ " &#160;&#160;&#160;&#160; <a href='../util/topics?opr=del&tid="
					+ data[i].tid + "'>删除</a> </li>");
		}
	}
	/*
	function initTopics() {//使用Ajax技术获取主题列表数据
		$("#opt_area>ul").load("../util/topics", "opr=listHtml");
	}
	*/
	var $leftLinks = $("#opt_list a"); // 获取页面左侧功能链接
	$leftLinks.eq(3).click(initTopics);
	$leftLinks.eq(1).click(initNews);
});
相关推荐
careybobo1 小时前
海康摄像头通过Web插件进行预览播放和控制
前端
TDengine (老段)2 小时前
TDengine 中的关联查询
大数据·javascript·网络·物联网·时序数据库·tdengine·iotdb
杉之3 小时前
常见前端GET请求以及对应的Spring后端接收接口写法
java·前端·后端·spring·vue
喝拿铁写前端3 小时前
字段聚类,到底有什么用?——从系统混乱到结构认知的第一步
前端
再学一点就睡3 小时前
大文件上传之切片上传以及开发全流程之前端篇
前端·javascript
木木黄木木4 小时前
html5炫酷图片悬停效果实现详解
前端·html·html5
请来次降维打击!!!5 小时前
优选算法系列(5.位运算)
java·前端·c++·算法
難釋懷5 小时前
JavaScript基础-移动端常见特效
开发语言·前端·javascript
还是鼠鼠5 小时前
Node.js全局生效的中间件
javascript·vscode·中间件·node.js·json·express
自动花钱机6 小时前
WebUI问题总结
前端·javascript·bootstrap·css3·html5