web技术 ----- AJAX介绍

本文深入探讨了AJAX的异步刷新技术,重点在于局部刷新的应用和实现步骤。讲解了XMLHttpRequest对象的创建、绑定事件、初始化、发送请求的过程,以及如何处理服务器返回的数据。同时,讨论了AJAX的优点和缺点,如局部刷新提高效率、无刷新获取数据,以及SEO和跨域问题。此外,还介绍了JSON在AJAX中的角色以及同步和异步的区别。通过实例展示了全局刷新和局部刷新的差异,并提供了原生AJAX的实现代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

AJAX

Javaweb — emmm……不知道是多少天了 happy 快四个月了


Ajax异步刷新技术


首先要了解AJAX的异步刷新技术,局部刷新,应用广泛,原生的AJAX步骤也是固定的,就创建、注册、初始化open,发送请求send

后面的框架其实就是简化目前的技术,mybatis封装jdbc的重复部分;JDK动态代理就是反射的高级应用;spring是用于创建对象的,之前是直接new Dao() ; springMVC则是对于servlet的改造,做之前servlet的事情

Ajax

ajax技术随处可见,比如百度搜索,搜索框下面的提示就是ajax技术,还有一个作用就是输入用户名之后,检测用户名是否可用也是ajax技术;还有就是鼠标放在一级分类上,就会显示二级分类;这也是ajax的局部刷新;还有就是头条新闻滚到底部就会刷新,也是Ajax

全局刷新和局部刷新

全局刷新: 整个浏览器被新的数据覆盖,再网络中传输大量的数据,浏览器需要加载,渲染页面

整个过程就是浏览器向服务器发送请求,然后loginServlet处理请求转发给jsp,数据写入响应体,然后响应给浏览器

局部刷新: 再浏览器的内部发送请求,获取数据,改变页面中的部分内容,其余页面无需加载和渲染,再网络中数据传输量少;效率高,体验感好;AJAX的核心就是局部刷新

局部刷新的重要的结构就是异步对象,这些异步对象能够与服务器进行通信

在这里插入图片描述

每一个异步对象都可以代替浏览器的行为发送请求获取数据

ajax引入 asynchronous JavaScript and Xml

AJAX全称为asynchronous JavaScript And XML,也就是异步的JavaScript和xml;通过AJAX可以再浏览器中向服务器发送异步的请求,最大的优势就是 : 无刷新获取数据;也就是不需要整个页面刷新,是一种局部刷新的技术;AJAX是一种现有的语言标准组合在一起的使用的新方式。 发送请求整个页面没有刷新【懒加载,节约资源】

  • JavaScript: 作用是负责创建异步对象,发送请求,更新dom对象
  • JSON[xml]: 网络中传输的数据的格式,用于ajax的数据传输;但是现在是使用JSON,但是ajax名字还是不变

Ajax作为一项新的技术,有着重要的作用,那就是异步刷新;所谓的同步和异步是有参照物的,比如clock的异步和同步就是clear_n和clock信号的触发规则;同步就是clear_n和clock使用门级电路关联,一起触发;异步就是两者的触发没有关联性;还有就是多线程中,不加锁就类似于异步,各线程之间没有关系,随意执行;但是加上同步锁之后,它们就有了关联,执行同一个对象,就会按照次序,强行产生的关联;一个执行,另外的只能等待

AJAX的优缺点

优点:

  • 可以无需刷新页面与服务器进行通信【局部刷新】
  • 允许根据用户的事件来更新部分页面的内容

缺点:

  • 没有浏览历史,不能回退【因为页面没有刷新】
  • 存在跨域问题【不允许两个应用的跳转】
  • SEO(搜索引擎优化不好)----- AJAX和JavaScript动态刷新的,所以整个响应体中没有,不能爬虫

关于HTTP协议就不再赘述,四部分即可

xml介绍

XML是extensive markup language ;可扩展标记语言 ---- 被设计用来传输和存储数据,xml和html类似,不同的是HTML都是预定义标签,都是要到浏览器之后才会使用;有特定的格式; 但是xml全都是自定义的标签,用来表示一些数据

<servlet>
	<servlet-name></servlet-name>
    <servlet-class></servlet-class>
</servlet>
<servlet-mapping>
	<servlet-name></servlet-name>
    <url-pattern></url-pattern>
</servlet-mapping>

但是再JavaScript和java之间转换数据使用的还是JSON,昨天已经演示过,因为java和JSON之间进行对象类型数据传输的时候普通的EL方式给的是地址,而不是具体的内容,需要拼JSON格式的字符串来当作一个对象【JSON是轻量级的】

