17. 数据交换和异步请求 - JSON & Ajax

文章目录


17.1 官方文档

17.1.1 JSon 在线文档:https://www.w3school.com.cn/js/js_json_intro.asp.

17.1.2 Ajax 在线文档:https://www.w3school.com.cn/js/js_ajax_intro.asp.

17.1.3 离线文档: W3School 离线手册(2017.03.11 版).chm

17.2 JSON 介绍

  1. JSON 指的是 JavaScript 对象表示法 (JavaScript Object Notation)
  2. JSON 是轻量级的文本数据交换格式
  3. JSON 独立于语言 (解读:即 java 、php、asp.net , go 等都可以使用 JSON)
  4. JSON 具有自我描述性,更易理解,一句话,非常的好用…

17.3 JSON 快速入门

  1. JSON 的定义格式
var 变量名 = { 
"k1" : value, // Number 类型
"k2" : "value", // 字符串类型
"k3" : [],// 数组类型
"k4" : {}, // json 对象类型
"k5" : [{},{}] // json 数组
};
var myJson = { 
"key1": "谢家升", // 字符串
"key2": 123, // Number 
"key3":[1,"hello", 2.3], // 数组
"key4": { "age" : 12, "name" :"jack" }, //json 对象
"key5": [ //json 数组
{ "k1" : 10, "k2" : "milan" },
{ "k3" : 30, "k4" : "smith" }
]};
  1. 解读 JSON 规则

    ① 映射(元素/属性)用冒号 : 表示,“名称”:值 ,注意名称是字符串,因此要用双引号引起来
    ② 并列的数据之间用逗号 , 分隔。"名称 1":值,"名称 2":值
    ③ 映射的集合(对象)用大括号 {} 表示。{"名称 1":值,"名称 2":值}
    ④ 并列数据的集合(数组)用方括号 [] 表示。 [{"名称 1":值,"名称 2":值}, {"名称 1":值," 名称 2":值}]
    ⑤ 元素值类型:string, number, object, array, true, false, null

  2. JSON 快速入门:创建 json_quick_start.html

在这里插入图片描述


<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>json快速入门</title>
    <script type="text/javascript">

        window.onload = function () {

            /*
            解读:
            1.myJson 就是一个json对象
            2.演示如何获取到json对象的各个属性/key
             */
            var myJson = {
                "key1": "谢家升",  //字符串
                "key2": 123,  //Number
                "key3": [1, "hello", 2.3],  //数组
                "key4": {"age": 23, "name": "jack"}, //json对象
                "key5": [  //json数组
                    {"k1": 10, "k2": "milan"},
                    {"k3": 20, "k4": "smith"}
                ]
            };

            //1.取出key1
            console.log("key1= ", myJson.key1);
            //2.取出key3
            console.log("key3= ", myJson.key3);
            // 可以对key3取出的值(Array), 进行遍历
            for (let i = 0; i < myJson.key3.length; i++) {
                console.log("第%i个元素的值= ", i, myJson.key3[i]);
            }

            //3.取出key4
            console.log("key4= ", myJson.key4, "name= ", myJson.key4.name);
            //4.取出key5
            console.log("key5= ", myJson.key5, "k4= ", myJson.key5[1].k4);

        }

    </script>
</head>
<body>
<h1>json 快速入门案例</h1>
</body>
</html>

17.4 JSON 对象和字符串对象转换

17.4.1 应用案例

  1. JSON.stringify(json) 功能:将一个 json 对象转换成为 json 字符串
  2. JSON.parse( jsonString)功能:将一个 json 字符串转换成为 json 对象
  3. 应用实例 创建 json_str.html

在这里插入图片描述


<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>JSON对象和字符串对象转换</title>
    <script type="text/javascript">
        window.onload = function () {
            //解读 JSON
            //1. JSON 是一个JS的内置对象(built-in), 可以直接使用
            console.log("JSON= ", JSON);

            //演示如何将一个json对象 --> String
            var jsonPerson = {
                "name": "jack",
                "age": 20
            }

            console.log("jsonPerson= ", jsonPerson);
            var strPerson = JSON.stringify(jsonPerson);
            console.log("strPerson= ", strPerson, " strPerson类型= ", typeof strPerson);

            //演示如何将一个 String --> json对象
            //注意:要转成json对象的 string,必须满足json格式
            var strDog = "{\"name\":\"小黄狗\",\"age\":2}";
            var jsonDog = JSON.parse(strDog);
            console.log("jsonDog= ", jsonDog, " jsonDog= ", typeof jsonDog);

        }
    </script>
</head>
<body>
<h1>JSON对象和字符串对象转换</h1>
</body>
</html>

17.4.2 注意事项和细节

  1. JSON.springify(json 对象) 会返回对应 string, 并不会影响 原来 json 对象,演示 json_string_detail.html

  2. JSON.parse(string) 函数会返回对应的 json 对象,并不会影响原来 string

  3. 在定义 Json 对象时, 可以使用 ' ' 表示字符串

    比如 var json_person = {"name": "jack", "age": 100};
    也可以写成 var json_person = {'name': 'jack', 'age': 100};

  4. 但是在把原生字符串转成 json 对象时,必须使用双引号 “”, 否则会报错 比如:var str_dog = "{'name':'小黄狗', 'age': 4}"; 转 json 就会报错

  5. JSON.springify(json 对象) 返回的字符串,都是 "" 表示的字符串,所以在语法格式正确的情况下,是可以重新转成 json 对象的

在这里插入图片描述


