AJAX的介绍和使用
AJAX概述
AJAX介绍
同步和异步的区别
AJAX应用场景和访问流程
应用场景
检查用户名是否存在
省市级连
内容自动补全
执行流程
XMLHttpRequest对象的事件,方法和属性
案例:判断用户名是否存在
服务器Servlet
package com.itheima.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("/demo1")
public class Demo1UserServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//注:设置响应内容和编码,输出是纯文本,不是网页.因为返回给浏览器的数据是文本
response.setContentType("text/plain;charset=utf-8");
PrintWriter out = response.getWriter();
request.setCharacterEncoding("utf-8");
//1.获取用户输入的内容
String name = request.getParameter("name");
System.out.println("请求方式:"+request.getMethod());
//判断用户名是否存在
if ("newboy".equals(name)) {
//如果符合
out.print("用户名已存在");
} else {
//如果不符合
out.print("用户名可以使用");
}
}
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
}
前端代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>用户注册</title>
</head>
<body>
用户名:<input type="text" id="name"><span id="info"></span>
<script>
//设置输入框失去焦点事件
document.getElementById("name").onblur = function () {
//获取输入框的值,this表示文本框对象
let name = this.value;
//1.创建浏览器端请求对象
let request = new XMLHttpRequest();
//判断如果name值不为空
if (name != "") {
//2.设置服务器数据响应回来的回调函数(onreadystatechange 准备状态发生改变的事件)
/**
* 准备状态有以下四种情况,从服务器返回状态码
* 1.
*/
request.onreadystatechange = function () {
//只有服务器准备状态为4才会获取服务器端的数据,而且服务器的状态码为200(成功)
if (request.readyState == 4 && request.status == 200) {
//获取服务器端的纯文本数据
let text = request.responseText;
//将获取到的文本数据显示在span里面
document.getElementById("info").innerText = text;
}
}
// //get请求
// //3.打开服务器的连接地址.1.请求方式(get,post),2.访问地址,3.同步false异步true
// let url="demo1?name="+name;//get请求的参数在地址栏后
// request.open("GET",url,true);
// //发送请求
// request.send();
//post请求
request.open("POST","demo1",true)
request.setRequestHeader("content-type","application/x-www-form-urlencoded");
request.send("name="+name)
}
}
</script>
</body>
</html>
案例:POST请求完成登录的功能
//post请求
request.open("POST","demo1",true)
//设置一个请求头,所有的参数以键=值得方式发送给服务器
request.setRequestHeader("content-type","application/x-www-form-urlencoded");
//发送请求,数据在send中发送
request.send("name="+name)
小结
jQuery
选择器
jQuery的选择器和转换方式
与DOM有关的方法
事件
语法的区别
get()和post方法
jQuery实现判断用户名是否存在
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>jQuery注册页面</title>
<!-- 导入包-->
<script src="js/jquery-3.3.1.js"></script>
</head>
<body>
<h2>使用jQuery注册</h2>
用户名:<input type="text" id="name" placeholder="请输入用户名"><span id="info"></span>
<script>
//编写文本框失去焦点事件
$("#name").blur(function (){
//1.获取文本框的值,注:this是一个js对象,需要转成jq对象才能调用jq中方法
let name = $(this).val();
if (name!=""){
//后台访问服务器使用get方法发送
$.get({
url:"demo1",//访问服务器地址
data:"name="+name,//发送给服务器的数据
success:function (result){//服务器正常响应的回调函数,注:函数的参数用来获取服务器返回的数据
//将服务器返回的文本显示在span中
$("#info").text(result);
}
})
}
})
</script>
</body>
</html>
表示jQuery没有文件
$ is not defined
到out目录下添加文件
ajax有关的方法
JSON
JSON的格式介绍
JSON常见的三种类型
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>json页面</title>
</head>
<body>
<h1>对象类型</h1>
<script type="text/javascript">
let person = {
id: 1,
name: "孙悟空",
nickName: "齐天大圣",
};
//语法与EL是一样的,但这不是EL,这是JS中差值运算,EL只能用在JSP中,差值运算用在JS中.好处:代码的可读性更好,没有字符串拼接操作
document.write(`编号:${person.id},姓名:${person.name},昵称:${person.nickName}<hr/>`)
</script>
<h2>数组/集合类型</h2>
<script type="text/javascript">
let brothers = [
{
id: 1,
name: "孙悟空",
nickName: "齐天大圣"
},
{
id: 2,
name: "猪八戒",
nickName: "天蓬元帅"
},
{
id: 3,
name: "沙悟净",
nickName: "卷帘大将"
}];
//
for (let brother of brothers) {
document.write(`编号:${brother.id},姓名:${brother.name},昵称:${brother.nickName}<br/>`)
}
</script>
<hr/>
<h1>混合类型</h1>
<script type="text/javascript">
let master = {
id: 1,
name: "唐三藏",
nickName: "御弟哥哥",
brothers: [{
id: 2,
name: "孙悟空",
nickName: "齐天大圣",
},
{
id: 3,
name: "猪八戒",
nickName: "天蓬元帅"
}
,
{
id: 4,
name: "沙悟净",
nickName: "卷帘大将"
}]
};
//获取元素
document.write(`编号:${master.id},姓名:${master.name},昵称:${master.nickName}<br/>`)
//遍历元素
for (let masterElement of master.brothers) {
document.write(`编号:${masterElement.id},姓名:${masterElement.name},昵称:${masterElement.nickName}<br/>`)
}
</script>
</body>
</html>
JS中操作JSON的方法
将Java对象转成JSON字符串
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>与JSON有关的函数</title>
</head>
<body>
<script type="text/javascript">
//定义一个字符串
let str = '{"id":1,"name":"张三","nickName":"猪"}';
document.write(str + "<br/>")
//parse(字符串)方法将字符串转化为JSON对象,字符串->对象
let s1 = JSON.parse(str);
document.write(`${s1.id},${s1.name},${s1.nickName},` + "<br/>")
//对象转化为字符串
let s2 = JSON.stringify(s1);
document.write(s2 + "<br/>")
</script>
</body>
</html>
小结
JSON转换工具
案例:JSON的转换案例
package com.itheima.test;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.itheima.entity.User;
import org.junit.Test;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
public class Deno1Json {
//对象映射:对象与JSON格式字符串之间转换类
private ObjectMapper mapper =new ObjectMapper();
/**
*将对象与JSON字符串之间进行相互转换
*/
@Test
public void testObject() throws IOException {
User user = new User(1, "牛魔王", 520);
//将对象转换成JSON字符串
String json = mapper.writeValueAsString(user);
System.out.println(json);
//将JSON字符转换成对象,参数1:要转的字符串,参数2:要转的类型
User user1 = mapper.readValue(json, User.class);
System.out.println(user1);
}
/**
* 将List<String>与JSON字符串之间进行转换
*/
@Test
public void test1Object() throws IOException {
List<String> list=new ArrayList<>();
list.add("张三");
list.add("李四");
list.add("王五");
//对象->字符串
String json = mapper.writeValueAsString(list);
System.out.println(json);
//字符串->对象
List list1 = mapper.readValue(json, List.class);
System.out.println(list1);
}
/**
* 将List<User>与JSON字符串直之间转换
*/
@Test
public void test2Object() throws IOException {
List<User> list=new ArrayList<>();
list.add(new User(1,"孙悟空",30));
list.add(new User(2,"猪八戒",28));
list.add(new User(3,"白骨精",26));
//将List集合转换成JSON字符串
String json = mapper.writeValueAsString(list);
System.out.println(json);
//将JSON转换成List字符串
//注意:List中每个元素是LinkedHashMap类型.我们希望每个元素是User对象
//TypeReference是一个抽象类.用来指定泛型集合中每个元素的类型
List user = mapper.readValue(json,new TypeReference<List<User>>(){});
System.out.println(user);
}
}
扩展案例
提交表单数据,返回修改后的JSON数据
自动补全案例
需求和效果
环境搭建
导入数据库脚本
CREATE TABLE `user` (
`id` int(11) PRIMARY KEY AUTO_INCREMENT,
`name` varchar(32)
);
INSERT INTO `user` (`name`) VALUES ('张三');
INSERT INTO `user` (`name`) VALUES ('李四');
INSERT INTO `user` (`name`) VALUES ('王五');
INSERT INTO `user` (`name`) VALUES ('赵六');
INSERT INTO `user` (`name`) VALUES ('田七');
INSERT INTO `user` (`name`) VALUES ('孙八');
INSERT INTO `user` (`name`) VALUES ('张三丰');
INSERT INTO `user` (`name`) VALUES ('张无忌');
INSERT INTO `user` (`name`) VALUES ('李寻欢');
INSERT INTO `user` (`name`) VALUES ('王维');
INSERT INTO `user` (`name`) VALUES ('李白');
INSERT INTO `user` (`name`) VALUES ('杜甫');
INSERT INTO `user` (`name`) VALUES ('李贺');
INSERT INTO `user` (`name`) VALUES ('李逵');
INSERT INTO `user` (`name`) VALUES ('宋江');
INSERT INTO `user` (`name`) VALUES ('王英');
INSERT INTO `user` (`name`) VALUES ('鲁智深');
INSERT INTO `user` (`name`) VALUES ('武松');
INSERT INTO `user` (`name`) VALUES ('张薇');
INSERT INTO `user` (`name`) VALUES ('张浩');
INSERT INTO `user` (`name`) VALUES ('刘小轩');
INSERT INTO `user` (`name`) VALUES ('刘浩宇');
流程分析
后端服务器代码
编写实体类
public class User {
private int id;
private String name;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
mybatis-config.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<settings>
<!--在控制台显示SQL语句-->
<setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>
<!--定义实体类别名-->
<typeAliases>
<package name="com.itheima.entity"/>
</typeAliases>
<environments default="default">
<!--环境变量-->
<environment id="default">
<!--事务管理器-->
<transactionManager type="JDBC"/>
<!--数据源-->
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/day33"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
</environment>
</environments>
<!--加载其它映射文件-->
<mappers>
<package name="com.itheima.dao"/>
</mappers>
</configuration>
UserDao接口
package com.itheima.dao;
import com.itheima.entity.User;
import org.apache.ibatis.annotations.Select;
import java.util.List;
/**
* 用户数据访问层 Data Access Object(持久层)
*/
public interface UserDao {
/**
* 查询指定字符串开头的用户列表
*/
@Select("SELECT * FROM `user` WHERE `name` LIKE #{name}\"%\"")
List<User> findUserByPrefix(String name);
}
MyBatisUtils类
package com.itheima.utils;
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 MyBatisUtils {
//会话工厂的创建类->会话工厂->会话
private static SqlSessionFactory factory;
static {
//1.会话工厂的创建类
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
//2.得到配置文件的输入流
try (InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml")) {
//3.创建会话工厂
factory = builder.build(inputStream);
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 得到会话对象
* @return
*/
public static SqlSession getSession() {
return factory.openSession();
}
}
DAO的工厂类
package com.itheima.util;
import org.apache.ibatis.session.SqlSession;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Arrays;
/**
* 所有DAO接口的代理实现类
*/
public class DaoInstanceFactory {
/**
* 获取DAO接口的代理对象
*/
public static <T> T getBean(Class<T> interfaceClass) {
/**
* 参数1:类加载器,我们自己写的类是同一个类加载器
* 参数2:实现的接口
* 参数3:回调函数,接口中每个方法都会调用一次
*/
return (T) Proxy.newProxyInstance(
DaoInstanceFactory.class.getClassLoader(),
new Class[]{interfaceClass},
new InvocationHandler() {
/**
* 每个被代理的方法都会调用一次
* @param proxy 代理对象
* @param method 被代理的方法
* @param args 方法参数
* @return 方法的返回值
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//1.获取会话对象
SqlSession session = MyBatisUtils.getSession();
//2.得到dao的代理对象
T dao = session.getMapper(interfaceClass);
//3.调用接口中方法,查询得到结果
//参数1:调用方法的对象,参数2:方法参数数组
System.out.println("调用了DAO的方法:" + method.getName() + ",参数是:" + Arrays.toString(args));
Object result = method.invoke(dao, args);
//4.关闭会话
session.commit();
session.close();
//5.返回
return result;
}
});
}
}
UserService接口
package com.itheima.service;
import com.itheima.entity.User;
import java.util.List;
public interface UserService {
/**
* 查询指定字符串开头的用户信息
*/
List<User> findUserByPrefix(String name);
}
UserServiceImpl实现类
package com.itheima.service.impl;
import com.itheima.dao.UserDao;
import com.itheima.entity.User;
import com.itheima.service.UserService;
import com.itheima.utils.DaoInstanceFactory;
import java.util.List;
/**
* 业务层
*/
public class UserServiceImpl implements UserService {
private UserDao userDao = DaoInstanceFactory.getBean(UserDao.class);
/**
* 查询指定字符串开头的用户信息
* @param name
*/
@Override
public List<User> findUserByPrefix(String name) {
return userDao.findUserByPrefix(name);
}
}
Servlet的编写
package com.itheima.servlet;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.itheima.entity.User;
import com.itheima.service.UserService;
import com.itheima.service.impl.UserServiceImpl;
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("/user")
public class UserServlet extends HttpServlet {
private UserService userService = new UserServiceImpl();
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//汉字乱码的处理
request.setCharacterEncoding("utf-8");
//1.获取提交的用户名
String username = request.getParameter("username");
//2.调用业务层查询以这个名字开头的用户
List<User> userList = userService.findUserByPrefix(username);
//3.转成JSON字符串
String json = new ObjectMapper().writeValueAsString(userList);
response.setContentType("application/json;charset=utf-8");
PrintWriter out = response.getWriter();
//4.打印到浏览器端
out.print(json);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
}
前端HTML代码
<!DOCTYPE html>
<html lang="zh-CN">
<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 black;
}
input[type='button'] {
width: 100px;
height: 30px;
background: #38f;
border: 0;
color: #fff;
font-size: 15px;
}
#show {
box-sizing: border-box;
position: relative;
left: 8px;
font-size: 14px;
width: 280px;
border: 1px solid black;
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>
<script type="text/javascript">
//在文本框中松开键盘上按键激活事件
$("#word").keyup(function () {
//获取文本框中值
let username = $("#word").val().trim();
//判断文本框中有没有内容
if (username == "") {
//隐藏div
$("#show").hide();
return;
}
//继续表示文本框中有内容
$.post({
url: "user",
data: {
username: username
},
//users就是服务器返回的集合对象
success: function (users) {
if (users.length > 0) {
let html=``; //定义空串
for (let user of users) {
html+=`<div>${user.name}</div>`;
}
//把这些div填充到大的div中
$("#show").html(html);
//显示div
$("#show").show();
}
else {
//隐藏div
$("#show").hide();
}
}
});
});
</script>
</body>
</html>