异步请求对象

在局部刷新中,需要创建一个对象,代替浏览器发起请求的行为,这个对象存在内存中,代替浏览器发起请求并接收响应的数据,这个对象就是异步请求对象

全局更新是同步行为,局部更新是异步的行为【浏览器的数据没有完全更新】;这个异步对象用于在后台和服务器交换数据,这个异步对象就是XMLHttpRequest

这个异步对象可以在不重新加载页面的情况下更新网页,在页面已加载后向服务器发送请求并接收数据;所有的浏览器都内建了XMLHttpRequest对象;通过简单的JS代码就可以创建异步对象

var  xmlhttp = new XMLHttpRequest();       //core

这个异步对象一般存在浏览器的内存中

AJAX异步的实现步骤 readystatechange

1.创建异步对象

在JavaScript中使用new XMLHttpRequest()创建异步对象

2.给异步对象绑定事件onreadstatechange

每当readstate改变的时候,就会触发这个readystatechange事件,给事件指定一个处理函数func1,通过判断XMLHttpRequest对象的状态,读取服务端返回的数据,异步对象关联这个事件的属性就是readyState

readyState属性【状态变化】

存有XMLHttpRequest的状态,从0到4发生变化

  • 0 : 请求未初始化, 创建异步请求对象 var xmlHttp = new XMLHttpRequest();
  • 1: 初始化异步对象, xmlHttp.open(请求方式,请求地址,true);
  • 2: 异步对象发送请求 xmlHttp.send();
  • 3:异步对象接收应答数据 从服务端返回数据,XMLHttpRequest内部处理
  • 4: 异步请求对象已经将数据解析完毕, 此时才能读取数据

简言之,0就是new 对象;1就是初始化,open方法指定地址和方式;2就是发送请求send;3就是服务器获取了数据—内部使用原始;4表示异步对象解析完毕了【3一般不使用,4是最常用的】 4状态开发人员拿到数据更新当前的页面 ---- 局部刷新刷新的是数据,更新页面

status属性【网络状况】

异步对象还有一个重要的属性就是status(状况),这个属性可以用来表示网络的状况,比如200,404,500;200表示成功,404表示前台出错,500表示服务端代码出错

所以要200的时候才能表示网络的请求是成功的

xmlHttp.onreadstatechange = function(){
	//处理的方案
    if(xmlHttp.readyState == 4 && xmlHttp.status == 200){//200表示请求成功
        //拿到了解析后的数据,更新页面
        var data = xmlHttp.responseText;
        document.getElementById("name").value = data; //这样就成功更新了数据
    }
}

3.初始化异步请求对象 open

异步的方法是open

xmlHttp.open(请求方式GET或者POST,服务器访问的地址,异步或者同步) 异步就是选择true

//比如
xmlHttp.open("get","loginServlet?name=zhangsan&pwd=1234",true);

4.使用异步对象发送请求

直接使用异步对象的方法即可 xmlhttp.sendO; 这个请求就可以发送请求给服务器

获取服务端返回的数据

获取数据还是使用异步对象的属性responseText

xmlhttp.responseText
xmlHttp.onreadstatechange = function(){
	//处理的方案
    if(xmlHttp.readyState == 4 && xmlHttp.status == 200){//200表示请求成功
        //拿到了解析后的数据,更新页面
        var data = xmlHttp.responseText;
        document.getElementById("name").value = data; //这样就成功更新了数据
    }
}

回调: 当请求状态发生变化时,会自动调用这个函数;所以programmer只是编写者,不是调用者

ajax使用的实例

ajax使用的步骤就是4步,创建对象,绑定事件,初始化,发送请求;

这里写一个例子,就是计算bmi;浏览器给出身高体重得到bmi,给出用户反馈;这里首先不使用ajax;先使用全局刷新

全局刷新

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>AJAXdemo</title>
</head>
<body>
	<form action="bmiServlet" method="post">
		姓名   : <input type="text" name="user"/><br>
		身高m  : <input type="text" name = "height"/><br>
		体重kg : <input type="text" name ="weight"/><br>
		<input type="submit" value="提交"/>
	</form>
</body>
</html>

然后一个简单的服务端控制层的servlet

package cfeng.controller;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;


