目录
一、Ajax快速入门
1.基本介绍 :
(1)AJAX,全称"Asynchronous JavaScript And XML",指异步JavaScript和XML。Ajax是一种支持浏览器异步发起请求(可以指定发送的数据),以及页面局部更新的技术。
(2) Ajax的常见应用场景如下——
1> 搜索引擎根据用于输入的关键字,自动提示检索关键字。
2> 动态加载数据,按需取得数据。(树形菜单、联动菜单......等,eg : 选择省份后自动加载出对应的市县)
3> 电子商务应用。(购物车,邮件订阅)
4> 改善用户体验。(输入内容前提示,带进度条的文件上传)
5> 访问第三方服务。(访问搜索服务,rss阅读器)
6> 页面局部刷新。(网站展示数据的实时刷新)
2.使用原理 :
传统的web数据通信方式的弊端——
①表单提交数据时,默认提交将该表单的全部数据都提交给服务端,数据量大且无意义。
②在服务端未给出HTTP响应之前,浏览器前端会一直处于等待状态,或者被挂起。
③无法进行页面的局部刷新,用户体验感较差。
使用Ajax的web数据通信方式的原理示意图如下——
编辑
Ajax数据通信方式与传统通信方式最大的区别在于,浏览器端并不是直接向服务器端发送HTTP请求,而是要先经过Ajax引擎对象——XMLHttpRequest对象的处理(浏览器内置对象),再发出请求。服务器端仍然是接收数据并做出相应处理,之后再通过HTTP响应将数据返回给浏览器,返回的数据格式可以是XML,JSON,或者是普通文本。浏览器接收到服务端的响应后,Ajax会解析返回的数据,并将解析之后的数据渲染到页面的对应元素中,以实现页面的局部刷新。
通过Ajax发送HTTP请求的优点——
①可以通过XMLHttpRequest对象,发送指定数据,数据量小且速度快。
②XMLHttpRequest对象是异步发送数据,在服务端没有回送HTTP响应之前,浏览器不需要等待,可以继续操作。
③实现了页面的局部刷新,提高了用户的体验。
PS : XMLHttpRequest对象有几个重要的属性,如下表所示 :
属性 | 描述 |
onload | 定义接收到(加载)请求时要调用的函数。 |
onreadystatechange | 定义当 readyState 属性发生变化时调用的函数。 |
readyState | 保存 XMLHttpRequest 的状态。
|
responseText | 以字符串形式返回响应数据。 |
responseXML | 以 XML 数据返回响应数据。 |
status | 返回请求的状态号
|
statusText | 返回状态文本(比如 "OK" 或 "Not Found") |
二、Ajax经典入门案例
1.需求 :
界面效果如下:
编辑
①编写一个用户登录页面,要求对用户名进行校验 (对用户名校验的HTTP请求要借助Ajax来发送!),若用户名已经存在于MySQL数据库中的user_demo用户表中,提示用户名重复、不可用,并以JSON格式的字符串返回该用户的信息;反之,则提示用户名可用。
②要求按照“Domain层 --> DAO层 --> Service层”的三层结构来实现业务逻辑。
③要求编写一个servlet用于处理客户端的HTTP请求,在servlet中利用已经实现的三层结构来完成业务,并向前端页面返回处理后的数据;前端页面收到HTTP响应后,要根据业务需求实现页面的局部刷新。
2.前端页面实现 :
login.html代码如下 :
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Login</title> <style type="text/css"> table, td, th { background-color: lightcyan; border:2px pink solid; border-collapse: collapse; padding: 5px } </style> <script type="text/javascript"> window.onload = function () { var checkButton = document.getElementById("checkButton"); checkButton.onclick = function () { //1.创建XMLHttpRequest对象 [AJax引擎对象] var xhr = new XMLHttpRequest(); //2.获取用户提交的数据 var uname = document.getElementById("uname").value; //3.利用open方法,规定请求的类型、URL、以及是否异步处理请求。 /* (1) 第一个参数———请求方式。可以是GET/POST等。 (2) 第二个参数———URL。此处采用了拼接的形式。 (3) 第三个参数———true。true表示异步发送。 */ xhr.open("GET", "/Ajax/checkUser?username=" + uname, true) /* !!! 在调用send函数之前,给XMLHttpRequest对象绑定一个事件onreadystatechange 该事件表示,当readyState属性的数据发生变化时, 会触发onreadystatechange事件,并调用指定的函数 */ xhr.onreadystatechange = function () { //若请求已经完成,响应已经就绪,且响应状态码是200 if (xhr.readyState == 4 && xhr.status == 200) { //获取实际返回的数据 var responseText = xhr.responseText; //若返回的字符串非null,说明该用户名重复,不可用 if (responseText.trim() != "") { checkButton.value = "用户名不可用"; var div01 = document.getElementById("div01"); //!!!!!! //由于是div元素,所以要更改的是innerText or innerHTML属性值 div01.innerHTML = responseText; div01.removeAttribute("hidden"); } else { checkButton.value = "用户名可用"; } } } //4.调用send方法,真正发送请求 //如果是POST请求,需要调用xhr.send("content"); xhr.send(); } } </script> </head> <body> <form action="/Ajax/checkUser" method="post"> <table width="625px"> <tr> <th colspan="3"><h2>用户注册</h2></th> </tr> <tr> <td>Username:</td> <td><input type="text" name="username" id="uname"/></td> <td><input type="button" value="验证用户名" id="checkButton"/></td> </tr> <tr> <td>Password:</td> <td><input type="password" name="password"/></td> </tr> <tr> <td>e-mail:</td> <td><input type="text" name="email"/></td> </tr> <tr> <td><input type="submit" value="Submit"/></td> <td><input type="reset" value="Reset"/></td> </tr> <tr> <th colspan="3"><h2>返回的JSON数据如下:</h2></th> </tr> <tr> <td colspan="3"><div id="div01"></div></td> </tr> </table> </form> </body> </html>
3. 处理HTTP请求的servlet实现
CheckUserServlet类代码如下 :
package servlet; import com.google.gson.Gson; import jakarta.servlet.ServletException; import jakarta.servlet.annotation.WebServlet; import jakarta.servlet.http.HttpServlet; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import javabean.User; import service.UserService; import java.io.IOException; @WebServlet(urlPatterns={"/checkUser"}) public class CheckUserServlet extends HttpServlet { //定义一个UserService属性 UserService userService = new UserService(); @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //联系手写Tomcat底层机制中,HttpServletRequest中封装的用于存储参数的Map对象。 String username = req.getParameter("username"); System.out.println("username = " + username); //此处利用了已实现的"Domain---DAO---Service"三层结构 User user = userService.getUserByName(username); if (user != null) { Gson gson = new Gson(); String strUser = gson.toJson(user); resp.setContentType("text/html; charset=utf-8"); resp.getWriter().print(strUser); } else { resp.getWriter().print(""); } } @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doPost(req, resp); } }
4.引入jar包及druid配置文件、工具类 :
引入jar包如下图所示 :
编辑
druid.properties配置文件如下 : (src目录下)
# 驱动名称(连接MySQL) driverClassName=com.mysql.cj.jdbc.Driver # 参数?rewriteBatchedStatements=true表示支持批处理机制 url=jdbc:mysql://localhost:3306/a_ajax?rewriteBatchedStatements=true # 用户名,注意这里是按“username”来读取的 username=root # 用户密码(自己改) password=RA9_Cyan # 初始化连接数量 initialSize=10 # 最小连接数量 minIdle = 5 # 最大连接数量 maxActive=50 # 超时时间5000ms(在等待队列中的最长等待时间,若超过,放弃此次请求) maxWait=5000
注意druid.properties配置文件中要修改连接的数据库,以及登录用户的用户名和密码!
负责德鲁伊连接池的工具类JDBCUtilsDruid,代码如下 : (尤其注意导入配置文件时和Java SE的使用区别)
package utils; import com.alibaba.druid.pool.DruidDataSourceFactory; import javax.sql.DataSource; import java.io.FileInputStream; import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.Properties; /** 基于Druid连接池的工具类 */ public class JDBCUtilsDruid { private static DataSource dataSource; static { Properties properties = new Properties(); try { //properties.load(new FileInputStream("src/druid.properties")); //由于JavaWeb和JavaSE的实际工作路径不一样,web的实际工作路径是在out目录下, //因此要使用类加载器来获取文件的真实路径!!! properties.load(JDBCUtilsDruid.class.getClassLoader().getResourceAsStream("druid.properties")); dataSource = DruidDataSourceFactory.createDataSource(properties); } catch (Exception e) { throw new RuntimeException(e); } } public static Connection getConnection() throws SQLException { return dataSource.getConnection(); } public static void close(ResultSet resultSet, Statement statement, Connection connection) { try { if (resultSet != null) { resultSet.close(); } if (statement != null) { statement.close(); } if (connection != null) { connection.close(); } } catch (SQLException e) { throw new RuntimeException(e); } } }
5.Domain层实现 :
现在MySQL中创建一张表user_demo,代码如下 :
CREATE TABLE IF NOT EXISTS `user_demo` ( `id` MEDIUMINT UNSIGNED PRIMARY KEY, `username` VARCHAR(255) NOT NULL DEFAULT '', `password` CHAR(64) NOT NULL, `email` VARCHAR(255) NOT NULL DEFAULT '' ) CHARACTER SET utf8mb3 COLLATE utf8mb3_bin ENGINE INNODB; INSERT INTO user_demo VALUES (1, 'Cyan', MD5(233), 'WangwuEX@outlook.com'), (2, 'Rain', MD5(111), 'Rain@rain.com'), (3, 'Five', MD5(141), 'Five@five.com'), (4, 'Ice', MD5(555), 'Ice@ice.com'), (5, 'Kyrie', MD5(666), 'Kyrie@irving.com'); SELECT * FROM `user_demo`;
user_demo表的效果如下 :
编辑
创建对应的User类(注意字段的顺序要和表中的保持一致),User类代码如下 :
package javabean; /** * @author : Cyan_RA9 * @version : 21.0 * @function : user_demo表对应的JavaBean类 */ public class User { private Integer id; private String username; private String password; private String email; public User() { //供反射使用 } public User(Integer id, String username, String password, String email) { this.id = id; this.username = username; this.password = password; this.email = email; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } @Override public String toString() { return "User{" + "id=" + id + ", username='" + username + '\'' + ", password='" + password + '\'' + ", email='" + email + '\'' + '}'; } }
6.DAO层实现 :
BasicDAO代码如下 :
package dao; import utils.JDBCUtilsDruid; import org.apache.commons.dbutils.QueryRunner; import org.apache.commons.dbutils.handlers.BeanHandler; import org.apache.commons.dbutils.handlers.BeanListHandler; import org.apache.commons.dbutils.handlers.ScalarHandler; import java.sql.Connection; import java.sql.SQLException; import java.util.List; /** BasicDAO类,完成所有DAO通用的crud操作。 */ public class BasicDAO<T> { private QueryRunner queryRunner = new QueryRunner(); public int update(String sql, Object... params) { int affectedRows = 0; Connection connection = null; try { connection = JDBCUtilsDruid.getConnection(); affectedRows = queryRunner.update(connection,sql,params); return affectedRows; } catch (SQLException e) { throw new RuntimeException(e); } finally { JDBCUtilsDruid.close(null, null, connection); } } public List<T> queryMultiply(String sql, Class<T> clazz, Object... params) { Connection connection = null; try { connection = JDBCUtilsDruid.getConnection(); List<T> query = queryRunner.query(connection,sql,new BeanListHandler<T>(clazz),params); return query; } catch (SQLException e) { throw new RuntimeException(e); } finally { JDBCUtilsDruid.close(null, null, connection); } } public T querySingle(String sql, Class<T> clazz, Object... params) { Connection connection = null; try { connection = JDBCUtilsDruid.getConnection(); return queryRunner.query(connection, sql, new BeanHandler<T>(clazz), params); } catch (SQLException e) { throw new RuntimeException(e); } finally { JDBCUtilsDruid.close(null, null, connection); } } public Object queryScalar(String sql, Object... params) { Connection connection = null; try { connection = JDBCUtilsDruid.getConnection(); return queryRunner.query(connection, sql, new ScalarHandler<>(), params); } catch (Exception e) { throw new RuntimeException(e); } finally { JDBCUtilsDruid.close(null,null,connection); } } }
UserDAO类代码如下 :
package dao; import javabean.User; /** * @author : Cyan_RA9 * @version : 21.0 */ public class UserDAO extends BasicDAO<User>{ }
7.Service层实现 :
UserService类, 代码如下 :
package service; import dao.UserDAO; import javabean.User; public class UserService { private UserDAO userDAO = new UserDAO(); public User getUserByName(String username) { String sql = "SELECT * FROM user_demo WHERE username = ?"; User user = userDAO.querySingle(sql, User.class, username); return user; } }
8.运行测试 :
启动Tomcat,进行测试,测试结果如下GIF图所示 :
编辑
三、JQuery操作Ajax
1 $.ajax({})函数 :
$.ajax函数的常用参数如下——
(1) url : 请求的地址
(2) type : 请求的方式GET or POST
(3) data : 发送到服务器端的数据,将自动转换为请求字符串格式
(4) success : 成功的回调函数
(5) dataType : 返回的数据类型,常用Json或text。
PS : 注意$.ajax({}) 的使用格式,不可以直接写参数,需要属性名 : 来约束。
2 $.get()和$.post()函数 :
$.get函数 和 $.post函数的常用参数如下——
(1) url : 请求的地址
(2) data : 发送到服务器端的数据,将自动转换为请求字符串格式
(3) success : 成功的回调函数
(4) dataType : 返回的数据类型,常用Json或text。
PS1 : $.get() 和 $.post() 底层还是使用$.ajax({})函数来实现异步请求。
PS2 : $.get() 和 $.post() 可以直接传入参数,但要注意顺序问题!
3 $.getJSON()函数 :
$.getJSON函数的常用参数如下——
(1) url : 请求的地址
(2) data : 发送到服务器端的数据,将自动转换为请求字符串格式
(3) success : 成功的回调函数
PS : $.getJSON() 底层还是使用$.ajax()函数来实现异步请求。
System.out.println("END------------------------------------------------");