<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>json和字符串转换的注意事项和细节</title>
    <script type="text/javascript">

        window.onload = function () {

            var jsonPerson = {
                "name": "jack",
                "age": 20
            }

            //1. JSON.stringify(json对象) 会返回对应string, 并不会影响原来json对象
            //   可以这样理解 java基础 int n = 10; double n2 = (double)n;
            var strPerson = JSON.stringify(jsonPerson);
            console.log("jsonPerson= ", jsonPerson);

            //2. JSON.parse(string) 函数会返回对应的json对象, 并不会影响原来string

            var strDog = "{\"name\":\"小黄狗\", \"age\":2}";
            var jsonDog = JSON.parse(strDog);
            console.log("strDog=", strDog, " 类型= ", typeof strDog);

            //3. 在定义Json对象时, 可以使用 ' ' 表示字符串
            //   前面的key 可以不用" " 或者 ' '

            var jsonPerson2 = {
                name: 'jack',
                age: 20
            }
            console.log("jsonPerson2=", jsonPerson2);

            //4. 但是在把原生字符串转成 json对象时, 必须使用 "" , 否则会报错 比如
            //   工作时,非常容易错
            var strDog3 = "{\"name\":\"小黄狗~\", \"age\": 4}";
            JSON.parse(strDog3);

            //5. JSON.stringify(json对象) 返回的字符串, 都是 "" 表示的字符串
            var strPerson2 = JSON.stringify(jsonPerson2);
            var parse = JSON.parse(strPerson2);
            console.log("parse=", parse);

        }

    </script>
</head>
<body>
<h1>json和字符串转换的注意事项和细节</h1>
</body>
</html>

17.5 JSON 在 java 中使用

17.5.1 说明

  1. java 中使用 json,需要引入到第 3 方的包 gson.jar
  2. Gson 是 Google 提供的用来在 Java 对象和 JSON 数据之间进行映射的 Java 类库
  3. 可以对 JSON 字符串 和 Java 对象相互转换

在这里插入图片描述

17.5.2 JSON 在 Java 中应用场景

  1. Javabean 对象和 json 字符串 的转换
  2. List 对象和 json 字符串 的转换
  3. map 对象和 json 字符串 的转换
  4. 应用场景示意图

在这里插入图片描述


17.5.3 应用实例 JavaJson.java Book.java

  1. 演示 json 在 java 程序的使用
  2. 创建 Book.java
package com.xjs.json;

/**
 * @Author: 谢家升
 * @Date: 2022/3/24-03-24-17:10
 * @Version: 1.0
 */
public class Book {
    private Integer id;
    private String name;

    public Book(Integer id, String name) {
        this.id = id;
        this.name = name;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "Book{" +
                "id=" + id +
                ", name='" + name + '\'' +
                '}';
    }
}

  1. 创建 JavaJson.java
package com.xjs.json;

import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;

import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @Author: 谢家升
 * @Date: 2022/3/24-03-24-17:12
 * @Version: 1.0
 */
public class JavaJson {
    public static void main(String[] args) {

        //创建一个 gson 对象,作为一个工具对象使用
        Gson gson = new Gson();

        //演示javabean 和 json 字符串的转换
        Book book = new Book(1, "我亦无他,惟手熟尔");

        //1.演示把 javabean --> json字符串
        String strBook = gson.toJson(book);
        System.out.println("strBook= " + strBook);

        //2.json字符串 --> javabean
        Book book2 = gson.fromJson(strBook, Book.class);
        System.out.println("book2= " + book2);

        //3.演示把 List对象 --> json字符串
        List<Book> bookList = new ArrayList<>();
        bookList.add(new Book(100,"天龙八部"));
        bookList.add(new Book(200,"神雕侠侣"));

        //解读:因为把对象,集合转成字符串,相对简单
        //底层只需要遍历,按照json格式拼接返回即可
        String strBookList = gson.toJson(bookList);
        System.out.println("strBookList= " + strBookList);

        //4.演示把 json字符串 --> List对象
        //解读:
        //(1) 如果需要把 json字符串 转成 集合 这样复杂的类型,需要使用 gson 提供的一个类
        //(2) TypeToken , 是一个自定义泛型类,然后通过 TypeToken 来指定我们需要转换成的类型
        /*
        package com.google.gson.reflect;

        public class TypeToken<T> {
            final Class<? super T> rawType;
            final Type type;
            final int hashCode;

            protected TypeToken() {
                this.type = getSuperclassTypeParameter(this.getClass());
                this.rawType = Types.getRawType(this.type);
                this.hashCode = this.type.hashCode();
        }
         */
        //解读 TypeToken
        //(1) type 返回类型的完整路径 java.util.List<com.xjs.json.Book>
        //(2) gson 的设计者,需要得到类型的完整路径,然后进行底层反射
        //(3) 所以 gson 的设计者就提供了 TypeToken,来搞定

        //二说 TypeToken 为什么要加 {}
        //(1) 如果我们这样写:new TypeToken<List<Book>>() 后面没有 {} 会报错:
        //    TypeToken()' has protected access in 'com.google.gson.reflect.TypeToken
        //(2) 因为我们 TypeToken 的无参构造器是 protected , 而 new TypeToken<List<Book>>() 就是
        //    调用其无参构造器
        //(3) 根据Java基础,如果一个方法 protected,而且不再同一个包,是不能直接访问的
        //(4) 为什么 new TypeToken<List<Book>>() {} 使用就可以呢? 因为这里就涉及到匿名内部类的知识
        //(5) 当 new TypeToken<List<Book>>() {} 其实这个类型已经不是 TypeToken 而是一个匿名内部类(可以理解为TypeToken的子类)
        //(6) 而且这个匿名内部类是有自己的无参构造器(隐式),根据Java基础规则,当执行子类的无参构造器时,默认会 super()

        //三说 TypeToken --> 举一个例子【对Java基础的回顾】
        Type type = new TypeToken<List<Book>>() { }.getType();
        //System.out.println(type.getClass());//com.google.gson.internal.$Gson$Types$ParameterizedTypeImpl
        //System.out.println("type= " + type);
        //type= java.util.List<com.xjs.json.Book>

        List<Book> bookList2 = gson.fromJson(strBookList, type);
        System.out.println("bookList2= " + bookList2);

        //5.演示把 Map对象 --> json字符串
        Map<String, Book> bookMap = new HashMap<>();
        bookMap.put("k1", new Book(300,"射雕英雄传"));
        bookMap.put("k2", new Book(400,"笑傲江湖"));

        String strBookMap = gson.toJson(bookMap);
        System.out.println("strBookMap= " + strBookMap);

        //6.演示一把 json字符串 --> Map对象
        
        Map<String,Book> bookMap2 = gson.fromJson(strBookMap, new TypeToken<Map<String, Book>>() {}.getType());
        System.out.println("bookMap2= " + bookMap2);


    }
}

  1. 完成测试,控制台输出如下:

在这里插入图片描述

  1. 举一个案例帮助理解 TypeToken

在这里插入图片描述

  • 目录结构如图所示,在 t1 包下创建 A.java
package com.xjs.t1;

/**
 * @Author: 谢家升
 * @Date: 2022/3/24-03-24-18:38
 * @Version: 1.0
 */
public class A<T> {

    protected A() {//受保护的无参构造器
        System.out.println("A的 protected A()");
    }
}

  • 目录结构如图所示,在 t2 包下创建 Test.java
package com.xjs.t2;

import com.xjs.t1.A;

/**
 * @Author: 谢家升
 * @Date: 2022/3/24-03-24-18:39
 * @Version: 1.0
 */
public class Test {
    public static void main(String[] args) {
        //直接调用A类的 protected 无参构造器会报错,因为不在一个包
        //提示:'A()' has protected access in 'com.xjs.t1.A'
        //思路梳理:
        //(1) 因为 A类和 Test类 不在同一个包
        //(2) 就不能访问 A类的 protected 的方法,包括构造器
        //(3) A<String>() {} 就是一个匿名内部类,可以理解成A类的子类
        //(4) A<String>() {} 这个匿名内部类,有一个隐式的无参构造器,根据Java基础,无参构造器 有默认 super()
        //(5) 当你执行 new A<String>() {}  会调用到A类的无参的 protected 构造器
        //(6) 感谢老韩,讲的透彻~~此乃传道授业解惑也,辛苦啦!!!
        A a = new A<String>() {};
        System.out.println(a.getClass());//class com.xjs.t2.Test$1
    }
}

17.6 Ajax 基本介绍

17.6.1 Ajax 是什么

  1. AJAX 即"Asynchronous Javascript And XML"(异步 JavaScript 和 XML)
  2. Ajax 是一种浏览器异步发起请求(指定发哪些数据),局部更新页面的技术
  3. 传统的方式

在这里插入图片描述

17.6.2 Ajax 经典应用场景

  1. 搜索引擎根据用户输入关键字,自动提示检索关键字
  2. 动态加载数据,按需取得数据【树形菜单、联动菜单…】
  3. 改善用户体验。【输入内容前提示、带进度条文件上传…】
  4. 电子商务应用。 【购物车、邮件订阅…】
  5. 访问第三方服务。【访问搜索服务、rss 阅读器】
  6. 页面局部刷新, https://piaofang.maoyan.com/dashboard

在这里插入图片描述


在这里插入图片描述

17.7 Ajax 原理示意图

17.7.1 传统的 WEB 应用

● 一图胜千言

在这里插入图片描述


17.7.2 Ajax 原理示意图

● 一图胜千言

在这里插入图片描述


17.8 JavaScript 原生 Ajax 请求

17.8.1 Ajax 文档

17.8.1.1 在线文档:https://www.w3school.com.cn/js/js_ajax_intro.asp
17.8.1.2 离线文档:W3School 离线手册(2017.03.11 版).chm

17.8.2 应用实例-验证用户名是否存在

  1. 演示 javascript 发送原生 ajax 请求的案例

    ① 在输入框输入用户名
    ② 点击验证用户名,使用 ajax 方式,服务端验证该用户名是否已经占用了
    ③ 如果该用户已经占用,以 json 格式返回该用户信息
    ④ 假定用户名为 king ,就不可用,其它用户名可以 => 后面我们接入 DB[Mysql+JDBC]
    ⑤ 对页面进行局部刷新,显示返回信息
    ⑥ 小思考: 为什么直接返回用户名是否可用信息,完成案例后,再思考?

在这里插入图片描述


  • 思路分析 => 程序框架图(画出框架图)-> 先思路-> 走代码

在这里插入图片描述


  1. 创建 User.java
package com.xjs.entity;

/**
 * @Author: 谢家升
 * @Date: 2022/3/26-03-26-18:37
 * @Version: 1.0
 */

/**
 * User类就是一个 javabean / pojo / domain
 */
public class User {
    private Integer id;
    private String username;
    private String email;
    private String pwd;

    public User(Integer id, String username, String email, String pwd) {
        this.id = id;
        this.username = username;
        this.email = email;
        this.pwd = pwd;
    }

    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 getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public String getPwd() {
        return pwd;
    }

    public void setPwd(String pwd) {
        this.pwd = pwd;
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", username='" + username + '\'' +
                ", email='" + email + '\'' +
                ", pwd='" + pwd + '\'' +
                '}';
    }
}

  1. 创建 UserCheckServlet.java
