原生与封装Ajax

Ajax

一.Ajax概述

1.应用场景

  • 在线视频、直播平台等...评论实时更新、点赞、小礼物、...
  • 会员注册时的信息验证,手机号、账号唯一
  • 百度关键搜索补全功能

2.简介

  • Ajax 即"Asynchronous Javascript And XML"(异步 JavaScript 和 XML),是指一种创建交互式网页应用的网页开发技术
  • Ajax 是一种用于创建快速动态网页的技术
  • Ajax 是一种在无需重新加载整个网页的情况下,能够更新部分网页的技术
  • 通过在后台与服务器进行少量数据交换,Ajax 可以使网页实现异步更新。这意味着可以在不重新加载整个网页的情况下,对网页的某部分进行更新。
  • 传统的网页(不使用 Ajax)如果需要更新内容,必须重载整个网页页面

3.特点

  • 局部刷新
  • 异步交互

4.异步与同步方式区别

(1)同步方式发送请求

  • 发送一个请求,需要等待响应返回,然后才能够发送下一个请求,如果该请求没有响应,不能发送下一个请求,客户端会处于一直等待过程中

(2)异步方式发送请求

  • 发送一个请求,不需要等待响应返回,随时可以再发送下一个请求,即不需要等待

二.JS原生方式实现异步

1.实现步骤

jsp 复制代码
1、创建XMLHttpRequest对象
var xhr = new XMLHttpRequest();
2、使用open方法指定请求的相关信息
xhr.open("get/post","***Servlet",true);
3、使用send方法发送请求
xhr.send();
4、定义onreadystatechange的函数
xhr.onreadystatechange = function(){}
5、当readystate属性值为4时
xhr.readyState == 4;
6、获取响应信息
var msg = xhr.responseText;
7、处理信息 

2.案例

  • 视频点赞

(1)video.jsp

jsp 复制代码
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
<script>
   function like() {
       var xhr = new XMLHttpRequest();
       xhr.open("get","likeServlet",true);
       xhr.send();
       xhr.onreadystatechange = function(){
           if (xhr.readyState == 4) {
               var msg = xhr.responseText;
               document.getElementById("num").innerText = msg;
           }
       }
   }
</script>
</head>
<body>
<video src="test.mp4" controls width="500"></video><br>
<input type="button" value="点赞" οnclick="like()">
当前点赞量:<span style="color: red;" id="num">${empty applicationScope.count ? 0 : applicationScope.count}</span>
</body>
</html>

(2)likeServlet.java

java 复制代码
package com.lfg.servlet;

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

@WebServlet("/likeServlet")
public class LikeServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
   //获取原本的点赞量+1,将新的点赞量放回去
   ServletContext servletContext = getServletContext();
   Integer count = (Integer) servletContext.getAttribute("count");
   //如果当前点赞是第一个点赞
   if (count == null) {
       count = 1;
   } else {
       count++;
   }
   servletContext.setAttribute("count",count);
   //将最新的点赞量还给Ajax
   PrintWriter out = resp.getWriter();
   out.print(count);
   out.close();
}
}

三.jQuery方式实现异步

1.概述

  • jQuery是一个优秀的js框架,自然对JS原生的Ajax进行了封装,封装后的Ajax的操作方法更简洁,功能更强大,这也是程序员最普遍使用,语法结构简单,代码可读性好。

2.Ajax操作相关的jQuery方法

请求方式 语法
Ajax请求 $.ajax([settings])
GET请求 $.get(url, [data] , [callback] , [type])
POST请求 $.post(url, [data] , [callback] , [type])

(1)Ajax请求