@WebServlet("/bmiServlet")
public class bmiServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;

	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		request.setCharacterEncoding("UTF-8");
		//接收请求参数
		String user = request.getParameter("user");
		String height = request.getParameter("height");
		String weight = request.getParameter("weight");
		
		//调用业务层的代码,本来要封装到service层中,这里过于简单就在控制层处理了
		//计算bmi
		float h = Float.valueOf(height);
		float w = Float.valueOf(weight);
		float bmi = w/(h*h);
		//判断bmi范围
		String msg = "";
		if(bmi <= 18.5) {
			msg = "你比较瘦";
		}else if(bmi > 18.5 && bmi <= 23.9) {
			msg = "你的bmi是正常的";
		}else if(bmi > 24 && bmi <= 27) {
			msg = "你比较胖";
		}else {
			msg = "你非常胖";
		}
		msg = "你好," + user + "先生/女士 : " +"你的bmi是-->" + bmi + " 因此," + msg;
		
		//将处理结果放到作用域中,转发给view层显示
		request.setAttribute("msg", msg);
		request.getRequestDispatcher("/result.jsp").forward(request, response);
	}

}

最后一个简单的view层的jsp页面

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>结果页面</title>
</head>
<body>
	<p>显示bmi结果</p>
	<h3> ${msg} </h3>  <!-- 简化版的el表达式 -->
</body>
</html>

上面就是一个标准的全局刷新的写法,现在可以试一下,不用jsp,直接使用response【这也是属于view层】这里地址栏显示的就是servlet的地址,因为请求转发是最开始的路径,尽管这里后面输出流才开放;重定向才是后面的地址

使用response来输出【应答对象】— 最开始的写法

package cfeng.controller;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;


@WebServlet("/bmiServlet")
public class bmiServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;

	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		request.setCharacterEncoding("UTF-8");
		//接收请求参数
		String user = request.getParameter("user");
		String height = request.getParameter("height");
		String weight = request.getParameter("weight");
		
		//调用业务层的代码,本来要封装到service层中,这里过于简单就在控制层处理了
		//计算bmi
		float h = Float.valueOf(height);
		float w = Float.valueOf(weight);
		float bmi = w/(h*h);
		//判断bmi范围
		String msg = "";
		if(bmi <= 18.5) {
			msg = "你比较瘦";
		}else if(bmi > 18.5 && bmi <= 23.9) {
			msg = "你的bmi是正常的";
		}else if(bmi > 24 && bmi <= 27) {
			msg = "你比较胖";
		}else {
			msg = "你非常胖";
		}
		msg = "你好," + user + "先生/女士 : " +"你的bmi是-->" + bmi + " 因此," + msg;
		
		//将处理结果放到作用域中,转发给view层显示
//		request.setAttribute("msg", msg);
//		request.getRequestDispatcher("/result.jsp").forward(request, response);
		response.setContentType("text/html;charset=utf-8");
		PrintWriter out = response.getWriter();  //IO流标准,开启输出,刷新,关闭
		out.println(msg);
		//清空缓存
		out.flush(); //立刻显示
		//关闭流
		out.close();
	}
}

这样也是正常输出的,返回的是就是字符串,这里就是全局刷新,整个页面都会发生变化

因为是表单发送的数据,服务端响应就会刷新整个页面

因为是表单发送的请求,没有异步对象,就是整个页面,因此响应体的数据就是返回给整个页面,显示到页面上,但是如果是异步对象发送的请求,那么返回的数据就交给ajax异步对象,而不是响应到页面

局部刷新

这里的实现的思路是

//readme.txt

1.新建jsp,使用XMLHttpRequest异步对象
  创建对象,绑定事件,初始化open,发送请求send
  
2.创建服务器的servlet,接收并处理数据,把数据输出给【异步对象】

首先写一个index页面

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title>AJAXdemo</title>
		<script type="text/javascript">
			doAJAX = function() {
				//获取用户输入的所有的数据
				var name = document.getElementById("name").value;
				var h = document.getElementById("h").value;
				var w = document.getElementById("w").value;
				
				var xmlhttp = new XMLHttpRequest();
				//绑定事件
				xmlhttp.onreadystatechange = function() {
					//刷新页面
					if(xmlhttp.readyState == 4 && xmlhttp.status == 200) {
						//alert(xmlhttp.responseText);   调试发现路径错误
						var data = xmlhttp.responseText;
						alert(data);
						document.getElementById("result").innerText = data;
					}
				}
				
				var uri = "/AjaxTest/bmi?user=" + name +"&weight="+ w + "&height="+h;
				//初始化
				xmlhttp.open("get",uri,true);
				//发送请求
				xmlhttp.send();
			}
		</script>
	</head>
	<body>
		姓名   : <input id="name" type="text"/><br>
		身高m  : <input id="h" type="text" /><br>
		体重kg : <input  id="w" type="text"/><br>
		<input type="button" value="计算bmi" onclick="doAJAX()"/>
		<br><br><br>
		<span id="result">等待加载数据……</span>
	</body>
