AJAX 介绍 AJAX(Asynchronous JavaScript And XML): 异步的JavaScript和XML 本身不是新技术, 而是多个技术的综合. 用于快速创建动态网页的技术. 一般的负面如果需要更新内容, 必需重新加载整个页面 而AJAX通过浏览器与服务器进行少量数据交换, 不可以使网页异步更新. 不重新加载整个页面, 对网页部分内容局部更新 原生JavaScript 实现AJAX 核心对象:xMLHttpRequest 用于在后台与服务器交换数据。可以在不重新加载整个网页的情况下,对网页的某部分进行更新。 打开链接:open(method,url,async) method :请求的类型 GET 或 POST. url:请求资源的路径, async:true(异步) 或false(同步)。 发送请求:send(String params) params:请求的参数(POST 专用)。 处理响应:onreadystatechange readyState :0-请求末初始化,1-服务器连接已建立,2-请求已接收 ,3-请求处理中,4-请求已完成,且响应已就绪。 status:200-响应已全部OK。 获得响应数据形式 response Text :获得字符串形式的响应数据。 responseXML:获得XML形式的响应 jQuery的Get方式实现AJAX 核心语法:$.get(url,[data],[callback],[type]); url:请求的资源路径 data:发送给服务器端的请求参数,格式可以是key=value,也可以是js对象 callback :当请求成功后的回调函数,可以在函数中编写我们的逻辑代码 type : 预期的返回数据的类型, 取值可以是xml, html, js, ison, text等 @WebServlet("/userServlet") public class UserServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { req.setCharacterEncoding("UTF-8"); resp.setContentType("text/html;charset=UTF-8"); // 1. 获取请求参数 String username = req.getParameter("username"); // 2. 判断姓名是否注册 if("zhangsan".equals(username)){ resp.getWriter().write(("<font color='red'>用户名已注册</font>")); }else{ resp.getWriter().write(("<font color='green'>用户名可用</font>")); } } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doGet(req, resp); } } <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>用户注册</title> </head> <body> <form autocomplete="off" > 姓名: <input type="text" id="username"> <span id="uSpan"></span> <br> 密码: <input type="password" id="password"> <br> <input type="submit" value="注册"> </form> </body> <script src="js/jquery-3.6.0.min.js"></script> <script> // 1. 为姓名绑定推动焦点事件 $("#username").blur(function(){ let username = $("#username").val(); // 2. jQuery的get方式实现AJAX $.get( "userServlet", "username="+username, // 3. 回调函数 function(data){ // 将响应的数据显示到span标签 $("#uSpan").html(data) }, "text" ); }) </script> </html> jQuery的POST方式实现AJAX 核心语法:$.post(url,[data],[callback],[type]) url:请求的资源路径 data:发送给服务器端的请求参数,格式可以是key=value,也可以是js对象 callback :当请求成功后的回调函数,可以在函数中编写我们的逻辑代码 type : 预期的返回数据的类型, 取值可以是xml, html, js, ison, text等 <script src="js/jquery-3.6.0.min.js"></script> <script> // 1. 为姓名绑定推动焦点事件 $("#username").blur(function(){ let username = $("#username").val(); // 2. jQuery的POST方式实现AJAX $.post( "userServlet", "username="+username, // 3. 回调函数 function(data){ // 将响应的数据显示到span标签 $("#uSpan").html(data) }, "text" ); }) </script> jQuery的通用方式实现AJAX 核心语法: $.ajax({name:value,name:value,…}); url :请求的资源路径. async :是否异步请求,true-是,false-否(默认是true)。 data:发送到服务器的数据,可以是键值对形式,也可以是js对象形式。 type:请求方式,POST或GET (默认是GET)。 dataType:预期的返回数据的券型,取值可以是xml,html,js, json, text等。 success :请求成功时调用的回调函数。 error :请求失败时调用的回调函数。 <script src="js/jquery-3.6.0.min.js"></script> <script> // 1. 为姓名绑定推动焦点事件 $("#username").blur(function(){ let username = $("#username").val(); $.ajax({ url: "userServlet", async: true, data: "username=" + username, type: "GET", success: function (data) { $("#uSpan").html(data) }, dataType: "text", error: function () { $("#uSpan").html("<font color='red'>出错了, 请稍后重试</font>") } }); }) </script> JSON 格式 类型 语法 说明 对象类型 {name:value,name:value,…} name是字符串类型,
value可以是任意类型 数组/集合类型 [{name:value,…},{name:value,…}] name是字符串类型,
value可以是任意类型 混合类型 {name:
[{name:value,…},{name:value,…}]
} name是字符串类型,
value可以是任意类型 常用方法 成员方法 说明 stringify(对象) 将指定对象转换为json格式字符串 parse(字符串) 将指定json格式字符串解析成对象 JSON Java 转换工具 jackson 类名 说明 ObjectMapper Jackson工具包的核心类,它提供一些方法来实现JSON字符串和对象之间的转换 TypeReference 对集合泛型的反序列化,使用TypeReference可以明确的指定反序列化的对象类型 ObjectMappper 常用方法 方法名 说明 String.writeValueAsString(Object.obj) 将Java对象转换成JSON字符串 <T>T.readValue(String.json,Class<T>.valueType) 将JSON字符串转换成Java对象 <T>T.readValue(String.json,TypeReference.valueTypeRef) 将JSON字符串转换成Java对象 public class User { private String name; private Integer age; public User(){} public User(String name, Integer age) { this.name = name; this.age = age; } } package com.example.ajax2; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; import org.junit.Test; import com.example.ajax2.User; import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; public class ObjectMapperTest { private ObjectMapper mapper = new ObjectMapper(); // 1. User对象转换json, json转User对象 @Test public void test01() throws JsonProcessingException { User user1 = new User("张三", 23); String json = mapper.writeValueAsString(user1); System.out.println("json字符串"+json); User user2 = mapper.readValue(json, User.class); System.out.println("Java对象"+user2); } // 2.map<String,String>转json json转map<String,String> @Test public void test02() throws IOException { Map<String,String> map = new HashMap<>(); map.put("姓名","张三"); map.put("性别","男"); String json = mapper.writeValueAsString(map); System.out.println("json字符串"+json); HashMap map2 = mapper.readValue(json, HashMap.class); System.out.println("Map对象"+map2); } // 3. map<String,User>转json json转map<String,User> @Test public void test03() throws Exception{ Map<String, User> map1 = new HashMap<>(); map1.put("1", new User("张三",23)); map1.put("2", new User("李四",24)); String json = mapper.writeValueAsString(map1); System.out.println("json字符串"+json); HashMap map2 = mapper.readValue(json, new TypeReference<HashMap<String, User>>() {} ); System.out.println("Map对象"+map2); } // 4.List<String>转json, json转List<String> @Test public void test04() throws Exception{ ArrayList<String> list = new ArrayList<>(); list.add("张三"); list.add("李四"); String json = mapper.writeValueAsString(list); System.out.println("json字符串"+json); // ArrayList<String> list2 = mapper.readVal ue(json, new TypeReference<ArrayList<String>>() { }); ArrayList<String> list2 = mapper.readValue(json, ArrayList.class); System.out.println("List<string>集合"+list2); } // 5. List<User>转json, json转List<User> @Test public void test05() throws Exception { ArrayList<User> list1 = new ArrayList<>(); list1.add(new User("张三",23)); list1.add(new User("李四",24)); String json = mapper.writeValueAsString(list1); System.out.println("json字符串"+json); ArrayList<User> list2 = mapper.readValue(json, new TypeReference<ArrayList<User>>() { }); System.out.println("List对象"+list2); } } 搜索联想 package com.lizicai.bean; public class Student { private Integer id; private String name; private Integer age; private Integer score; public Student(){} public Student(Integer id, String name, Integer age, Integer score) { this.id = id; this.name = name; this.age = age; this.score = score; } } <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>搜索</title> </head> <body> <form autocomplete="off" > 姓名: <input type="text" id="username" list="userlist" placeholder="输入名称搜索"> <datalist id="userlist"> </datalist> </form> </body> <script src="js/jquery-3.6.0.min.js"></script> <script> // 1. 为用户名输入框绑定鼠标点击事件 $("#username").mousedown(function(){ // 2. 获取用户名是否为空 let username = $("#username").val(); if( username == null || username == ""){ return; }else{ $.ajax({ url: "userServlet", async: true, data: {"username":username}, type: "POST", success: function (data) { let names = ""; console.log(data) for(let i=0;i<data.length;i++){ names +="<option>"+data[i].name+"</option>"; console.log(data[i]) } $("#userlist").html(names) }, dataType: "json" }); } }) </script> </html> package com.lizicai.sql; import org.apache.ibatis.jdbc.SQL; public class ReturnSql { public String getSelectLikeName(){ return new SQL(){ { SELECT("*"); FROM("student"); WHERE("name like CONCAT('%',#{name},'%')"); ORDER_BY("score DESC"); LIMIT("0,4"); } }.toString(); } } package com.lizicai.mapper; import com.lizicai.bean.Student; import com.lizicai.sql.ReturnSql; import org.apache.ibatis.annotations.*; import java.util.List; public interface StudentMapper { @SelectProvider(type = ReturnSql.class, method = "getSelectAll") public abstract List<Student> selectAll(); @SelectProvider(type = ReturnSql.class, method = "getSelectLikeName") public abstract List<Student> selectLikeName(String name); } package com.lizicai.service; import com.lizicai.bean.Student; import com.lizicai.mapper.StudentMapper; import org.apache.ibatis.io.Resources; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactoryBuilder; import org.junit.Test; import java.io.IOException; import java.io.InputStream; import java.util.List; public class Test001 { @Test public List<Student> selectLikeName(String name) throws IOException { InputStream is = Resources.getResourceAsStream("MyBatisConfig.xml"); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is); SqlSession sqlSession = sqlSessionFactory.openSession(true); StudentMapper mapper = sqlSession.getMapper(StudentMapper.class); List<Student> students = mapper.selectLikeName(name); for (Student stu : students) { System.out.println(stu); } sqlSession.close(); is.close(); return students; } } package com.lizicai.controller; import com.fasterxml.jackson.databind.ObjectMapper; import com.lizicai.bean.Student; import com.lizicai.service.Test001; 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("/userServlet") public class UserServlet extends HttpServlet { @Override public void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doPost(req, resp); } @Override public void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { req.setCharacterEncoding("UTF-8"); String username = req.getParameter("username"); ObjectMapper mapper = new ObjectMapper(); Test001 t = new Test001(); List<Student> list = t.selectLikeName(username); String json = mapper.writeValueAsString(list); resp.setContentType("application/json; charset=utf-8"); PrintWriter pw = resp.getWriter(); pw.write(json); pw.close(); } } 瀑布流分页 create database db11; use db11; CREATE TABLE news( id INT PRIMARY KEY AUTO_INCREMENT, title VARCHAR(999) ); DELIMITER $$ CREATE PROCEDURE create_date() BEGIN DECLARE i INT; SET i=1; WHILE i<=100 do INSERT INTO news VALUES (NULL,CONCAT('今天吃瓜啦,瓜',i)); SET i=i+1; end WHILE; end $$ CALL create_date(); 如何确定当前显示的数据已经浏览完毕 公式: 滚动条距询问的距离+滚去条上下滚动的距离+当前窗口的高度>=100 当前文档高度: 存储10条数据,100px 滚去条距询问的距离: 1px 当前窗口的高度: 80px 滚去条上下滚去的距离: >=19px 前置知识 功能 说明 $(function(){}) 页面加载事件 $(window) 获取当前窗口对象 scroll() 鼠标滚去事件 $(window).height() 当前窗口的高度 $(window).scrollTop() 滚去条上下滚去的距离 $(document).height() 当前文档的高度 package com.lizicai.controller; import com.fasterxml.jackson.databind.ObjectMapper; import com.github.pagehelper.Page; import com.lizicai.bean.News; import com.lizicai.service.NewsService; import com.lizicai.service.impl.NewsServiceImpl; 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("/newsList") public class NewsServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doPost(req, resp); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { req.setCharacterEncoding("UTF-8"); String pageNum = req.getParameter("pageNum"); String pageSize = req.getParameter("pageSize"); System.out.println(pageNum+" "+pageSize+"----"); Integer intPageNum = Integer.parseInt(pageNum) ; Integer intPageSize = Integer.parseInt(pageSize) ; ObjectMapper mapper = new ObjectMapper(); NewsService newsService = new NewsServiceImpl(); Page<News> page = newsService.pageQuery(intPageNum,intPageSize); String json = mapper.writeValueAsString(page); resp.setContentType("application/json; charset=utf-8"); PrintWriter pw = resp.getWriter(); pw.write(json); pw.close(); } } package com.lizicai.controller; import com.fasterxml.jackson.databind.ObjectMapper; import com.github.pagehelper.Page; import com.github.pagehelper.PageInfo; import com.lizicai.bean.News; import com.lizicai.service.NewsService; import com.lizicai.service.impl.NewsServiceImpl; 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("/newsList2") public class NewsServlet2 extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doPost(req, resp); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { req.setCharacterEncoding("UTF-8"); String pageNum = req.getParameter("pageNum"); String pageSize = req.getParameter("pageSize"); System.out.println(pageNum+" "+pageSize+"----"); Integer intPageNum = Integer.parseInt(pageNum) ; Integer intPageSize = Integer.parseInt(pageSize) ; ObjectMapper mapper = new ObjectMapper(); NewsService newsService = new NewsServiceImpl(); Page page = newsService.pageQuery(intPageNum,intPageSize); PageInfo<List<News>> pageInfo = new PageInfo<>(page); String json = mapper.writeValueAsString(pageInfo); resp.setContentType("application/json; charset=utf-8"); PrintWriter pw = resp.getWriter(); pw.write(json); pw.close(); } } <script> //1.定义发送请求标记 let send = true; //2.定义当前页码和每页显示的条数 let pageNum = 1; let pageSize = 10; //3.定义滚动条距底部的距离 let bottom = 1 //4.设置页面加载事件 $(function (){ //5.为当前窗口绑定滚动条滚动事件 $(window).scroll(function (){ //6.获取必要信息,用于计算当前展示数据是否浏览完毕 //当前窗口的高度 let windowHeight = $(window).height() ; //当前滚动条从上往下滚动的距离 let scrollTop = $(window).scrollTop(); //当前文档的高度 let docHeight = $(document).height() ; //7.计算当前展示数据什么时候浏览完毕 //当 滚动条距底部的距离 + 当前滚动条滚动的距离 + 当前窗口的高度 >= 当前文档的高度 if((bottom + scrollTop + windowHeight) >= docHeight) { //8.判断请求标记是否为true if(send == true){ // 如果当前页大于10,则将加载动图隐藏并结束方法 //9.将请求标记置为false,当前异步操作完成前,不能重新发起请求 send = false; //10.根据当前页和每页显示的条数来 请求查询分页数据 queryByPage(pageNum, pageSize); //11.当前页码+1 pageNum++; } } }); }) //请求查询分页数据的函数 function queryByPage(pageNum, pageSize){ //将加载动图显示 $(".loading").show(); //发起AJAX异步请求 $.ajax({ url:"newsList", data:{"pageNum":pageNum,"pageSize":pageSize}, type:"POST", dataType:"json", success:function (data){ if(data.length == 0){ // 加载动图隐藏 $(".loading").hide(); $("#no").html("我也是有底线的") return; } // 将数据进行显示 let titles = ""; for(let i=0;i<data.length;i++){ titles += "<li>\n" + " <div class=\"title-box\">\n" + " <a href=\"#\" class=\"link\">\n" + data[i].title+ " <hr>\n" + " </a>\n" + " </div>\n" + " </li>"; } //追加到页面 $(".news_list").append(titles); //将请求标记置为true send = true; } }) } </script> <script> // 1. 定义当前页码和每页显示的条数 let pageNum = 1; let pageSize = 10; // 2. 调用查询数据的方法 queryByPage(pageNum, pageSize) // 3. 定义请求查询分布数据的函数, 发起AJAX异步请求, 将数据显示到页面 function queryByPage(pageNum, pageSize){ $.ajax({ url:"newsList2", data:{"pageNum":pageNum,"pageSize":pageSize}, type:"POST", dataType:"json", success:function (pageInfo){ let titles = ""; for( let i=0;i<pageInfo.list.length;i++){ titles += "<li>\n" + " <div class=\"title-box\">\n" + " <a href=\"#\" class=\"link\">\n" + pageInfo.list[i].title+ " <hr>\n" + " </a>\n" + " </div>\n" + " </li>"; } // 将数据显示到页面上 $(".news_list").html(titles); // 4. 为分布按钮区域设置页数参数(总页数和当前页) $("#light-pagination").pagination({ pages:pageInfo.pages, currentPage: pageInfo.pageNum }); // 5. 为分布按钮绑定单击事件, 完成上一页下一页 $(".page-link").click(function(){ // 获取点击按钮的文本内容 let page = $(this).html() console.log(page) // 如果点击的是Prev, 调用查询方法, 查询当前页的上一页数据 if( page == "Prev"){ queryByPage(pageInfo.pageNum-1, pageSize) } else if(page == "Next"){ queryByPage(pageInfo.pageNum+1, pageSize) } else{ queryByPage(page, pageSize) } }) } }) } </script>