a.语法
Javascript 复制代码
$.ajax({
	url:"",
	data:{},
	type:"post/get",
	async:true,
	dataType:"text",
	success:function(obj){

	},
	error:function(){

	}
})
b.属性解析
参数名称 描述
url 请求的服务器端url地址, 与form表单中的action一样,都是代表请求的路径
data 前台需要向后台传递的数据(键值对形式)
type 和form表单中method对应,代表请求类型 get/post
async 取值是布尔类型true/false,分别表示异步和同步,默认为true(异步),一般不建议写
dataType 回传的数据类型。text、xml、html、json...
success 成功的回调函数,参数obj表示返回值
error 失败的回调函数,一般不写
c.注意事项
  • 每个属性后都要跟随一个英文逗号,最后一个不用。
  • 每一个属性都是键值对的形式存在,中间用英文冒号:隔开
  • data:{} 是一个特殊的写法,值是一个{},里面使用键值对存储
    • 例如:data:{"键1":值1, "键2":值2, "键3":值3}
  • 引入jQuery
d.示例
javascript 复制代码
        $(function () {
            $("#btn").click(function () {
                $.ajax({
                    url:"likeServlet",
                    data:null,
                    type:"get",
                    async:true,
                    dataType:"text",
                    success:function (obj) {
                        $("#num").text(obj);
                    },
                    error:function () {
                        alert("测试");
                    }
                });
            });
        });

(2)GET请求

a.语法格式
javascript 复制代码
$.get(url, [data], [callback], [type]);
b.属性解析
参数名称 描述
url 请求的服务器端url地址, 与form表单中的action一样,都是代表请求的路径
data 前台需要向后台传递的数据(键值对形式)
callback 当请求成功后的回掉函数,可以在函数体中编写我们的逻辑代码
type 预期的返回数据的类型,取值可以是 text、xml、html、json...
c.注意事项
  • 写法功能和$.ajax是一样的,但是严格要求属性顺序。
  • 引入jQuery
d.示例
Javascript 复制代码
	$.get("likeServlet",null,function (obj) {
                    $("#num").text(obj);
                },"text");

(3)POST请求

a.语法
javascript 复制代码
$.post(url, [data], [callback], [type]);
b.属性解析
参数名称 描述
url 请求的服务器端url地址, 与form表单中的action一样,都是代表请求的路径
data 前台需要向后台传递的数据(键值对形式)
callback 当请求成功后的回掉函数,可以在函数体中编写我们的逻辑代码
type 预期的返回数据的类型,取值可以是 text、xml、html、json...
c.注意事项
  • 写法功能和$.ajax是一样的,但是严格要求属性顺序
  • 引入jQuery
d.示例
javascript 复制代码
				$.post("likeServlet",null,function (obj) {
                    $("#num").text(obj);
                },"text");

(4) . a j a x 与 .ajax与 .ajax与.get|$.post异同

相同点 不同点
都是jQuery封装的方法实现异步交互 $.ajax()是jQuery的第一次封装,使用时稍显麻烦,但是功能强大,覆盖了get和post请求,有错误调试能力,写法顺序可以改变。
. p o s t ( ) 和 .post()和 .post()和.get()是jQuery Ajax的第二次封装,由于 . A j a x ( ) 写法过于臃肿,简化为 .Ajax()写法过于臃肿,简化为 .Ajax()写法过于臃肿,简化为.post()和$.get(),功能是相同的没有区别。但是写法要求更高,顺序不能改变。

3.案例

  • 校验用户名是否唯一

(1)需求

  • 在用户注册页面,输入用户名,当用户名输入框失去焦点时,发送异步请求,将输入框的用户名传递给服务器端进行是否存在的校验。

(2)register.jsp

jsp 复制代码
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>注册</title>
<script src="jquery-3.6.4.js"></script>
<script>
   $(function () {
       // blur()失焦事件
       $("[name=username]").blur(function () {
           //获取用户输入的账号
           var username = $(this).val();
           //携带数据发送Ajax请求
           $.post("registerServlet",{"name":username},function(obj){
               if (obj) {
                   $("#username_msg").text("√");
               } else {
                   $("#username_msg").text("该账号已存在");
               }
           },"json");
       });
   });
