AJAX&JSON

原生js的AJAX应用

传统请求的缺点

我们以前的学习过程,浏览器对服务器发出的请求,都是传统的全局刷新的请求.
在这里插入图片描述
如果我们仅仅只需要更新页面中的某一小块的内容,我们传统的全局刷新的形式,其他的部分也会随着需要更新的这一小块内容,也刷新一次.
我们现在想要的效果是,哪一块需要更新,就刷哪一块,其他的部分保持不动.这种请求,为局部刷新的请求.在浏览器上体现就是做操作以后,刷新按钮没有动
我们现在急需局部刷新的请求方式,来有效的提升用户体验.

AJAX技术应用带来的好处

ajax是一项JavaScript扩展的技术,ajax代码写在js中.
ajax技术最重要的功能是能够发出局部刷新的请求到后台servlet,servlet处理完请求后,为ajax响应一个返回值.ajax拿到返回值后,处理前端的业务逻辑.

原生js的AJAX实现步骤和同步异步操作
<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<%
	String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort()
			+ request.getContextPath() + "/";
%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<base href="<%=basePath%>">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
<script type="text/javascript">
	function dj() {
		
		//1.创建核心对象
		/*
			创建ajax的核心对象xmlhttp
			以下所有的ajax功能的实现都是由该对象发起
		*/
		var xmlhttp;
		//浏览器支不支持创建形式
		if (window.XMLHttpRequest) {// code for IE7+, Firefox, Chrome, Opera, Safari
			xmlhttp = new XMLHttpRequest();
		} else {// code for IE6, IE5
			xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
		}
		
		
		//2.创建回调函数
		/*
			xmlhttp.onreadystatechange:
				创建ajax的回调函数,ajax的回调函数指的是,先执行后台servlet,再执行该函数体.
		*/
		xmlhttp.onreadystatechange = function() {
			/*
				if表示回调函数的执行条件
					xmlhttp.readyState:取得请求的状态码 码值为4 表示请求成功
					xmlhttp.status:取得响应的状态码 码值为200 表示响应成功
					回调函数的执行条件为,当请求成功并且响应成功的基础上,才执行该回调函数
			*/
			if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
				
				//xmlhttp.responseText接收后台servlet传递的返回值  
				//后台以响应流的形式传递的 out.print的内容就是ajax接收的返回值 
				var data = xmlhttp.responseText;
				//在回调函数体中实现业务逻辑
				document.getElementById("msg").innerHTML = data;
				
			}
		}
		
		
		//3.设置请求信息
		/*
			xmlhttp.open
				设置请求的基本信息
				参数1:设置请求方式 GET/POST
				参数2:设置请求路径
				参数3:设置 同步请求还是异步请求
					
					true:异步
						上面的ajax代码和下面的alert弹框彼此之间没有互相影响
						ajax的执行没有影响到alert的执行
						alert的执行也没有影响到上面ajax的执行
						全程为两根线程
						一根执行ajax程序
						一根执行alert弹框
						异步为ajax与其他的程序自己执行自己的,不互相影响
						
						
					false:同步
						只有在执行完上面ajax代码之后,才能够执行下面的alert弹框
						代码按照从上向下的顺序,依次执行.
						全程一根线程
						同步为ajax和其他程序,按照代码的顺序依次执行
						
					在实际项目开发中,我们一般情况下,默认使用的都是异步操作,能够有效的提升用户体验,比如在显示页面的时候,有一块内容读取额较慢,但不影响其他块的内容显示
					如果遇到特殊需求,我们也会使用到同步的技术,比如我们在验证表单时,有时需要只有填写的上一项内容通过,才能填写下一项内容
						
					
		
		*/
		xmlhttp.open("GET", "myServlet1.do?str1="+new Date().getTime(), false);
		
		//post请求传递参数 这一行代表必须加在open方法和send方法的中间
		//xmlhttp.setRequestHeader("Content-type","application/x-www-form-urlencoded"); 
		
		//4.发送请求
		//发送请求
		xmlhttp.send("str1=ccc&str2=ddd");
		
		//alert(123);
		
	}
</script>
</head>
<body>

	<button οnclick="dj()">点击</button>
	<br />
	<br />
	<div style="width: 200px; height: 200px; background-color: pink" id="msg">
	
	</div>
	
