Web基础之开启AJAX的学习之旅

Web基础之开启AJAX的学习之旅

一、AJAX简介
AJAX即“Asynchronous Javascript And XML”(异步JavaScript和XML),是指一种创建交互式网页应用的网页开发技术。
通过在浏览器后台与服务器进行少量数据交换,AJAX 可以使网页实现异步更新。这意味着可以在不重新加载整个网页的情况下,对网页的某部分进行更新。
传统的网页(不使用 AJAX)如果需要更新内容,必须重载整个网页页面。
AJAX 中使用的 Web 标准已被良好定义,并被所有的主流浏览器支持。AJAX 应用程序独立于浏览器和平台。

二、AJAX的技术核心
AJAX的技术核心是 XMLHttpRequest 对象(JavaScript对象)。

三、AJAX请求过程
创建 XMLHttpRequest 对象 -> 连接服务器 -> 发送请求 -> 接收响应数据

四、响应数据的类型
响应数据的类型一般为: XML 或者 JSON。XML 和 JSON 都是平台(操作系统)和语言(编程语言)无关的。

五、JSON简介
5.1什么是JSON?
JSON 即 JavaScript Object Notation, 是一种轻量级的数据交换格式。 JSON采用完全独立于语言的文本格式。
参考资料: http://www.json.org/

5.2JSON 语法规则
JSON 语法是 JavaScript 对象表示语法的子集。
数据在键值对中
数据由逗号分隔
花括号保存对象
方括号保存数组

5.3JSON 名称/值对
JSON 数据的书写格式是:名称/值对。
名称/值对组合中的名称写在前面(在双引号中),值对写在后面(同样在双引号中),中间用冒号隔开:
例如:"firstName":"John"  等价于 JavaScript语句:var firstName="John"

5.4JSON 值
JSON 值可以是:
数字(整数或浮点数)
字符串(在双引号中)
逻辑值(true 或 false)
数组(在方括号中)
对象(在花括号中)
null

5.5基础结构
一般来说,JSON结构有两种:对象和数组(可以类比JS中的对象和数组来理解)。

1、对象:对象在js中表示为“{}”括起来的内容,数据结构为 {key:value,key:value,...}的键值对的结构,在面向对象的语言中,key为对象的属性,value为对应的属性值,所以很容易理解,取值方法为 对象.key 获取属性值,这个属性值的类型可以是 数字、字符串、数组、对象几种。

2、数组:数组在js中是中括号“[]”括起来的内容,数据结构为 ["java","javascript","vb",...],取值方式和所有语言中一样,使用索引获取,字段值的类型可以是 数字、字符串、数组、对象几种。

3. Object 和 Array 中Value 可取的类型:经过对象、数组2种结构就可以组合成复杂的数据结构了。

六、JSON 与 JS 对象的互转
JSON.parse(data);

七、过程详解
7.1 创建
7.1.1、 IE7及其以上版本中支持原生的 XHR 对象(其他主流浏览器都支持),因此可以直接用: var oAjax = new XMLHttpRequest();
7.1.2 、IE6及其之前的版本中,XHR对象是通过MSXML库中的一个ActiveX对象实现的,可以直接使用下面的语句创建: var oAjax=new ActiveXObject(’Microsoft.XMLHTTP’);

7.2 连接和发送
7.2.1、 open()函数的三个参数:请求方式、请求地址、是否异步请求(同步请求的情况极少,至今还没用到过);
7.2.2、GET 请求方式是通过URL参数将数据提交到服务器的,POST则是通过将数据作为 send 的参数提交到服务器;
7.2.3、POST 请求中,在发送数据之前,要设置表单提交的内容类型;
7.2.4、提交到服务器的参数必须经过 encodeURIComponent() 方法进行编码,实际上在参数列表”key=value”的形式中,key 和 value 都需要进行编码,因为可能会包含特殊字符。每次请求的时候都会在参数列表中拼入一个 “v=xx” 的字符串,这样是为了拒绝缓存,每次都直接请求到服务器上。

7.3 接收服务器响应
7.3.1、 接收到响应后,响应的数据会自动填充XHR对象,相关属性如下:
responseText:响应返回的主体内容,为字符串类型;
responseXML:如果响应的内容类型是 "text/xml" 或 "application/xml",这个属性中将保存着相应的xml 数据,是 XML 对应的 document 类型;
status:响应的HTTP状态码;
statusText:HTTP状态的说明;

7.3.2、XHR对象的readyState属性表示请求/响应过程的当前活动阶段,这个属性的值如下:
0-未初始化,尚未调用open()方法;
1-启动,调用了open()方法,未调用send()方法;
2-发送,已经调用了send()方法,未接收到响应;
3-接收,已经接收到部分响应数据;
4-完成,已经接收到全部响应数据;

只要 readyState 的值变化,就会调用 readystatechange 事件,(其实为了逻辑上通顺,可以把readystatechange放到send之后,因为send时请求服务器,会进行网络通信,需要时间,在send之后指定readystatechange事件处理程序也是可以的,我一般都是这样用,但为了规范和跨浏览器兼容性,还是在open之前进行指定吧)。