</script>
</head>
<body>
<form action="" method="">
   账号:<input type="text" name="username"><span id="username_msg"></span><br>
   密码:<input type="password" name="password"><br>
   <input type="submit" value="注册">
</form>
</body>
</html>

(3)RegisterServlet.java

java 复制代码
package com.lfg.servlet;

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

@WebServlet("/registerServlet")
public class RegisterServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
       throws ServletException, IOException {
   String name = req.getParameter("name");
   boolean res = true;
   //账号不能是admin和chenwei
   if ("admin".equals(name) || "lfg".equals(name)) {
       res = false;
   }
   PrintWriter out = resp.getWriter();
   out.print(res);
   out.close();
}
}

(4)返回效果

四.Ajax返回值类型介绍

类型 介绍
XML 太麻烦,解析太费劲,已经不使用
HTML 网页,其实质和返回文本一样,没区别,一般使用文本代替
script 直接返回脚本
Text(文本) (默认返回类型)字符串类型,返回直接接收字符串
json 返回是一个json对象,脚本中可以直接操作这个对象,非常方便
jsonp 和Json一样,只不过这个支持跨域访问

五.JSON数据格式

1.JSON概述

  • JSON(JavaScript Object Notation, JS 对象标记) 是一种轻量级的数据交换格式。
  • 它基于ECMAScript的一个子集,采用完全独立于编程语言的文本格式来存储和表示数据。
  • 简洁和清晰的层次结构使得 JSON 成为理想的数据交换语言。
  • 易于人阅读和编写,同时也易于机器解析和生成,并有效地提升网络传输效率。
  • JSON本质上就是格式有点特殊的字符串。

2.JSON语法格式

类型 语法 解释
对象类型 {name:value,name:value...} 其中name是字符串类型,而value是任意类型
数组类型 [value,value,value...] 其中value是任意类型
混合类型 [{},{}... ...] 或 {name:[]... ...} 合理包裹嵌套对象类型和数组类型

3.JSON书写规范

  • 使用{}和[]书写,{}表示对象类型,[]表示数组类型
  • 对象类型中每组数据之间用逗号隔开,每组中的关键字与值之间用冒号隔开
  • 数组类型中每个值之间用逗号隔开,最后一个值后面不要加逗号

4.JSON数据应用

(1)概述

  • json的转换工具是通过java封装好的一些jar工具包,直接将java对象或集合转换成json格式的字符串。
  • json可以直接接收boolean值,故不用转字符串

(2)JSON数据中转换常用工具

工具名称 介绍
Jsonlib Java 类库,需要导入的jar包较多
Gson google提供的一个简单的json转换工具
Fastjson alibaba技术团队提供的一个高性能的json转换工具
Jackson 开源免费的json转换工具,springmvc转换默认使用jackson

5.JSON使用步骤

(1)导入json相关jar包

jackson-annotations-2.7.9.jar
jackson-core-2.7.9.jar
jackson-databind-2.7.9.jar

(2)创建java对象或集合

jsp 复制代码
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
<script src="jquery-3.6.4.js"></script>
<script>
   $(function () {
       $("#btn").click(function () {
           $.get("jsonServlet",null,function (obj) {
               console.log(obj);
               //解析对象
               //console.log(obj.sid+","+obj.name);
               //解析数组
               /*for (var i = 0;i < obj.length;i ++) {
                   console.log(obj[i]);
               }*/

               //解析装满学生对象的数组
               /*for (var i = 0;i < obj.length;i ++) {
                   console.log(obj[i].sid+","+obj[i].name);
               }*/

               //解析map
               var students = obj.students;
               for (var i = 0;i < students.length;i ++) {
                   console.log(students[i].sid+","+students[i].name);
               }

           },"json");
       });
   });
</script>
</head>
<body>
<input type="button" value="测试" id="btn">
</body>
</html>

