今天这节课主要学习
- 什么是Ajax,Ajax有什么作用
- 通过调用XMLHttpRequest对象实现异步请求
- XMLHttpRequest对象调用的步骤
- 实践:通过异步请求实现对登陆用户的用户名是否在数据库中做实时的查询
这次还是和上次一样,结合晚上实验的内容来回忆今天学习的内容
实验要求:
首先分析完成以上要求的逻辑结构:
由以上分析可知共需要4个文件:首页(index.html)、servlet处理页面(VerityUseryName.java)、数据库操作DAO(userDao.java)、数据库连接(DButil.java)
①首页--index.html
这个页面除了向用户暴露表单之外,还负责Ajax(异步请求)的编写,Ajax通过在JavaScript调用XMLHttpRequest对象来实现
调用XMLHttpRequest对象主要由4个步骤:
- 创建一个XMLHttpRequest -- 该对象专门负责将用户数据以异步请求/通信的方式发送至服务器端,并接收服务器返回的信息和数据(当然这些功能都是通过调用其内部的方法实现的)
xmlrequest = new XMLHttpRequest(); //与Java语法相同,通过关键字与构造方法获取一个XMLHttpRequest对象 只是JavaScript中无数据类型,所以数据类型都是var - 向服务端发送请求(即与后端建立连接)--请求参数包括:①请求方式/②接收请求的地址(一般都是做请求处理的servlet)/③是否使用异步请求
//③一般都是true,因为如果不适应异步的或就没有必要使用AJax -- 使用false时退化为同步请求
xmlrequest.open("GET","verityUserName?un="+uname,true); //这里的servlet地址不要加“/”,否则需要写上servlet的绝对路径 //使用?+键值对传递参数 - 发送请求 -- 即在与服务器端实现连接之后就要向服务器发送对应的请求参数,也就是这个异步请求实现其独特异步请求具体数据功能的地方
xmlrequest.send(null); //serd括号中写入要向后台传递的参数/条件,没有时写"null" -- 参数还可以通过url传递,即通过?将url与传递的参数之间隔开,参数采用键值对的方式(与get请求方式相同) - 处理请求
//状态码一个有5个
xmlrequest.onreadystatechange=callback; //callback为自定义的一个函数,在状态码发生变化时被调用
对应的需要通过判断状态码来判断连接进行的情况,因为上述步骤都是通过调用XMLHttpRequest对象 的内置方法和内置属性来实现异步请求,但是并没有将调用结果返回,所以想要知道调用的情况,还要使用状态码来进行标识。第4步中的onreadystatechange是一个关键字,其调用机制为JavaScript中的事件调用机制,即该事件发生就调用指定的函数运行,而关键字为“readyState”,共5种,在异步请求的过程中状态码将发送5次变化:0-->1-->2-->3-->4
//4表明连接建立完成,请求传到了服务端
if(xmlrequest.readyState==4)
//200表示响应完成,客户端收到了回应
//404表示url出错,500表示服务器异常
if(xmlrequest.status==200)
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
</head>
<body>
Ajax:解释为“异步请求,局部刷新” -- 实现方式:JavaScript<br />
<p>异步:在用户做其他操作的同时,如正在填写表单数据时,使用一个额外的对象(XMLHttpRequest)去与后端进行实时的连接,
并获取我们所需要的一些数据做为该请求对象的返回值
相对来说就是同步:即在用户填写表单完成之后,才将请求绑定至request对象,并一同发送至后方
同步请求&异步请求:二者关系就好像要行军的大部队与提前出发的先遣队相似,先遣队的作用就是为大部队探路,保证大部队能够顺利的前行
异步请求也可以看成是在为同步请求做着准备工作,防止同步请求发生错误/失败(就如注册用户时填写用户名提示“该用户名是否被注册”一样)</p>
<p>总的来说同步请求与异步请求都是对后台DB的访问,所以只要是请求就会消耗后台服务器的资源,但是异步请求占用的资源很小,且可以保证同步请求的正常进行
可以看出是“用空间换时间”的一种做法</p>
<!-- 通过事件触发机制来运行定义好的异步请求,否则写在JavaScript中的代码在每次打开浏览器的时候就会自动运行,这使得定义好的异步请求功能不受控制,这当然是我们不希望看到的 -->
<!-- 因此就将对应的异步请求操作封装为一个function,而触发的条件使用事件触发机制,由此定义的异步请求在JavaScript部分不会制动执行,变得可控 -->
<!-- 红色部分标识的是一个事件,即当点击这个按钮时就执行其后指定的方法 -->
<!-- 单击是onclick,双击是ondoclick -->
<button onclick="ajaxTest()">点击运行AJax异步请求</button>
<!-- 通过异步请求实现对用户注册时用户名是否重复进行检测 -->
<br />
事件--onfocus:获得焦点,即光标选中此处<br />
事件--onblur:失去焦点,即光标移开
<form>
<label>用户名:</label><input type="text" name="uname" onblur="verityUserName()" id="uname"/>
<span id="info"></span><br>
<label>密 码:</label><input type="password" name="upwd" /><br>
<input type="submit" value="登陆" />
</form>
</body>
<!-- JavaScript脚本的位置灵活,但是约定俗成写在bode标签之后-->
<!--且一个页面可以包含多个JavaScript脚本,各个脚本之间是完全对立的,不会出现同名变量这样的冲突-->
<!--但是这也出现了对类的获取必须定义为全局变量,否则一个方法的内部类是不能被其他脚本所共享的-->
<!--JavaScript中的代码只要没写封装进函数中,则浏览器一打开就会自动运行-->
<script>
var xmlrequest = null //声明为全局变量,使得各个function可以共享这个对象
function verityUserName(){ //编写一个验证用户登陆的用户名是否在数据库中的function
//获取用户填写的用户名 -- 找到用户输入用户名的文本框对象,并获取用户输入的值
var uname = document.getElementById("uname").value //通过在全文检索id属性值为uname的元素,获取它,并通过value属性获取用户输入的值(value时HTML中用户可输入的元素特有的属性)
//AJax实现步骤
//1.创建一个XMLHttpRequest -- 该对象专门负责将用户数据以异步请求/通信的方式发送至服务器端,并接收服务器返回的信息和数据(当然这些功能都是通过调用其内部的方法实现的)
xmlrequest = new XMLHttpRequest(); //与Java语法相同,通过关键字与构造方法获取一个XMLHttpRequest对象 只是JavaScript中无数据类型,所以数据类型都是var
//2.向服务端发送请求(即与后端建立连接)--请求参数包括:①请求方式/②接收请求的地址(一般都是做请求处理的servlet)/③是否使用异步请求
//③一般都是true,因为如果不适应异步的或就没有必要使用AJax -- 使用false时退化为同步请求
xmlrequest.open("GET","verityUserName?un="+uname,true); //这里的servlet地址不要加“/”,否则需要写上servlet的绝对路径
//使用?+键值对传递参数
//3.发送请求 -- 即在与服务器端实现连接之后就要向服务器发送对应的请求参数,也就是这个异步请求实现其独特异步请求具体数据功能的地方
xmlrequest.send(null); //serd括号中写入要向后台传递的参数/条件,没有时写"null" -- 参数还可以通过url传递,即通过?将url与传递的参数之间隔开,参数采用键值对的方式(与get请求方式相同)
//4.处理请求
//状态码一个有5个
xmlrequest.onreadystatechange=callback;
}
//定义响应函数
function callback(){ //JavaScript中将public->function,且不再指定函数的返回值,有返回值就返回,没有就算了 -- 所以JavaScript中定义函数就是function 函数名(){函数体}
//readyState:即为步骤4中涉及到的状态码,状态码共有5个
//在Ajax请求与服务端建立连接的过程中,状态码将发送5次变化:0-->1-->2-->3-->4
//当readyState==4时,说明这个异步请求已经与后端都武器建立了连接,且后端服务器回应了响应
//这个函数应该当后端成功收到请求并成功的发出响应时才调用对应的处理内容,所以要对状态码做判断
//状态码用于指示当前客户端与服务器之间的连接状态
//即当后端收到请求并成功的发出响应时才调用对应的处理内容
//4表明连接建立完成,请求传到了服务端
if(xmlrequest.readyState==4){
//200表示响应完成,客户端收到了回应
//404表示url出错,500表示服务器异常
if(xmlrequest.status==200){//j
//alert("测试") //不写分号&alert括号中写字符串,即被双引号引起来 -- 这个函数一般用来做测试
//接收服务器返回的文本
var result=xmlrequest.responseText
//alert(result) //由此弹出的就是test.html的源码
document.getElementById("info").innerText=result
}
}
}
</script>
</html>
当(xmlrequest.readyState==4)与(xmlrequest.status==200)两个条件都满足时,就通过xmlrequest.responseText取servlet传回来的响应值(可以理解为servlet返回来的值默认被xmlrequest对象的responseText属性接收,且存储为String,而我们要显示时只需要将其属性值赋给另外一个变量用于输出即可)
而通过在前面HTML部分定义了一个<span>标签,通过document.getElementById("info").innerText=result来控制其输出(因为innerText属性就是用来设置标签的文本内容的;即先通过get方法获取对应的标签,再通过innerText控制在这个标签范围内输出的文本内容)
② servlet处理页面(VerityUseryName.java)
- 这个servlet通过调用dao实现对DB的操作;
- 再通过Boolean类型的变量flag来控制服务端向客户端回应的内容(通过三目运算符,条件成立,info为第一个字符串的值;反之为第二个字符串的值);
- 最后再通过response.getWriter().write(info)将输出信息送到前端
package com.servlets;
import java.io.IOException;
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 com.dao.userDao;
@WebServlet("/verityUserName")
public class VerityUseryName extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//前端的JavaScript中已经做好了传递参数的准备,只要用户输入就会将参数传到这个servlet进行处理
//首先设置字符编码:请求/回应的字符都要设置
request.setCharacterEncoding("utf-8");
response.setCharacterEncoding("utf-8");
//取出参数
String uname = request.getParameter("un");
userDao dao = new userDao();
boolean flag = dao.verityName(uname);//调用验证方法
String info = flag?"√":"该账号不存在,请重新输入";//三目运算符,条件成立,info为第一个字符串的值;反之为第二个字符串的值
//转发
response.getWriter().write(info);//输出信息到前端
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
③ 数据库操作DAO(userDao.java)
主要复习查询的步骤:
- 连接DB
- 获取预编译对象(传入sql语句)
- 设置缺省参数
- 执行查询,并接收结果集
package com.dao;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import com.utils.DButil;
public class userDao {
private Connection conn = null;
private PreparedStatement ps = null;
private ResultSet rs = null;
public boolean verityName(String uname) {
conn = DButil.getconn();//连接DB
String sql = "select account from users where account=?";
try {
//获取预编译对象
ps=conn.prepareStatement(sql);
//设置参数
ps.setString(1, uname);
//执行查询,并接收结果集
rs = ps.executeQuery();
if(rs.next()) {
return true;
}
} catch (SQLException e) {
e.printStackTrace();
}finally {
DButil.closeDB(conn, ps, rs); //try..catch的完整结构
}
return false;
}
}
④ 数据库连接(DButil.java)
连接数据库的步骤:
- Class.forName(driver);//注册驱动
- conn = DriverManager.getConnection(url, user, password);//获取连接对象
- return conn;//返回连接对象
断开数据库的步骤:(断开的前提是这些对象都是非空)
- 关闭结果集:rs
- 关闭预编译对象:ps
- 断开连接对象:conn
package com.utils;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
//该类用于连接与断开DB
public class DButil {
private static String url = "jdbc:mysql://localhost:3306/ajax";
private static String user = "root";
private static String password = "abc123456789";
private static String driver = "com.mysql.jdbc.Driver";
private static Connection conn = null;
private PreparedStatement ps = null;
private ResultSet rs = null;
//连接DB
public static Connection getconn() {//为了方便调用,所以将这个类定义为静态的,而静态的类里面的属性都必须是静态的,所以上述属性都是静态的
try {
Class.forName(driver);
conn = DriverManager.getConnection(url, user, password);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
System.out.print("连接数据库成功..");
return conn;
}
//关闭DB -- 本质上就是关闭连接/预编译/结果集,关闭顺序:结果集/预编译/连接
public static void closeDB(Connection conn,PreparedStatement ps,ResultSet rs) { //指定要关闭的对象
try {
if(rs!=null) {
rs.close();
}
if(ps!=null) {
ps.close();
}
if(conn!=null) {
conn.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
小结:以上就是本次实验的所有涉及代码与知识点
-
主要学习了什么是异步请求,异步请求有什么用
-
怎么实现异步请求
-
使用XMLHttpRequest对象的4个步骤
-
通过状态码来判断客户端与服务端连接状态
-
通过JavaScript中的事件来触发设置好的函数
-
回顾了对数据库的连接与增删改查
-
新增了断开数据库连接的操作
-
通过以上知识点对用户登陆用户名进行合法性的实时鉴定