</body>
</html>
package com.jpg.servlet;

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

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class MyServlet1 extends HttpServlet{
	
	@Override
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		
		System.out.println("servlet1");
		
		String str1 = request.getParameter("str1");
		String str2 = request.getParameter("str2");
		
		/*try {
			Thread.sleep(3000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}*/
		
		/*
		 * 如果当前servlet接收的请求为传统的全局刷新的请求,那么响应流就是为浏览器做html代码的响应工作
		 * 如果当前servlet接收的请求为ajax发送的局部刷新的请求,那么响应流就是为ajax技术做返回值存在的 out.print中的内容,就是为ajax返回的值
		 * 
		 */
		PrintWriter out = response.getWriter();
		out.print(str1+";"+str2);
		out.close();
		
		
	}
	
	@Override
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		
		this.doGet(request, response);
		
	}
	
}
ajax以get请求方式传递参数

和传统的get请求传参数相同,在路径后面挂参数
xmlhttp.open(“GET”, "myServlet1.do?str1=aaa&str2=bbb, true);

ajax以post请求方式传递参数

在这里插入图片描述

使用ajax中避免浏览器缓存的方式

之所以走缓存,是因为浏览器认识了我们的请求路径,所以,想要避免缓存,让我们每一次的访问路径都不同,以挂参数的方式,但post不存在该问题,只针对get请求,因为post请求方式的路径的在地址栏不会显示
(1)随机数方式:
在这里插入图片描述
(2)时间戳方式:
在这里插入图片描述

JQuery支持的AJAX

$.ajax:最传统的基于jquery实现ajax的方式,这种方式最大的好处是使用方便,功能齐全.在实际项目开发中被普遍应用.(支持json)(用的其次)
$.get/$.post:这两种方式是基于以上$.ajax方式的简写形式,使用更加简单.在实际项目开发中使用的是最多的.但是由于应用比较简单,所以一些不常用的功能没有集成进来,所以,要有特殊需求的情况下,必须是在该方式的外部写额外的代码.(默认异步,想要修改,需要写额外的代码)(支持json)(用的最多)
$.getJSON:该方式除了能够有效的处理json数据之外,更重要的是能够读取json文件(用的不是很多)中的json内容.(用的较少)

$.ajax方式
$.ajax({
		//type:"post",	//请求方式   get/post  默认为get
		url : "myServlet2.do",	//请求路径 必要的
		async: true,	//表示同步或异步,true表示异步
		dataType : "text",	//从后台返回值的类型   text:普通文本(默认)    json:json格式的文本
		data : "str1=abc&str2=bcd",	//请求参数
		success : function(data) {	//回调函数     data:从后台接收的返回值
			
			$("#msg").html(data);
			
		}
});

上述的dataType,如果后台设置相应的类型为:response.setContentType(“text/json;charset=utf-8”);则dataType可省略

$.get方式和$.post方式
默认异步,若需修改,在get或post外面修改
这种形式顺序不能乱,第一位是请求的路径
第二位是请求的参数
第三位是回调函数
第四位是从后台的返回值的类型
如果没有请求参数,直接删除即可,这样,回调函数排在第二位
$.get(
	   "myServlet1.do", 
	    "username=zs&password=123", //以传统方式传参数
	    function(data) {
	    	$("#msg").html(data);
		},
		"text"
	);

JSON

语法

{“key1”:”value1”,”key2”:”value2”}
{key1:”value1”,key2:”value2”}
[{},{},{}] 集合
{“id”:”A0001”,”name”:”zs”,”age”:23}
key如果要加双引号,剩下的key都加,要不加,都不加

ajax以json格式传递参数
$.get(
	   "myServlet1.do", 
	    {"username":username,"password":password}, //以json格式传参数
	    function(data) {
	    	$("#msg").html(data);
		},
		"text"
	);
ajax以json格式接收返回值(json的拼接)

拼接的步骤:
(1).写json模板
(2).将json模板粘贴到空串中
(3).将双引号转义
(4).为?赋值
1.接收单个值
2.接收多个值

//传递多个值
//{"str1":"aaa","str2":bbb}
String str = "{\"str1\":\"aaa\",\"str2\":\"bbb\"}";

3.接收单个对象

//接受单个对象
//{"id":"?", "name":"?", "age":?}

String str = "{\"id\":\""+s.getId()+"\", \"name\":\""
+s.getName()+"\", \"age\":"+s.getAge()+"}";
$.post(
	"myServlet2.do",
	function(data) {
		alert(data.id);
	},
	"json"
)

4.接收多个对象

//接受多个对象
//{"id":"?", "name":"?", "age":?}
//{"s1":{"id":"?", "name":"?", "age":?}, "s2":{"id":"?", "name":"?", "age":?}}

String str = "{\"s1\":{\"id\":\""+s1.getId()+"\", \"name\":\""
+s1.getName()+"\", \"age\":"+s1.getAge()+"}, \"s2\":{\"id\":\""
+s2.getId()+"\", \"name\":\""+s2.getName()+"\", \"age\":"+s2.getAge()+"}}";
$.post(
		"myServlet3.do",
		function(data) {
			alert(data.s2.id);
		},
		"json"
	)

5.接收集合

public class MyServlet4 extends HttpServlet {
	
	@Override
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		PrintWriter out = response.getWriter();
		
		Student s1 = new Student("A0001", "zs", 23);
		Student s2 = new Student("A0002", "ls", 24);
		Student s3 = new Student("A0003", "ww", 25);
		Student s4 = new Student("A0004", "zl", 26);
		Student s5 = new Student("A0005", "sq", 27);
		
		List<Student> sList = new ArrayList<Student>();
		
		sList.add(s1);
		sList.add(s2);
		sList.add(s3);
		sList.add(s4);
		sList.add(s5);
		
		//接受集合
		//{"id":"?", "name":"?", "age":?}
		//{"sList":[{"id":"?", "name":"?", "age":?},{},{}]}
		
		//我们需要使用循环的形式来拼接
		StringBuffer buf = new StringBuffer();
		buf.append("{\"sList\":[");
		//使用普通for循环是因为我们需要使用到i,来拼接逗号
		for(int i = 0; i < sList.size(); i++) {
			Student s = sList.get(i);
			//因为大量的+拼接,相当于String拼接,所以需要分开来append
			//buf.append("{\"id\":\""+s.getId()+"\", \"name\":\""+s.getName()+"\", \"age\":"+s.getAge()+"}");
			buf.append("{\"id\":\"");
			buf.append(s.getId());
			buf.append("\", \"name\":\"");
			buf.append(s.getName());
			buf.append("\", \"age\":");
			buf.append(s.getAge());
			buf.append("}");
			if (i < sList.size() - 1) {
				buf.append(",");
			}
		}
		
		buf.append("]}");
		
		out.print(buf.toString());
		out.close();
	}
	
	@Override
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		this.doGet(request, response);
	}

}

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%
	String basePath = request.getScheme() + "://" + request.getServerName() + ":" + 	request.getServerPort() + request.getContextPath() + "/";
