AJAX
Asynchronous JavaScript And Xml :异步JavaScript和XML;
用于快速创建动态网页的技术;
对页面进行局部更新;
异步同步
同步方式:正常情况下,浏览器与服务器之间是串行操作,类似于一个Java线程的操作。
异步方式:浏览器与服务器是并行操作,类似于Java中多个线路同时工作。
AJAX使用的技术
JavaScript:用于后台发送数据给服务器,并且对服务器返回的结果进行处理。
XML:用于接收服务器返回的数据,但是已经被JSON格式代替。
原生AJAX
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Crhw5Im6-1593939140557)(C:\Users\computer\AppData\Local\Temp\1593172499571.png)]
流程说明:
1、用户在浏览器端由JS创建一个对象XMLHttpRequest对象
2、这个对象是ajax的核心对象,由它发送请求给服务器
3、将请求的数据发送到服务器
4、在服务器处理数据,从数据库中查询用户是否存在,通过XML(JSON)把数据返回
5、在回调函数中得到服务器返回的数据,使用HTML和CSS更新页面的信息
编写
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>原始AJAX</title>
<script src="js/jquery-3.3.1.js"></script>
</head>
<body>
用户名:<input type="text" id="name"><span id="spa"></span>
<script type="text/javascript">
document.getElementById("name").onchange = function () {
//获取XMLHttpRequest对象
let xhr = new XMLHttpRequest();
//打开服务器连接;发送方式、地址、是否异步
xhr.open("GET","Json/User.json",true);
//发送请求
xhr.send();
let user = document.getElementById("name").value;
let flag = false;
//回调函数,状态改变时接收数据
xhr.onreadystatechange = function () {
//准备状态等于4,服务器状态码等于200;这样等于服务器成功响应
if(xhr.status == 200 && xhr.readyState == 4){
//接收响应数据
let datas = xhr.responseText;//相应返回为字符串
//处理数据
let das = JSON.parse(datas);
for (let da of das) {
if(da == user){
flag = true;
break;
}
}
if(flag){
$("#spa").text("用户名重复!");
// document.getElementById("spa").innerText = "用户名重复!";
}
else {
$("#spa").text("恭喜,可以注册!");
// document.getElementById("spa").innerText = "恭喜,可以注册!";
}
}
}
}
</script>
</body>
</html>
使用方式
. g e t ( ) 和 .get()和 .get()和.post()方式
二者除提交方式和名称不一样外,其余参数完全一样;(3.0版本以前的使用方式)
使用
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>3.0以前get等方式的使用</title>
<script src="js/jquery-3.3.1.js"></script>
</head>
<body>
用户名:<input type="text" id="name"><span id="spa"></span>
<script type="text/javascript">
$("#name").change(function () {
$.get("Json/User.json",//地址值;post方式为$.post();其余一样
function (users) {//回调函数,接收响应数据
let name = $("#name").val();
let flag = false;
for (let user of users) {
if(user == name){
flag = true;
break;
}
}
if(flag){
$("#spa").text("用户名重复!");
}else {
$("#spa").text("恭喜,可以注册!");
}
},
"json"//响应数据格式
);
});
</script>
</body>
</html>
$.AJAX()方式
参数说明
$.ajax({键:值,键:值}) 属性名称 | 解释 |
---|---|
url | 服务器访问地址 |
async | 默认是异步,取值是true,设置为false表示同步 |
method | GET或POST方法,默认GET |
data | 发送给服务器的数据,2种格式: 1. 键=值&键=值 2. {键:值, 键:值} |
dataType | 服务器返回的数据类型 取值:xml, html, script, json, text |
success | 服务器正常响应的回调函数,参数就是服务器返回的数据 |
error | 服务器出现异常的回调函数,参数是XMLHttpRequest对象 |
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>$.ajax实现用户登录</title>
<script src="js/jquery-3.3.1.js"></script>
</head>
<body>
<form id="loginForm">
<table>
<tr>
<td>用户名</td>
<td><input type="text" name="username" id="username"/></td>
</tr>
<tr>
<td>密码</td>
<td><input type="password" name="password" id="password"/></td>
</tr>
<tr>
<!--登录按钮是一个普通按钮-->
<td colspan="2" align="center"><input type="button" value="登录" id="btnLogin"/></td>
</tr>
</table>
</form>
<script type="text/javascript">
$("#btnLogin").click(function () {
let name = $("#username").val();
let password = $("#password").val();
$.ajax({ //此处方法名称可以改为$.post()和$.get();3.0版本以后可以使用
url:"Json/login.json",
// async:true,//默认异步
// method:"POST",//不写默认是get提交方式
success:function (users) {//回调函数接收响应数据
let flag = false;
for (let user of users) {
if(user.name == name && user.password == password){
flag = true;
break;
}
}
if(flag){
alert("登录成功!" + name);
}else{
alert("用户名或密码错误!");
}
},
dataType:"json"//数据类型
});
});
</script>
</body>
</html>
JSON
概念: JavaScript Object Notation
作用
json现在多用于存储和交换文本信息的语法;
进行数据的传输;
JSON 比 XML 更小、更快,更易解析。
格式
{
"name":"张三",
"age":23,
"gender":"男"
}
前段json格式转换
方法 | 说明 |
---|---|
stringify | 对象转字符串 |
parse | 字符串转对象 |
后端json格式转换
ObjecrtMapper
- writeValueAsString:字符串转json
- readValue:json转字符串
案例
案例1、搜索联想词
需求
当在搜索框中输入关键字,搜索框下方显示相关联想词
步骤
1、前端页面获取输入关键字名称
2、前段根据关键字发送异步请求到后端请求数据
3、前段根据后端响应数据在页面上回写内容
模拟后端数据
json文件
[
"张三",
"李四",
"王五",
"赵六",
"田七",
"孙八",
"张三丰",
"张无忌",
"李寻欢",
"王维",
"李白",
"杜甫",
"李贺",
"李逵",
"宋江",
"王英",
"鲁智深",
"武松",
"张薇",
"刘小轩",
"刘浩宇",
"刘六"
]
前段页面
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>自动补全</title>
<style type="text/css">
.content {
width: 400px;
margin: 30px auto;
text-align: center;
}
input[type='text'] {
box-sizing: border-box;
width: 280px;
height: 30px;
font-size: 14px;
border: 1px solid #38f;
}
input[type='button'] {
width: 100px;
height: 30px;
background: #38f;
border: 0;
color: #fff;
font-size: 15px;
}
#show {
box-sizing: border-box;
position: relative;
left: 7px;
font-size: 14px;
width: 280px;
border: 1px solid dodgerblue;
text-align: left;
border-top: 0;
/*一开始是隐藏不可见*/
display: none;
}
#show div {
padding: 4px;
background-color: white;
}
#show div:hover {
/*鼠标移上去背景变色*/
background-color: #3388ff;
color: white;
}
</style>
<script src="js/jquery-3.3.1.js"></script>
</head>
<body>
<div class="content">
<img alt="传智播客" src="img/logo.png"><br/><br/>
<input type="text" name="word" id="word">
<input type="button" value="搜索一下">
<div id="show"></div>
</div>
</body>
<script type="text/javascript">
//当键盘松开事件,触发请求
$("#word").keyup(function () {
//获取输入数据
let value = $("#word").val().trim();
//防止null
if(value == ""){
$("#show").hide();
return;
}
//发送异步请求
$.post({
url:"Json/search.json",
success:function (datas) {
let reg = new RegExp("^" + value);
let arr = new Array();
let html = "";
//处理响应数据
for (let data of datas) {
if(reg.test(data)){
arr.push(data);
}
}
if(arr.length == 0){
$("#show").hide();
return;
}
//回显数据
for (let a of arr) {
html += "<div>" + a + "</div>";
}
$("#show").html(html);
$("#show").fadeIn(500);
$("#show div").click(function () {
let text = $(this).text();
$("#word").val(text);
$("#show").slideUp("normal");
});
},
dataType:"json"
});
});
</script>
</html>
案例2分页
插件介绍
前端插件
css文件:simplePagination.css
js文件:jquery.simplePagination.js
使用
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
//导入分页插件样式
<link rel="stylesheet" href="css/simplePagination.css">
</head>
<body>
//其固定样式div,必须这样写
<div class="content">
<div class="pagination-holder clearfix">
<div id="light-pagination" class="pagination"></div>
</div>
</div>
</body>
//导入js文件,必须同时导入两个该文件
<script src="js/jquery-3.3.1.min.js"></script>
<script src="js/jquery.simplePagination.js"></script>
<script>
//设置页数和当前页;必须是这样的格式
$("#light-pagination").pagination({
pages:10,
currentPage:5
});
</script>
</html>
效果
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yM7TifFu-1593939140568)(C:\Users\computer\AppData\Local\Temp\1593312393921.png)]
后端插件
导包:pageHelper-5.1.10.jar
方法:PageHelper.startPage(start,pageSize);
经过插件处理后,如果后续有查询数据,会自动封装到该对象中
使用
//封装Page对象 start:当前页码 pageSize:每页显示的条数;
page = PageHelper.startPage(start,pageSize);
分页1:瀑布式
需要用到后端分页插件
需求
当滚动条向下滑动触底时显示更多数据;
使用技术
mybatis、jquery、ajax、mysql
步骤
1、页面加载显示一定数据;
2、当滚动条向下滑动触底请求服务器数据
3、处理服务器响应数据并回显到页面上
配置mybatis核心配置文件;log4j.properties文件,导包等等;
前端
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>网站首页</title>
<link rel="stylesheet" href="css/tt.css">
</head>
<body>
<div class="top">
<span class="top-left">下载APP</span>
<span class="top-left"> 北京 晴天</span>
<span class="top-right">更多产品</span>
</div>
<div class="container">
<div class="left">
<a>
<img src="img/logo.png"><br/>
</a>
<ul>
<li>
<a class="channel-item active" href="#">
<span>
推荐
</span>
</a>
</li>
<li><a class="channel-item" href="#">
<span>
视频
</span>
</a></li>
···
</ul>
</div>
<div class="center">
//页面加载时显示数据
<ul class="news_list">
<li>
<div class="title-box">
<a href="#" class="link">
奥巴马罕见介入美国2020大选,警告民主党参选人须“基于现实11”
<hr>
</a>
</div>
</li>
····
</ul>
<div class="loading" style="text-align: center; height: 80px">
<img src="img/loading2.gif" height="100%">
</div>
<div class="content">
<div class="pagination-holder clearfix">
<div id="light-pagination" class="pagination"></div>
</div>
</div>
<div id="no" style="text-align: center;color: red;font-size: 20px"></div>
</div>
</div>
</body>
<script src="js/jquery-3.3.1.js"></script>
<script>
//1.定义发送请求标记
let send = true;
//2.定义当前页码和每页显示的条数
let start=1;
let size=10;
//3.定义滚动条距底部的距离
let bottom = 5;
//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){
//9.将请求标记置为false,当前异步操作完成前,不能重新发起请求
send = false;
//10.根据当前页和每页显示的条数来 请求查询分页数据
queryInfo(start,size);
//11.当前页码+1
start++;
}
}
});
});
//请求查询分页数据的函数
function queryInfo(start, pageSize) {
//将加载动图显示
$(".loading").show();
//发起AJAX异步请求
$.ajax({
url:"newsServlet",
data:{"start":start,"pageSize":pageSize},
success:function (datas) {
if (datas.length == 0) {
$(".loading").hide();
$("#no").html("没了。。。");
return;
}
$(".loading").hide();
let html = ``;
for (let i = 0; i < datas.length; i++) {
html+=`<li>
<div class="title-box">
<a href="#" class="link">
${datas[i].title}
<hr>
</a>
</div>
</li>`;
}
//追加到页面
$(".news_list").append(html);
//将请求标记置为true
send=true;
}
})
};
</script>
</html>
servlet
package com.itheima.controller;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.github.pagehelper.Page;
import com.itheima.service.NewsService;
import com.itheima.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;
@WebServlet("/newsServlet")
public class NewsServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//设置请求和响应的编码
req.setCharacterEncoding("UTF-8");
resp.setContentType("applicaion/json;charset=UTF-8");
//1.获取请求参数
String start = req.getParameter("start");
String pageSize = req.getParameter("pageSize");
//2.根据当前页码和每页显示的条数,调用业务层的方法,得到分页Page对象
NewsServiceImpl newsService = new NewsServiceImpl();
Page page = newsService.pageQuery(Integer.parseInt(start), Integer.parseInt(pageSize));
//3.将得到的数据转为json
String s = new ObjectMapper().writeValueAsString(page);
//模拟服务器加载数据需要1秒钟
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//4.将数据响应给客户端
resp.getWriter().write(s);
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req,resp);
}
}
service
package com.itheima.service.impl;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.itheima.mapper.NewsMapper;
import com.itheima.service.NewsService;
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 java.io.IOException;
import java.io.InputStream;
public class NewsServiceImpl implements NewsService {
@Override
public Page pageQuery(Integer start, Integer pageSize) {
InputStream is = null;
SqlSession sqlSession = null;
Page page = null;
try{
//1.加载核心配置文件
is = Resources.getResourceAsStream("MyBatisConfig.xml");
//2.获取SqlSession工厂对象
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
//3.通过SqlSession工厂对象获取SqlSession对象
sqlSession = sqlSessionFactory.openSession(true);
//4.获取NewsMapper接口的实现类对象
NewsMapper mapper = sqlSession.getMapper(NewsMapper.class);
//5.封装Page对象 start:当前页码 pageSize:每页显示的条数
page = PageHelper.startPage(start,pageSize);
//6.调用实现类对象的查询全部方法,此时底层执行的就是MySQL的limit分页查询语句
mapper.selectAll();
} catch (Exception e) {
e.printStackTrace();
} finally {
//7.释放资源
if(sqlSession != null) {
sqlSession.close();
}
if(is != null) {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
//8.返回page对象
return page;
}
}
dao
public interface NewsMapper {
/*
查询全部
*/
@Select("SELECT * FROM news")
public abstract List<News> selectAll();
}
分页2:正常分页
需要使用上述前后端分页插件
操作基本类似瀑布式;
前端页面
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<link rel="stylesheet" href="css/simplePagination.css">
<link rel="stylesheet" href="css/tt.css">
</head>
<body>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>网站首页</title>
<link rel="stylesheet" href="css/tt.css">
</head>
<body>
<div class="top">
<span class="top-left">下载APP</span>
<span class="top-left"> 北京 晴天</span>
<span class="top-right">更多产品</span>
</div>
<div class="container">
<div class="left">
<a>
<img src="img/logo.png"><br/>
</a>
<ul>
<li>
<a class="channel-item active" href="#">
<span>
推荐
</span>
</a>
</li>
<li><a class="channel-item" href="#">
<span>
视频
</span>
</a></li>
</ul>
</div>
<div class="center">
<div id="error"></div>
<ul class="news_list">
</ul>
<div class="content">
<div class="pagination-holder clearfix">
<div id="light-pagination" class="pagination"></div>
</div>
</div>
<div id="no" style="text-align: center;color: red;font-size: 20px"></div>
</div>
</div>
</body>
<script src="js/jquery-3.3.1.js"></script>
<script src="js/jquery.simplePagination.js"></script>
<script>
$(function () {
//设置加载时开始页面和页面大小
let start = 1;
let pageSize = 10;
pageIn(start,pageSize);
//查询当前页面数据的方法
function pageIn(start,pageSize){
$.ajax({
url:"newsServlet02",
data:{"start":start,"pageSize":pageSize},
type:"POST",
dataType:"json",
success:function(datas){
if (datas.list.length == 0){
$("#error").html("无数据信息!");
return;
}
let html = ``;
for (let i = 0; i < datas.list.length; i++) {
html+=`<li>
<div class="title-box">
<a href="#" class="link">
${datas.list[i].title}
<hr>
</a>
</div>
</li>`;
}
$(".news_list").html(html);
//分页
$("#light-pagination").pagination({
pages:datas.page,
currentPage:datas.pageNum
});
//添加分页点击事件;递归
$("#light-pagination .page-link").click(function () {
let v = $(this).html();
if(v == "Prev"){
pageIn(datas.pageNum-1,pageSize);
}else if(v == "Next"){
pageIn(datas.pageNum-1,pageSize);
}else {
pageIn(v,pageSize);
};
});
}
})
}
});
</script>
</html>
</body>
</html>
后端与瀑布式一样
servlet改变处
//2.根据当前页码和每页显示的条数,调用业务层的方法,得到分页Page对象
NewsServiceImpl newsService = new NewsServiceImpl();
Page page = newsService.pageQuery(Integer.parseInt(start), Integer.parseInt(pageSize));
//封装数据
PageInfo<List<News>> info = new PageInfo<>(page);
//3.将得到的数据转为json
String s = new ObjectMapper().writeValueAsString(info);