package com.xjs.servlet;

import com.google.gson.Gson;
import com.xjs.entity.User;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

/**
 * @Author: 谢家升
 * @Date: 2022/3/26-03-26-18:34
 * @Version: 1.0
 */
public class UserCheckServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("UserCheckServlet 被调用...");

        String uname = request.getParameter("uname");
        System.out.println("uname= " + uname);

        response.setContentType("text/html;charset=utf-8");

        //假定用户名为 king,就不能使用,其他用户名可以
        if ("king".equals(uname)) {
            //不能用
            User user = new User(100, uname, "king@qq.com", "666");
            String strUser = new Gson().toJson(user);
            //发给浏览器
            PrintWriter writer = response.getWriter();
            writer.write(strUser);
        } else {
            //可以用,返回 ""
            response.getWriter().write("");
        }


    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doPost(request, response);
    }
}

  1. 创建 login.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>用户注册</title>
    <script type="text/javascript">
        window.onload = function () {//页面加载完毕后执行function

            var button = document.getElementById("checkButton");
            button.onclick = function () {//给checkButton绑定onclick

                //1. 创建XMLHttpRequest对象(!!!) [ajax引擎对象]
                var xmlHttpRequest = new XMLHttpRequest();

                //获取用户输入的username
                var uname = document.getElementById("uname").value;

                //2. 准备发送指定数据 open, send
                //解读:
                //(1) "GET" 请求方式可以 GET/POST
                //(2) "/ajax/checkUserServlet?username=" + uname 就是 url
                //(3) true , 表示异步发送
                xmlHttpRequest.open("GET", "/ajax/userCheckServlet?uname=" + uname, true);

                //注意,一定要在send方法前,绑定onreadystatechange事件
                //说明:在send函数调用前,给XMLHttpRequest 绑定一个事件onreadystatechange
                //该事件表示,可以去指定一个函数,当数据变化,会触发onreadystatechange
                // 每当 xhr对象readyState 改变时,就会触发 onreadystatechange 事件
                xmlHttpRequest.onreadystatechange = function() {
                    //如果请求已完成,且响应已就绪, 并且状态码是200
                    if (xmlHttpRequest.readyState == 4  && xmlHttpRequest.status == 200) {
                        //把返回的数据显示在 div 上
                        document.getElementById("div1").innerText = xmlHttpRequest.responseText;

                        //console.log("xmlHttpRequest= ", xmlHttpRequest);
                        var responseText = xmlHttpRequest.responseText;
                        //console.log("返回的信息= ", responseText);
                        // 返回的信息=  {"id":100,"username":"king","email":"king@qq.com","pwd":"666"}
                        if (responseText != "") {
                            //说明不可用
                            document.getElementById("myres").value = "用户名不可用";
                        } else {
                            //说明可用
                            document.getElementById("myres").value = "用户名可用";
                        }
                    }

                }

                //3. 真正的发送ajax请求[http请求]
                // 再次说明:如果你是 POST 请求,在send("发送的数据")
                xmlHttpRequest.send();

            }

        }
    </script>
</head>
<body>
<h1>用户注册~</h1>
<form action="/ajax/userCheckServlet" method="post">
    用户名字:<input type="text" name="username" id="uname">
    <input type="button" id="checkButton" value="验证用户名">
    <input style="border-width: 0;color: red" type="text" id="myres"><br/><br/>
    用户密码:<input type="password" name="password"><br/><br/>
    电子邮件:<input type="text" name="email"><br/><br/>
    <input type="submit" value="用户注册">
</form>
<h1>返回的json数据</h1>
<div id="div1"></div>
</body>
</html>
  1. 完成测试,注意看 FF 抓包

17.8.3 课后作业

17.8.3.1 作业布置

● 需求分析: 到数据库去验证用户名是否可用

  1. 点击验证用户名, 到数据库中验证用户名是否可用
  2. 创建数据库 ajaxdb ,创建表 user 表 自己设计(自己试试)
  3. 使用 ajax 方式, 服务端验证该用户名是否已经占用了, 如果该用户已经占用,以 json 格式返回该用户信息
  4. 对页面进行局部刷新,显示返回信息
  5. 只需要再前面的应用实例中,进行升级, 接入 DB
  6. 提示: java 基础【Mysql+JDBC+数据库连接池 => 满汉楼项目】

在这里插入图片描述


● 思路分析(程序框架图)

在这里插入图片描述


17.8.3.2 作业完成
1. 创建数据库和表
-- 使用指令创建数据库
CREATE DATABASE ajax;
USE ajax;

-- 创建表
CREATE TABLE `user` (
	id INT PRIMARY KEY,
	`username` VARCHAR(32) NOT NULL DEFAULT '',
	`email` VARCHAR(32) NOT NULL DEFAULT '',
	`pwd` VARCHAR(32) NOT NULL DEFAULT '')CHARSET utf8 ENGINE INNODB

-- 添加测试数据
INSERT INTO USER VALUES(100,"king","king@qq.com",MD5('666'));
INSERT INTO USER VALUES(200,"tom","tom@qq.com",MD5('123'));
INSERT INTO USER VALUES(300,"jack","jack@qq.com",MD5('888'));

在这里插入图片描述


2. 导入响应的jar包,从满汉楼项目拷贝

在这里插入图片描述

3. 创建dao包、service包、utils包

在这里插入图片描述

4. 完善代码【思路非常重要,围绕程序框架图】

UserCheckServlet.java => UserService.java => UserDAO.java => 操作数据库

  • 思路是从上到下,而写代码是从下到上
● 工具类

在这里插入图片描述

package com.xjs.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;