%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<base href="<%=basePath%>">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
<script type="text/javascript" src="jquery/jquery-1.11.1-min.js"></script>
<script type="text/javascript">
	$(function(){
		$("#djBtn").click(function(){
			//当每一次点击的时候,将原先展示的数据设置为空
			$("#tbody").html("");
			$.post(
				"myServlet4.do",
				function(data) {
					/*
						数据我们已经拿到了,我们以前的方式是拿到数据以后,将数据铺到table中,
						我们以前使用的el和jstl,因为是全局刷新的方式,现在我们是以AJAX局部
						刷新请求的方式拿到的数据,我们是使用的动态拼接table的方式,来将数据铺到table
					*/
					var i = 1;
					//$(data.sList)拿到了json数组,将其转换成jQuery对象
					$(data.sList).each(function(){
						//每一个json对象使用this表示
						$("#tbody").append("<tr><td>"+(i++)
								+"</td><td>"+this.id+"</td><td>"+this.name
								+"</td><td>"+this.age+"</td><td>删除||修改</td></tr>");
					})
				},
				"json"
			)
			
		});
	})
	
</script>
</head>
<body>
	<button id="djBtn">点击</button><br>
	<table border="1" align="center" width="70%" cellpadding="6px" cellspacing="0">
		<thead>
			<tr>
				<td>序号</td>
				<td>编号</td>
				<td>姓名</td>
				<td>年龄</td>
				<td>操作</td>
			</tr>
		</thead>
		
		<tbody id="tbody">
		
		</tbody>
	</table>

</body>
</html>
实战: 省市联动

需求:为点击的时候,两个下拉框中没有内容,当点击后,第一个下拉框显示省份,第二个框只要在选中省份后,才会显示对应的城市
在这里插入图片描述
省份表和城市表,一对多的关系,一个省份里面有多个城市,一个城市只能属于一个省份.
省份:一
城市:多
我们使用外键来描述表与表之间的关系
在谁的一方建立关系?(在哪张表中建立外键?)
永远是在多的一方建立关系(在多的一方建立外键)
省份表 tbl_province
id name
1 辽宁
2 吉林
3 黑龙江