7.3.3、在readystatechange事件中,先判断响应是否接收完成,然后判断服务器是否成功处理请求,xhr.status 是状态码,状态码以2开头的都是成功,304表示从缓存中获取,上面的代码在每次请求的时候都加入了随机数,所以不会从缓存中取值,故该状态不需判断。

7.3.4、AJAX请求是不能跨域的!


八、实例

 验证码的验证:在输入框中输入后面图片中的验证码;失去焦点的时候,发起AJAX请求,验证验证码是否填写正确;

项目整体框架:





Servlet代码:
图片验证码Servlet:

package com.usc.servlet;

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Random;

import javax.imageio.ImageIO;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;


public class MyValidateCodeServlet extends HttpServlet{

	private static final long serialVersionUID = 1L;
	
	private static final char[] DICTIONARY={ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd',
        'e', 'f', 'g', 'h', 'i', 'g', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A',
        'B', 'C', 'D', 'E', 'F', 'G', 'H', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y',
        'Z'};
//	验证码图片的宽度
	private int width=100;
//	验证码图片高度
	private int height=50;
//	验证码字符长度
	private int length =4;
	
	private int count =15;
	
	private double factor =0.6;
	
//	随机产生器
	private Random r = new Random();
	
	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		this.doPost(req, resp);
	}
	
	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
//		从字典字符中随机产生4个验证码字符
		req.setCharacterEncoding("UTF-8");
		StringBuilder sb = new StringBuilder();
		
		for(int i=0;i<length;i++){
			char code=(char) DICTIONARY[r.nextInt(DICTIONARY.length)];
			sb.append(code);
		}
		
		String validateCode =sb.toString();
		req.getSession().setAttribute("code", validateCode);
		
//		创建图片
		BufferedImage bufimg = new BufferedImage(width, height,BufferedImage.TYPE_INT_RGB);
		Graphics g =bufimg.getGraphics();
		g.setColor(getRandomColor(220, 255));
		g.fillRect(0, 0, width, height);
		
//		绘制干扰线
		int x1,y1,x2,y2;
		for (int i = 0; i < count; i++) {
			x1=r.nextInt(width);
			y1=r.nextInt(height);
			x2=r.nextInt(width-x1);
			y2=r.nextInt(height-y1);
			g.setColor(getRandomColor(100, 255));
			g.drawLine(x1, y1, x1+x2, y1+y2);
		}
//		画验证码
		int size=(int)(height*factor);
		g.setFont(new Font("微软雅黑", Font.PLAIN, size));
		for (int i = 0; i < validateCode.length(); i++) {
			g.setColor(Color.red);
			g.drawString(String.valueOf(validateCode.charAt(i)), i*20, 35);
		}
		
//		写响应
		resp.setHeader("Pragma", "No-cache");
		resp.setHeader("Cache-Control", "no-cache");
        resp.setDateHeader("Expires", 0);
//        设置mimeType
        String mimeType =req.getServletContext().getMimeType(".jpg");
        resp.setContentType(mimeType);
        // 4.3 输出响应
        OutputStream out = resp.getOutputStream();
        ImageIO.write(bufimg, "JPEG", out);
        g.dispose();
        
	}
	
	private Color getRandomColor(int low ,int height){
		int sub=height-low;
		int r1=low+r.nextInt(sub);
		int g=low +r.nextInt(sub);
		int b=low +r.nextInt(sub);
		return new Color(r1, g, b);
	}
}

验证码验证Servlet

package com.usc.servlet;

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;

import javax.imageio.ImageIO;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;


public class CheckValidateCodeServlet extends HttpServlet{

	private static final long serialVersionUID = 1L;
	
	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		this.doPost(req, resp);
	}
	
	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
//		设置编码
		req.setCharacterEncoding("UTF-8");
		String code=req.getParameter("code");
		Map <String,Object> msg = new HashMap<String,Object>();
		String codeStr=(String)req.getSession().getAttribute("code");
		if(code==null || "".equals(code.trim())){
			msg.put("respcode", -1);
			msg.put("desc", "\"验证码未填写!\"");
		}
		else if(codeStr==null){
			msg.put("respcode", 2);
			msg.put("desc", "\"验证码过期!\"");
		}
		else if(code.equalsIgnoreCase(codeStr)){
				msg.put("respcode", 1);
				msg.put("desc", "\"正确!\"");
			}
		else{
				msg.put("respcode", -1);
				msg.put("desc", "\"验证码错误!\"");
			}
		StringBuilder jsonsb = new StringBuilder();
		jsonsb.append("{\"respcode\""+":"+"\""+msg.get("respcode")+"\"").append(",")
		.append("\"desc\""+":"+msg.get("desc"))
		.append("}");
		
		String respdata=jsonsb.toString();
		String jsonmimeType=req.getServletContext().getMimeType(".json");
		resp.setContentType(jsonmimeType+";charset=UTF-8;");
		resp.getWriter().write(respdata);
	}
}