(3)进行转换

  • 使用jackson的ObjectMapper对象的writeValueAsString方法进行转换
  • JsonServlet.java
java 复制代码
package com.lfg.servlet;

import com.lfg.entity.Student;
import com.fasterxml.jackson.databind.ObjectMapper;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@WebServlet("/jsonServlet")
public class JsonServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
   //对象类型
   Student student = new Student(1,"mary");

   //数组类型
   String[] strs = {"abc","bcd","cde"};

   //混合类型(集合)
   List<Student> list = new ArrayList<>();
   Student student1 = new Student(1,"mary");
   Student student2 = new Student(2,"tom");
   Student student3 = new Student(3,"jack");
   list.add(student1);
   list.add(student2);
   list.add(student3);

   Map<String,Object> map = new HashMap<>();
   map.put("students",list);

   //使用Jackson进行数据类型转换
   ObjectMapper mapper = new ObjectMapper();
   String str = mapper.writeValueAsString(map);
   System.out.println(str);
   PrintWriter out = resp.getWriter();
   out.print(str);
   out.close();

}
}

6.案例

  • 百度搜索框自动补全

(1)需求

  • 在输入框输入关键字,下拉框中异步显示与该关键字相关的学生姓名

(2)search.jsp

jsp 复制代码
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>百度一下</title>
<style type="text/css">
       * {
           margin: 0px;
           padding: 0px;
       }

       #box {
           display: inline-block;
       }

       #search {
           width: 545px;
           height: 42px;
           border-color: #4E6EF2;
           border-top-left-radius: 10px;
           border-bottom-left-radius: 10px;
           float: left;
       }

       #btn {
           width: 108px;
           height: 42px;
           background-color: #4e6ef2;
           color: #fff;
           border: none;
           font-size: 17px;
           font-weight: 400;
           border-top-right-radius: 10px;
           border-bottom-right-radius: 10px;
           float: left;
       }

       #show {
           width: 545px;
           border: 1px solid #4e6ef2;
           position: relative;
           left: -55px;
           text-align: left;
       }
   </style>
   <script src="jquery-3.6.4.js"></script>
   <script>
       $(function () {
           $("#search").bind("input propertyChange",function () {
               //获取输入的数据
               var sname = $(this).val();
               if (sname != "") {
                   $.get("studentServlet",{"sname":sname},function (obj) {
                       var div = "";
                       for (var i = 0;i < obj.length;i ++) {
                            div += "<div>"+obj[i].sname+"</div>";
                       }
                       $("#show").html(div);
                   },"json");
               } else {
                   $("#show").html("");
               }
           });
       });
   </script>
</head>
<body>
<center>
   <img alt="" width="310" height="150" src="http://www.baidu.com/img/PCtm_d9c8750bed0b3c7d089fa7d55720d6cf.png"><br/>
   <div id="box">
       <input id="search" type="text" name="search"/>
       <button id="btn">百度一下</button>
   </div>
   <div id="show">

   </div>
</center>
</body>
</html>

(3)StudentServlet.java

java 复制代码
package com.lfg.servlet;

import com.lfg.entity.Student;
import com.lfg.service.StudentService;
import com.lfg.service.impl.StudentServiceImpl;

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

@WebServlet("/studentServlet")
public class StudentServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
  req.setCharacterEncoding("utf-8");
  resp.setContentType("text/html;charset=utf-8");
  String sname = req.getParameter("sname");
  StudentService studentService = new StudentServiceImpl();
  String res = studentService.getStudentBySname(sname);
  PrintWriter out = resp.getWriter();
  out.print(res);
  out.close();
}
}

(4)Service

java 复制代码
package com.lfg.service;

public interface StudentService {
String getStudentBySname(String sname);
}


package com.lfg.service.impl;

import com.lfg.dao.StudentDao;
import com.lfg.dao.impl.StudentDaoImpl;
import com.lfg.entity.Student;
import com.lfg.service.StudentService;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;