/**
 * @author 谢家升
 * @version 1.0
 * 基于druid数据库连接池的工具类
 */
public class JDBCUtilsByDruid {

    private static DataSource ds;

    //在静态代码块完成 ds初始化
    static {
        Properties properties = new Properties();
        try {
            //properties.load(new FileInputStream("src\\druid.properties"));
            //解读:
            //1.目前我们是JavaWeb方式启动
            //2.要获取src目录下的文件,需要使用类加载器
            properties.load(JDBCUtilsByDruid.class.getClassLoader()
                    .getResourceAsStream("druid.properties"));
            ds = DruidDataSourceFactory.createDataSource(properties);
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    //编写getConnection方法
    public static Connection getConnection() throws SQLException {
        return ds.getConnection();
    }

    //关闭连接, 再次强调: 在数据库连接池技术中,close 不是真的断掉连接
    //而是把使用的Connection对象放回连接池
    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);
        }
    }
}

● 配置文件 - druid.properties
#key=value
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/ajax?rewriteBatchedStatements=true
username=root
password=hsp
#initial connection Size
initialSize=10
#min idle connection size
minIdle=5
#max active connection size
maxActive=50
#max wait time (5000 mil seconds)
maxWait=5000
● DAO层 - BasicDAO.java
package com.xjs.dao;


import com.xjs.utils.JDBCUtilsByDruid;
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;

/**
 * @author 谢家升
 * @version 1.0
 * 开发BasicDAO , 是其他DAO的父类
 */
public class BasicDAO<T> { //泛型指定具体类型

    private QueryRunner qr =  new QueryRunner();

    //开发通用的dml方法, 针对任意的表
    public int update(String sql, Object... parameters) {

        Connection connection = null;

        try {
            connection = JDBCUtilsByDruid.getConnection();
            int update = qr.update(connection, sql, parameters);
            return  update;
        } catch (SQLException e) {
           throw  new RuntimeException(e); //将编译异常->运行异常 ,抛出
        } finally {
            JDBCUtilsByDruid.close(null, null, connection);
        }

    }

    //返回多个对象(即查询的结果是多行), 针对任意表

    /**
     *
     * @param sql sql 语句,可以有 ?
     * @param clazz 传入一个类的Class对象 比如 Actor.class
     * @param parameters 传入 ? 的具体的值,可以是多个
     * @return 根据Actor.class 返回对应的 ArrayList 集合
     */
    public List<T> queryMulti(String sql, Class<T> clazz, Object... parameters) {

        Connection connection = null;
        try {
            connection = JDBCUtilsByDruid.getConnection();
            return qr.query(connection, sql, new BeanListHandler<T>(clazz), parameters);

        } catch (SQLException e) {
            throw  new RuntimeException(e); //将编译异常->运行异常 ,抛出
        } finally {
            JDBCUtilsByDruid.close(null, null, connection);
        }

    }

    //查询单行结果 的通用方法
    public T querySingle(String sql, Class<T> clazz, Object... parameters) {

        Connection connection = null;
        try {
            connection = JDBCUtilsByDruid.getConnection();
            return  qr.query(connection, sql, new BeanHandler<T>(clazz), parameters);

        } catch (SQLException e) {
            throw  new RuntimeException(e); //将编译异常->运行异常 ,抛出
        } finally {
            JDBCUtilsByDruid.close(null, null, connection);
        }
    }

    //查询单行单列的方法,即返回单值的方法

    public Object queryScalar(String sql, Object... parameters) {

        Connection connection = null;
        try {
            connection = JDBCUtilsByDruid.getConnection();
            return  qr.query(connection, sql, new ScalarHandler(), parameters);

        } catch (SQLException e) {
            throw  new RuntimeException(e); //将编译异常->运行异常 ,抛出
        } finally {
            JDBCUtilsByDruid.close(null, null, connection);
        }
    }

}

● DAO层 - UserDAO.java【切记无参构造器!!!】
package com.xjs.entity;

/**
 * @Author: 谢家升
 * @Date: 2022/3/26-03-26-18:37
 * @Version: 1.0
 */

/**
 * User类就是一个 javabean / pojo / domain
 */
public class User {
    private Integer id;
    private String username;
    private String email;
    private String pwd;

    //必须提供无参构造器,底层反射需要使用


    public User() {
    }

    public User(Integer id, String username, String email, String pwd) {
        this.id = id;
        this.username = username;
        this.email = email;
        this.pwd = pwd;
    }

    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 getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public String getPwd() {
        return pwd;
    }

    public void setPwd(String pwd) {
        this.pwd = pwd;
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", username='" + username + '\'' +
                ", email='" + email + '\'' +
                ", pwd='" + pwd + '\'' +
                '}';
    }
}

● service层 - UserService.java
package com.xjs.service;

import com.xjs.dao.UserDAO;
import com.xjs.entity.User;
import org.junit.Test;

/**
 * @Author: 谢家升
 * @Date: 2022/3/27-03-27-11:19
 * @Version: 1.0
 */

/**
 * UserService 提供业务方法
 */
public class UserService {

    //查询user表, 给 UserDAO 属性
    private UserDAO userDAO = new UserDAO();

    //根据name查询单行信息
    //如果查不到就返回null
    public User getByName(String name) {
        User user = userDAO.querySingle("SELECT * FROM `USER` WHERE username=?", User.class, name);
        return user;
    }



}

● servlet层 - UserCheckServlet.java【稍作修改即可】
package com.xjs.servlet;

import com.google.gson.Gson;
import com.xjs.entity.User;
import com.xjs.service.UserService;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

/**
 * @Author: 谢家升
 * @Date: 2022/3/26-03-26-18:34
 * @Version: 1.0
 */