</html>

这里和上面的全局刷新的主要区别就是没有使用表单,因为ajax不使用表单提交请求;所以按钮不需要name

<script type="text/javascript">
		var xmlhttp = new XMLHttpRequest();
		//绑定事件
		xmlhttp.onreadystatechange = function() {
			//刷新页面
			}
		//初始化
		xmlhttp.open("POST","/bmiServlet",true);
		//发送请求
		xmlhttp.send();
</script>

这里就是一段js脚本,用来创建一个异步对象;每一个异步对象都能够发送请求;当点击按钮之后触发事件就会进行创建xmlhttp异步对象

在绑定的事件中使用alert调试,发现state从1变化到4;和设想的情况是相同的;xhr就是异步请求的简称;这里0是不可见的,4就表示数据返回并解析成功了

servlet将数据写入响应体中,异步对象就能够取出数据然后使用

这里的局部对象就相当于在下面的按钮中,只有按钮中的异步对象会发送请求和接收数据,页面的其他的部分不会发生变化,不受影响

这个过程中,出现了一点小错误,使用F12的网络调试才发现问题,404有部分是路径问题,这里的js是前台路径,所以要加上项目名称

这里我们将数据写入div中【火狐的老版浏览器不支持innerText,在新版的EDGE上面一下子就好了】哎

java代码还是和之前的响应输出的代码相同

这样就两个文件,一个java,一个jsp就实现了原生的ajax的异步刷新,当我们点击按钮的时候获得数据,但是页面没有刷新,和之前的刷新不同

也就是说,原生的ajax就是在JavaScript脚本中,后台的控制层代码直接将响应数据直接使用输出流输出给ajax异步对象,然后ajax的异步对象XMLHttpRequest的responseText属性会接收记录输出的数据

ajax原生编程就是和JDBC一样是固定的,相应的事件触发,创建ajax异步对象,注册事件,初始化open,发送请求send;  事件中的条件是xhr.readyState == 4 && xhr.status == 200

JSON格式的ajax

上面返回的就是一个普通的文本,那么如果要返回多个数据该如何做,昨天已经分享演示了将JSON格式的字符串传给JavaScript,JavaScript变量直接通过el表达式接收,那么对于异步对象来说;

java中的对象和JavaScript中不相通;JavaScript中的对象是JSON格式的,而java中对象传输的是地址,这个地址只有java中的变量才能找到,而JavaScript中的变量是找不到的,所以对象类型的数据就要使用JSON格式传递给JavaScript,或者想一次性传输多个数据也要使用JSON

java的控制层传送的是JSON格式的字符串,而不是JSON对象,在JavaScript中有两种形式可以获得JSON对象

JSON字符串转JSON对象

  • 使用EL表达式,直接取出域中的数据输出给JavaScript中的响应体
  • 使用eval方法,注意如果是data = “{……}”, 那么转化是一定要加上括号; 也就是 var obj = eval("(" + data + “)”);
//第一种方式适用于 普通的 全局刷新;因为EL表达式直接转换需要使用域,在JS中可以直接使用EL表达式转化未JSON对象赋值给变量   --- 主要是共享域

//第二种方式适用于AJAX,因为这里是直接获得响应的JSON字符串,所以原生的就使用eval函数来当作js代码执行
var data = "{'name':'zhangsan','stuclass':'HC2001'}";
var stu = eval("(" + data + ")");

同步和异步

open函数中第三个参数就是boolean类型的,true代表异步,false代表同步,同步和异步的区别

  • 异步: 使用异步对象发出请求后,不用等待数据处理结果,就可以执行其他的操作;也就是相对于整个界面的代码【整个界面】来说就是异步的 比如send函数执行,不会等待servlet的请求响应之后才执行下面的代码;而是先执行下面的代码; 当响应之后才会做出其他的操作 类似于多线程,可以创建多个异步对象,它们之间的执行没有顺序,都是响应之后才会执行
  • 同步: 就是和界面的代码执行的顺序一致,在任意时刻只能执行一个请求,所以多个异步对象只能依次序执行,类似于加上了关于连接的同步锁;必须等send()执行完之后,才能执行下面的代码

同步就效率非常低下,线程问题也是如此,所以要减少使用synchronized

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值