import java.util.List;

public class StudentServiceImpl implements StudentService {

StudentDao studentDao = new StudentDaoImpl();

@Override
public String getStudentBySname(String sname) {
  List<Student> list = studentDao.getStudentBySname(sname);
  ObjectMapper mapper = new ObjectMapper();
  String str = "";
  try {
      str = mapper.writeValueAsString(list);
  } catch (JsonProcessingException e) {
      e.printStackTrace();
  }
  return str;
}
}

(5)Dao

java 复制代码
package com.lfg.dao;

import com.lfg.entity.Student;

import java.util.List;

public interface StudentDao {
List<Student> getStudentBySname(String sname);
}

package com.etime.dao.impl;

import com.etime.dao.StudentDao;
import com.etime.entity.Student;
import com.etime.util.C3P0Util;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanListHandler;

import java.sql.SQLException;
import java.util.List;

public class StudentDaoImpl implements StudentDao {

QueryRunner queryRunner = new QueryRunner(C3P0Util.getDataSource());

@Override
public List<Student> getStudentBySname(String sname) {
  List<Student> list = null;
  String sql = "select * from student where sname like ?";
  try {
      list = queryRunner.query(sql, new BeanListHandler<>(Student.class),"%"+sname+"%");
  } catch (SQLException e) {
      e.printStackTrace();
  }
  return list;
}
}

(6)实现效果

六.同异步

1.jsp

jsp 复制代码
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
    <script src="jquery-3.6.4.js"></script>
    <script>
        $(function () {
            $("#btn").click(function () {
                $.ajax({
                    url:"asyncServlet",
                    data:{"flag":"first"},
                    type:"get",
                    dataType:"text",
                    async:false,
                    success:function (obj) {
                        $("body").append(obj);
                    }
                });

                $.ajax({
                    url:"asyncServlet",
                    data:{"flag":"second"},
                    type:"get",
                    dataType:"text",
                    async:false,
                    success:function (obj) {
                        $("body").append(obj);
                    }
                });
            });
        });
    </script>
</head>
<body>
    <input type="button" value="同异步测试" id="btn">

</body>
</html>

2.servlet

java 复制代码
package com.lfg.servlet;

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

@WebServlet("/asyncServlet")
public class AsyncServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String flag = req.getParameter("flag");
        PrintWriter out = resp.getWriter();
        if ("first".equals(flag)) {
            out.print("<div style='background-color:red;'>" + flag + "</div>");
        } else {
            out.print("<div style='background-color:green;'>" + flag + "</div>");
        }
        out.close();
    }
}

3.注意事项

  • 必须使用同步的情况:第二个请求需要的数据是第一个请求返回的结果时
  • 设置同步请求
    • async:false
相关推荐
NoloveisGod几秒前
Vue的基础使用
前端·javascript·vue.js
GISer_Jing2 分钟前
前端系统设计面试题(二)Javascript\Vue
前端·javascript·vue.js
海上彼尚31 分钟前
实现3D热力图
前端·javascript·3d
杨过姑父31 分钟前
org.springframework.context.support.ApplicationListenerDetector 详细介绍
java·前端·spring
理想不理想v41 分钟前
使用JS实现文件流转换excel?
java·前端·javascript·css·vue.js·spring·面试
惜.己1 小时前
Jmeter中的配置原件(四)
java·前端·功能测试·jmeter·1024程序员节
EasyNTS1 小时前
无插件H5播放器EasyPlayer.js网页web无插件播放器vue和react详细介绍
前端·javascript·vue.js
poloma1 小时前
五千字长文搞清楚 Blob File ArrayBuffer TypedArray 到底是什么
前端·javascript·ecmascript 6
guokanglun1 小时前
Vue.js动态组件使用
前端·javascript·vue.js
Go4doom1 小时前
vue-cli3+qiankun迁移至rsbuild
前端