public class UserCheckServlet extends HttpServlet {

    private UserService userService = new UserService();

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("UserCheckServlet 被调用...");

        String uname = request.getParameter("uname");
        System.out.println("uname= " + uname);

        response.setContentType("text/html;charset=utf-8");

        //假定用户名为 king,就不能使用,其他用户名可以 ---> 使用数据库
        //if ("king".equals(uname)) {
        //    //不能用
        //    User user = new User(100, uname, "king@qq.com", "666");
        //    String strUser = new Gson().toJson(user);
        //    //发给浏览器
        //    PrintWriter writer = response.getWriter();
        //    writer.write(strUser);
        //} else {
        //    //可以用,返回 ""
        //    response.getWriter().write("");
        //}

        //接入数据库
        User user = userService.getByName(uname);
        if (user != null) {
            //说明查到了对应数据,该用户名不可用
            String strUser = new Gson().toJson(user);
            //发送给浏览器
            response.getWriter().write(strUser);
        } else {
            //可用,返回 ""
            response.getWriter().write("");
        }


    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doPost(request, response);
    }
}

● 完成测试
  1. 测试一个可用的用户名

在这里插入图片描述


  1. 测试一个不可用的用户名

在这里插入图片描述


17.9 JQuery 的 Ajax 请求

17.9.1 JQuery Ajax 操作方法

17.9.1.1 在线文档:https://www.w3school.com.cn/jquery/jquery_ajax_get_post.asp

在这里插入图片描述

17.9.1.2 离线文档:W3School 离线手册(2017.03.11 版).chm

17.9.2 $.ajax 方法

  1. $.ajax 常用参数

    ● url: 请求的地址
    ● type : 请求的方式 get 或 post
    ● data : 发送到服务器的数据。将自动转换为请求字符串格式
    ● success: 成功的回调函数
    ● error: 失败后的回调函数
    ● dataType: 返回的数据类型 常用 json 或 text

  2. 说明:完整的参数参看手册

17.9.3 $.get 请求和 $.post 请求

  1. $.get 和 $.post 常用参数

    ● url: 请求的 URL 地址
    ● data: 请求发送到服务器的数据
    ● success: 成功时回调函数
    ● type: 返回内容格式,xml, html, script, json, text

在这里插入图片描述

在这里插入图片描述

  1. 说明:$.get$.post 底层还是使用$.ajax()方法来实现异步请求

17.9.4 $.getJSON

  1. $.getJSON 常用参数

    ● url: 请求发送的哪个 URL
    ● data: 请求发送到服务器的数据
    ● success: 请求成功时运行的函数

在这里插入图片描述

  1. 说明:$.getJSON 底层使用 $.ajax()方法来实现异步请求

17.9.5 应用实例

● 演示 jquery 发送 ajax 请求的案例
  1. 在输入框输入用户名
  2. 点击验证用户名,服务端验证该用户名是否已经占用了,如果该用户已经占用,以 json格式返回该用户信息
  3. 假定用户名为 king ,就不可用,其它用户名可以
  4. 对页面进行局部刷新, 显示返回信息

在这里插入图片描述


  • 简单的思路分析 => 程序框架图 => 直接参考前面的分析图即可

在这里插入图片描述


● 代码实现:
  • 特别提示:别忘了引入 jQuery库
1. 演示 $.ajax 方法 - login2.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>用户注册</title>
    <!--    引入jquery-->
    <script type="text/javascript" src="./script/jquery-3.6.0.min.js"></script>
    <script type="text/javascript">
        $(function () {

            //先给btn1绑定单击事件
            $("#btn1").click(function () {

                /**
                 *解读:
                 * 1. 指定参数时,需要在{}
                 * 2. 给参数时,前面需要指定参数名
                 * 3. dataType: "json" 要求服务器返回的数据格式是json
                 */
                $.ajax({
                    url:"/ajax/userCheckServlet2",
                    type:"GET",
                    data:{//这里我们直接给json, 为啥我要传日期, 为了防止浏览器缓存
                        username:$("#uname").val(),
                        dateTime:new Date()
                    },
                    success:function (data,status,xhr) {
                        //alert("成功...");
                        //实现局部刷新,将后端发来的信息显示处理
                        console.log("data= " ,data);//这里data就是json对象
                        console.log("status= " ,status);
                        console.log("xhr= " ,xhr);
                        //对返回的结果进行处理
                        if (data.id == "-1") {//可用
                            $("#myres").val("用户名可用");
                        } else {
                            $("#myres").val("用户名不可用");
                        }
                        var strUser = JSON.stringify(data);
                        $("#div1").html(strUser);
                    },
                    error:function () {//失败后的回调函数
                        alert("失败...");
                    },
                    dataType:"json"
                })




            })

        })
    </script>
</head>
<body>
<h1>用户注册-Jquery+Ajax</h1>
<form action="/ajax/userCheckServlet2" method="post">
    用户名字:<input type="text" name="username" id="uname">
    <input type="button" id="btn1" value="验证用户名">
    <input style="border-width: 0;color: red" type="text" id="myres"><br/><br/>
    用户密码:<input type="password" name="password"><br/><br/>
    电子邮件:<input type="text" name="email"><br/><br/>
    <input type="submit" id="submit" value="用户注册">