城市表 tbl_city
id name pid
1 沈阳 1
2 大连 1
3 长春 2

如果外键换成pname可以吗?只记录下,该城市所属于的省份,这样不用多表联查,一张表搞定?也可以,但是存在缺点,第一:获取不到省份的其他信息,只能获取到省份名称,第二:数据得不到及时的更新,如果省份的名称发生了变化,那么城市表中的省份的字段的不到及时的更新,所以还是用pid作为外键合适
如果数据量过大,并且查询城市所属的省份很频繁,我们可以给城市表添加冗余字段pname,这样用一张表搞定,提高效率
关于建立外键有两种形式,一种是不直接建立外键,但是关系是外键关系,还有一种是真正的建立起外键(删除的麻烦),在实际项目开发中,一般采用第一种

$("#djBtn").click(function(){
			//当每一次点击的时候,将原先展示的数据设置为空
			$("#pid").html("<option value='-1'>-- 请选择 --</option>");
			$.post(
				"province/list.do",
				function(data) {
					
					$(data.pList).each(function(){
						$("#pid").append("<option value="+this.id+">"+this.name+"</option>")
					});
				},
				"json"
			)
			
		});
		
		//判断下拉框的值是否变化,是change事件
		$("#pid").change(function(){
			
			$("#cid").html("<option value='-1'>-- 请选择 --</option>");
			//选中option后会将option的value值赋值给select的value
			var pid = $("#pid").val();
			
			$.post(
					"city/list.do",
					"pid="+pid,
					function(data) {
						$(data.cList).each(function(){
							$("#cid").append("<option value="+this.id+">"+this.name+"</option>")
						});
					},
					"json"
				)
		});
转发形式向AJAX传返回值

如果是以request域+转发来向AJAX返回值,那么必须以json的形式来传数据,这样不会受到换行的影响,比如:

ajax请求传递:
$("#djBtn").click(function(){
	$.post(
		"myServlet1.do",
		function(data){
		//先弹出data,如果后台响应回的值等于aaa则弹出success
		//在该程序中,是使用request+转发来给ajax返回值,因为是以文本的形式传数据,
		//所以不会忽略换行的处理,最后返回的ajax的数据是两个换行+aaa,所以不会弹出success
		//在转发的目标
			alert(data);
			if(data=="aaa"){
				alert("success");
			}
		}
		
	)
})
servlet处理:
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		System.out.println("进入myServlet1"); 
		String str1 = "aaa";
		request.setAttribute("data",str1);
		//如果写成以下json传输数据的格式,则会忽略换行,在该例子中会弹出success
		//String str1 = "{\"str1\":\"aaa\"}";
		//request.setAttribute("data",str1);
		request.getRequestDispatcher("/data.jsp").forward(request, response);
	}
转发的指定页面
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
${data}
$.getJSON的使用

我们以前都是发送请求到后台,从后台取数据,这种方式直接从json文件中取数据
这种方式中,从后台的返回值类型不用写,就是json

//为点击按钮绑定事件
		$("#djBtn").click(function() {
			
			$.getJSON(
				"js/demo.json", 	//表示要读取的json文件的路径
				function(data) {
					alert(data.name);
				}
			)

		})

在这里插入图片描述

ajax的跨域操作

什么是跨域操作

对于我们的ajax操作,都是从后台去取ajax的返回值.
我们都是从我们自己的项目的后台去取返回值
以前的形式
在这里插入图片描述
如果将路径加全
在这里插入图片描述
以上的访问路径,说明发出的ajax请求,是从我们自己的服务器的项目中的后台去取数据.
根据以上访问路径,其中的协议 ip 端口号,这3个条件,改变其中一种,就是跨域操作.
跨域操作,就是从别人家取数据

跨域操作案例

天气预报,腾讯qq的天气采用的是中国天气网的数据

实际项目开发中跨域的应用

以前
util包
domain包
servlet包

以后
util项目
domain项目
servlet项目

只是举例,以后并不这样分层
将三个项目分别放到三个服务器,浏览器首先访问servlet服务器,因为servlet需要谁用到domain项目和util项目中的内容,只能通过跨域进行访问

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值