JS代码:

function ajax(options){
	
	options=options || {};
	//请求类型
	var type = (options.type || "GET").toUpperCase();
	//请求数据类型
	var dataType =options.dataType || "json";
	//请求参数转换
	var params =formateParams(options.data);
	
	//创建XMLHttpRequest对象
	var xmlreq={};
	//如果浏览器支持
	if(window.XMLHttpRequest){
		xmlreq=new XMLHttpRequest();
	}else{
		//如果浏览器不支持
		xmlreq=new ActiveXObject('Microsoft.XMLHTTP');
	}
	
	//判断类型
	if(type=="GET"){
		//如果是GET请求
		xmlreq.open("GET",options.url+"?"+params,true);
		xmlreq.send(null);
	}else{
		//如果是POST请求
		xmlreq.open("POST", options.url,true);
		xmlreq.setRequestHeader("Content-Type", "application/x-www-form-urlencode");
		xmlreq.send(params);
	}
	
	//状态监测
	xmlreq.onreadystatechange=function(){
		//已经准备就绪
		if(xmlreq.readyState==4){
			var status =xmlreq.status;
			//请求成功
			if(status==200){
//				var info=xmlreq.responseText;
				if(options.success){
					if(dataType=="json"){
						options.success(xmlreq.responseText);
					}else{
						options.success(xmlreq.responseXML);
					}
				}
			}
			//请求失败
			else{
				options.fails && options.fails(xmlreq.responseXML);
			}
		}
	}
}

//GET请求参数正确转换
function formateParams(data){
	var arr=[];
	for(var name in data){
		arr.push(encodeURIComponent(name)+"="+encodeURIComponent(data[name]));
	}
	arr.push("t="+(new Date()).valueOf());
	var dataOp=arr.join("&");
	return dataOp;
}

login.jsp代码:

<%@page import="java.util.Date"%>
<%@ 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>
<%
	String basePath=request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+request.getContextPath();
	request.setAttribute("basePath", basePath);
%>
<script type="text/javascript" src="${basePath}/js/ajax.js"></script>
<script type="text/javascript">
	function changeImage(){
		var img =document.getElementById("img");
			//为了不缓存后面加了一个时间参数
		img.src="${basePath}/validateCode?t="+(new Date()).valueOf();
	}
	
	function checkCode(){
		var code =document.getElementById("code").value;
		if(!code){
			return ;
		}else{
			//发起AJAX请求
			ajax({
				type:"GET",
				dataType:"json",
				data:{code:code},
				url:"${basePath}/checkValidateCode",
				success:function(data){
					//JSON对象转为JS对象 
					var msg=JSON.parse(data);
					var spanObj=document.getElementById("showspan");
					if(msg.respcode!=2){
						spanObj.innerHTML=msg.desc;
					}else{
						spanObj.innerHTML="正确";
					}
					spanObj.style.display="inline";
				},
				fails:function(status){
					console.log(status);
				}
			});
		}
	}
</script>
</head>
<body>
<!-- 验证码失去焦点时 发起AJAX请求 验证验证码是否正确 -->
验证码:<input id="code"  type="text" οnblur="checkCode()">
<span id="showspan" style="color: red;"></span>
<!-- 点击图片或者看不清楚连接时 重新发起请求 刷新整个页面 -->
<img id="img" alt="验证码" src="${basePath}/validateCode" οnclick="changeImage()">
<a  href="javascript:changeImage();">看不清楚换一张</a>
</body>
</html>


web.xml配置文件

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">
  <display-name>MyAjax</display-name>
  <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>
  
  <servlet>
  <servlet-name>validateCode</servlet-name>
  <servlet-class>com.usc.servlet.MyValidateCodeServlet</servlet-class>
  </servlet>
  <servlet-mapping>
  <servlet-name>validateCode</servlet-name>
  <url-pattern>/validateCode</url-pattern>
  </servlet-mapping>
  
  
  <servlet>
  <servlet-name>checkvalidateCode</servlet-name>
  <servlet-class>com.usc.servlet.CheckValidateCodeServlet</servlet-class>
  </servlet>
  <servlet-mapping>
  <servlet-name>checkvalidateCode</servlet-name>
  <url-pattern>/checkValidateCode</url-pattern>
  </servlet-mapping>
</web-app>


九、项目运行效果:



验证码填写正确:



验证码填写失败:




十、总结
了解了什么是AJAX;AJAX的是一种轻量级的数据交换方式;不要刷新整个页面;
如何发起AJAX请求;首先我们需要创建XMLHttpRequest对象实例;通过该对象实例的方法发起AJAX请求;同时需要注意的是请求参数以及回传数据格式;
了解了JSON这种数据类型;
最后,我们通过一个实例,来实战演练AJAX的用法;
学无止境!共勉!


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值