</form>
<h1>返回的json数据</h1>
<div id="div1"></div>
</body>
</html>
2. 演示 $.get 请求 - login2.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>用户注册</title>
    <!--    引入jquery-->
    <script type="text/javascript" src="./script/jquery-3.6.0.min.js"></script>
    <script type="text/javascript">
        $(function () {

            //先给btn1绑定单击事件
            $("#btn1").click(function () {


                //===========================================
                //演示 $.get 请求方式
                //说明:
                //1.$.get() 默认是get请求,不需要指定 请求方式
                //2.不需要指定参数名
                //3.填写的实参,是顺序 url, data, success回调函数, 返回的数据格式
                $.get(
                    "/ajax/userCheckServlet2",
                    {
                        username: $("#uname").val(),
                        dateTime: new Date()
                    },
                    function (data, status, xhr) {
                        //alert("成功...");
                        //实现局部刷新,将后端发来的信息显示处理
                        console.log("data= ", data);//这里data就是json对象
                        console.log("status= ", status);
                        console.log("xhr= ", xhr);
                        //对返回的结果进行处理
                        if (data.id == "-1") {//可用
                            $("#myres").val("用户名可用");
                        } else {
                            $("#myres").val("用户名不可用");
                        }
                        var strUser = JSON.stringify(data);
                        $("#div1").html(strUser);
                    },
                    "json"
                )


            })

        })
    </script>
</head>
<body>
<h1>用户注册-Jquery+Ajax</h1>
<form action="/ajax/userCheckServlet2" method="post">
    用户名字:<input type="text" name="username" id="uname">
    <input type="button" id="btn1" value="验证用户名">
    <input style="border-width: 0;color: red" type="text" id="myres"><br/><br/>
    用户密码:<input type="password" name="password"><br/><br/>
    电子邮件:<input type="text" name="email"><br/><br/>
    <input type="submit" id="submit" value="用户注册">
</form>
<h1>返回的json数据</h1>
<div id="div1"></div>
</body>
</html>
3. 演示 $.post 请求 - login2.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>用户注册</title>
    <!--    引入jquery-->
    <script type="text/javascript" src="./script/jquery-3.6.0.min.js"></script>
    <script type="text/javascript">
        $(function () {

            //先给btn1绑定单击事件
            $("#btn1").click(function () {

                //===========================================
                //演示 $.post 请求方式
                //说明: $.post() 和 $.get() 的方式一样
                //只是这时,是按照post方式发送ajax请求
                $.post(
                    "/ajax/userCheckServlet2",
                    {
                        username: $("#uname").val(),
                        dateTime: new Date()
                    },
                    function (data, status, xhr) {
                        //alert("成功...");
                        //实现局部刷新,将后端发来的信息显示处理
                        console.log("data= ", data);//这里data就是json对象
                        console.log("status= ", status);
                        console.log("xhr= ", xhr);
                        //对返回的结果进行处理
                        if (data.id == "-1") {//可用
                            $("#myres").val("用户名可用");
                        } else {
                            $("#myres").val("用户名不可用");
                        }
                        var strUser = JSON.stringify(data);
                        $("#div1").html(strUser);
                    },
                    "json"
                )

            })

        })
    </script>
</head>
<body>
<h1>用户注册-Jquery+Ajax</h1>
<form action="/ajax/userCheckServlet2" method="post">
    用户名字:<input type="text" name="username" id="uname">
    <input type="button" id="btn1" value="验证用户名">
    <input style="border-width: 0;color: red" type="text" id="myres"><br/><br/>
    用户密码:<input type="password" name="password"><br/><br/>
    电子邮件:<input type="text" name="email"><br/><br/>
    <input type="submit" id="submit" value="用户注册">
</form>
<h1>返回的json数据</h1>
<div id="div1"></div>
</body>
</html>
4. 演示 $.getJSON - login2.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>用户注册</title>
    <!--    引入jquery-->
    <script type="text/javascript" src="./script/jquery-3.6.0.min.js"></script>
    <script type="text/javascript">
        $(function () {

            //先给btn1绑定单击事件
            $("#btn1").click(function () {
                //===========================================
                //演示 $.getJSON 请求方式
                //说明:
                //1. 如果你通过jquery发出的ajax请求是get 并且 返回的数据格式是json
                //2. 可以直接使用getJSON() 函数,就很简洁
                $.getJSON(
                    "/ajax/userCheckServlet2",
                    {
                        username:$("#uname").val(),
                        dateTime: new Date()
                    },
                    function (data, status, xhr) {
                        //alert("成功...");
                        //实现局部刷新,将后端发来的信息显示处理
                        console.log("data= ", data);//这里data就是json对象
                        console.log("status= ", status);
                        console.log("xhr= ", xhr);
                        //对返回的结果进行处理
                        if (data.id == "-1") {//可用
                            $("#myres").val("用户名可用");
                        } else {
                            $("#myres").val("用户名不可用");
                        }
                        var strUser = JSON.stringify(data);
                        $("#div1").html(strUser);
                    }
                )

            })

        })
    </script>
</head>
<body>
<h1>用户注册-Jquery+Ajax</h1>
<form action="/ajax/userCheckServlet2" method="post">
    用户名字:<input type="text" name="username" id="uname">
    <input type="button" id="btn1" value="验证用户名">
    <input style="border-width: 0;color: red" type="text" id="myres"><br/><br/>
    用户密码:<input type="password" name="password"><br/><br/>
    电子邮件:<input type="text" name="email"><br/><br/>
    <input type="submit" id="submit" value="用户注册">
</form>
<h1>返回的json数据</h1>
<div id="div1"></div>
</body>
</html>
5. login2.html 完整代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>用户注册</title>
    <!--    引入jquery-->
    <script type="text/javascript" src="./script/jquery-3.6.0.min.js"></script>
    <script type="text/javascript">
        $(function () {

            //先给btn1绑定单击事件
            $("#btn1").click(function () {

                /**
                 *解读:
                 * 1. 指定参数时,需要在{}
                 * 2. 给参数时,前面需要指定参数名
                 * 3. dataType: "json" 要求服务器返回的数据格式是json
                 */
                // $.ajax({
                //     url:"/ajax/userCheckServlet2",
                //     type:"GET",
                //     data:{//这里我们直接给json, 为啥我要传日期, 为了防止浏览器缓存
                //         username:$("#uname").val(),
                //         dateTime:new Date()
                //     },
                //     success:function (data,status,xhr) {
                //         //alert("成功...");
                //         //实现局部刷新,将后端发来的信息显示处理
                //         console.log("data= " ,data);//这里data就是json对象
                //         console.log("status= " ,status);
                //         console.log("xhr= " ,xhr);
                //         //对返回的结果进行处理
                //         if (data.id == "-1") {//可用
                //             $("#myres").val("用户名可用");
                //         } else {
                //             $("#myres").val("用户名不可用");
                //         }
                //         var strUser = JSON.stringify(data);
                //         $("#div1").html(strUser);
                //     },
                //     error:function () {//失败后的回调函数
                //         alert("失败...");
                //     },
                //     dataType:"json"
                // })

                //===========================================
                //演示 $.get 请求方式
                //说明:
                //1.$.get() 默认是get请求,不需要指定 请求方式
                //2.不需要指定参数名
                //3.填写的实参,是顺序 url, data, success回调函数, 返回的数据格式
                // $.get(
                //     "/ajax/userCheckServlet2",
                //     {
                //         username: $("#uname").val(),
                //         dateTime: new Date()
                //     },
                //     function (data, status, xhr) {
                //         //alert("成功...");
                //         //实现局部刷新,将后端发来的信息显示处理
                //         console.log("data= ", data);//这里data就是json对象
                //         console.log("status= ", status);
                //         console.log("xhr= ", xhr);
                //         //对返回的结果进行处理
                //         if (data.id == "-1") {//可用
                //             $("#myres").val("用户名可用");
                //         } else {
                //             $("#myres").val("用户名不可用");
                //         }
                //         var strUser = JSON.stringify(data);
                //         $("#div1").html(strUser);
                //     },
                //     "json"
                // )

                //===========================================
                //演示 $.post 请求方式
                //说明: $.post() 和 $.get() 的方式一样
                //只是这时,是按照post方式发送ajax请求
                // $.post(
                //     "/ajax/userCheckServlet2",
                //     {
                //         username: $("#uname").val(),
                //         dateTime: new Date()
                //     },
                //     function (data, status, xhr) {
                //         //alert("成功...");
                //         //实现局部刷新,将后端发来的信息显示处理
                //         console.log("data= ", data);//这里data就是json对象
                //         console.log("status= ", status);
                //         console.log("xhr= ", xhr);
                //         //对返回的结果进行处理
                //         if (data.id == "-1") {//可用
                //             $("#myres").val("用户名可用");
                //         } else {
                //             $("#myres").val("用户名不可用");
                //         }
                //         var strUser = JSON.stringify(data);
                //         $("#div1").html(strUser);
                //     },
                //     "json"
                // )

                //===========================================
                //演示 $.getJSON 请求方式
                //说明:
                //1. 如果你通过jquery发出的ajax请求是get 并且 返回的数据格式是json
                //2. 可以直接使用getJSON() 函数,就很简洁
                $.getJSON(
                    "/ajax/userCheckServlet2",
                    {
                        username:$("#uname").val(),
                        dateTime: new Date()
                    },
                    function (data, status, xhr) {
                        //alert("成功...");
                        //实现局部刷新,将后端发来的信息显示处理
                        console.log("data= ", data);//这里data就是json对象
                        console.log("status= ", status);
                        console.log("xhr= ", xhr);
                        //对返回的结果进行处理
                        if (data.id == "-1") {//可用
                            $("#myres").val("用户名可用");
                        } else {
                            $("#myres").val("用户名不可用");
                        }
                        var strUser = JSON.stringify(data);
                        $("#div1").html(strUser);
                    }
                )

            })

        })
    </script>
</head>
<body>
<h1>用户注册-Jquery+Ajax</h1>
<form action="/ajax/userCheckServlet2" method="post">
    用户名字:<input type="text" name="username" id="uname">
    <input type="button" id="btn1" value="验证用户名">
    <input style="border-width: 0;color: red" type="text" id="myres"><br/><br/>
    用户密码:<input type="password" name="password"><br/><br/>
    电子邮件:<input type="text" name="email"><br/><br/>
    <input type="submit" id="submit" value="用户注册">
</form>
<h1>返回的json数据</h1>
<div id="div1"></div>
</body>
</html>
6. UserCheckServlet2.java
package com.xjs.servlet;

import com.google.gson.Gson;
import com.xjs.entity.User;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * @Author: 谢家升
 * @Date: 2022/3/28-03-28-13:50
 * @Version: 1.0
 */
public class UserCheckServlet2 extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("UserCheckServlet2 被调用... ");
        String username = request.getParameter("username");
        System.out.println("username= " + username);

        response.setContentType("text/json;charset=utf-8");

        //进行验证,假定username是 king,就不可用
        if ("king".equals(username)) {
            //不可用,返回king
            User king = new User(1, "king", "king@qq.com", "000");
            //回复给前端
            Gson gson = new Gson();
            response.getWriter().write(gson.toJson(king));
        } else {
            //可用
            User user = new User(-1, username, "", "");
            //回复给前端
            Gson gson = new Gson();
            response.getWriter().write(gson.toJson(user));
        }
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doPost(request, response);
    }
}

● 测试及些许小细节:

在这里插入图片描述


在这里插入图片描述


在这里插入图片描述

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

要学就学灰太狼

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值