一、Ajax快速入门

1.1 AJAX介绍

  • AJAX(Asynchronous JavaScript And XML):异步的 JavaScript 和 XML。
  • 本身不是一种新技术,而是多个技术综合。用于快速创建动态网页。
  • 一般的网页如果需要更新内容,必需重新加载个页面。
  • 而 AJAX 通过浏览器与服务器进行少量数据交换,就可以使网页实现异步更新。也就是在不重新加载整个页面的情况下,对网页的部分内容进行局部更新。
    网页局部更新.png
  • 同步异步对比

ajax介绍.png

1.2 原生JS实现AJAX(了解)

  • 代码实现
    ```java package com.yuwang;

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(“/userServlet”) public class UserServlet extends HttpServlet { @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doGet(req, resp); }

  1. @Override
  2. protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
  3. //设置请求和响应的乱码
  4. req.setCharacterEncoding("UTF-8");
  5. resp.setContentType("text/html;charset=UTF-8");
  6. //1.获取请求参数
  7. String username = req.getParameter("username");
  8. //模拟服务器处理请求需要5秒钟
  9. try {
  10. Thread.sleep(1000);
  11. } catch (InterruptedException e) {
  12. e.printStackTrace();
  13. }
  14. //2.判断姓名是否已注册
  15. if ("zhangsan".equals(username)) {
  16. resp.getWriter().write("<font color='red'>用户名已被占用</font>");
  17. } else {
  18. resp.getWriter().write("<font color='green'>用户名可用</font>");
  19. }

} }

  1. - **html代码**
  2. ```html
  3. <!DOCTYPE html>
  4. <html lang="en">
  5. <head>
  6. <meta charset="UTF-8">
  7. <title>用户注册</title>
  8. </head>
  9. <body>
  10. <form autocomplete="off">
  11. 姓名:<input type="text" id="username">
  12. <span id="uSpan"></span>
  13. <br>
  14. 密码:<input type="text" id="password">
  15. <br>
  16. <input type="submit" value="注册">
  17. </form>
  18. </body>
  19. <script>
  20. //1.为姓名绑定失去焦点事件
  21. document.getElementById("username").onblur = function () {
  22. //2.创建XMLHttpRequest核心对象
  23. let xmlHttp = new XMLHttpRequest();
  24. //3.open(method,url,async) 打开链接
  25. let username = document.getElementById("username").value;
  26. xmlHttp.open("get", "userServlet?username=" + username, true);
  27. // xmlHttp.open("get","userServlet?username=",false);
  28. //4.send(String params) 发送请求
  29. xmlHttp.send();
  30. //5.处理响应
  31. xmlHttp.onreadystatechange = function () {
  32. //判断请求和响应是否成功
  33. if (xmlHttp.readyState == 4 && xmlHttp.status == 200) {
  34. //将响应的数据显示到span标签
  35. document.getElementById("uSpan").innerHTML = xmlHttp.responseText;
  36. }
  37. }
  38. }
  39. </script>
  40. </html>

1.3 原生JS实现AJAX详解

  • 核心对象:XMLHttpRequest
    • 用于在后台与服务器交换数据。可以在不重新加载整个网页的情况下,对网页的某部分进行局部更新。
  • 打开链接:open(method,url,async)
    • method:请求的类型 GET 或 POST。
    • url:请求的资源路径(GET方法需要将参数用?拼接上)。
    • async:true(异步) 或 false(同步)。
  • 发送请求:send(String params)
    • params:请求的参数(POST 专用)。
  • 处理响应:onreadystatechange
    • readyState:0-请求未初始化,1-服务器连接已建立,2-请求已接收,3-请求处理中,4-请求已完成,且响应已就绪。
    • status:200-响应已全部 OK。
  • 获得响应数据形式

    • responseText:获得字符串形式的响应数据。
    • responseXML:获得 XML 形式的响应数据。

      1.4 jQueryuery的GET方式实现AJAX(重点)

  • 核心语法

    • $.get(url,[data],[callback],[type]);
    • []:可省略。
    • url:请求的资源路径。
    • data:发送给服务器端的请求参数,格式可以是key=value,也可以是 js 对象。
    • callback:当请求成功后的回调函数,可以在函数中编写我们的逻辑代码,函数的参数是返回的数据,类型由type指定,如果需要在出错时执行函数,选择通用方式。
    • type:预期的返回数据的类型,取值可以是 xml, html, js, json, text等。
  • 代码实现

    1. <!DOCTYPE html>
    2. <html lang="en">
    3. <head>
    4. <meta charset="UTF-8">
    5. <title>用户注册</title>
    6. </head>
    7. <body>
    8. <form autocomplete="off">
    9. 姓名:<input type="text" id="username">
    10. <span id="uSpan"></span>
    11. <br>
    12. 密码:<input type="password" id="password">
    13. <br>
    14. <input type="submit" value="注册">
    15. </form>
    16. </body>
    17. <script src="js/jQueryuery-3.3.1.min.js"></script>
    18. <script>
    19. //1.为用户名绑定失去焦点事件
    20. $("#username").blur(function () {
    21. let username = $("#username").val();
    22. //2.jQueryuery的GET方式实现AJAX
    23. $.get(
    24. //请求的资源路径
    25. "userServlet",
    26. //请求参数
    27. // {"username":username},
    28. "username=" + username,
    29. //回调函数
    30. function (data) {
    31. //将响应的数据显示到span标签
    32. $("#uSpan").html(data);
    33. },
    34. //响应数据形式
    35. "text"
    36. );
    37. });
    38. </script>
    39. </html>

    1.5 jQueryuery的POST方式实现AJAX(重点)

  • 核心语法:

    • $.post(url,[data],[callback],[type]);
    • []:可省略。
    • url:请求的资源路径。
    • data:发送给服务器端的请求参数,格式可以是key=value,也可以是 js 对象。
    • callback:当请求成功后的回调函数,可以在函数中编写我们的逻辑代码,函数的参数是返回的数据,类型由type指定,如果需要在出错时执行函数,选择通用方式。
    • type:预期的返回数据的类型,取值可以是 xml, html, js, json, text等。
  • 代码实现

    1. <!DOCTYPE html>
    2. <html lang="en">
    3. <head>
    4. <meta charset="UTF-8">
    5. <title>用户注册</title>
    6. </head>
    7. <body>
    8. <form autocomplete="off">
    9. 姓名:<input type="text" id="username">
    10. <span id="uSpan"></span>
    11. <br>
    12. 密码:<input type="password" id="password">
    13. <br>
    14. <input type="submit" value="注册">
    15. </form>
    16. </body>
    17. <script src="js/jQueryuery-3.3.1.min.js"></script>
    18. <script>
    19. //1.为用户名绑定失去焦点事件
    20. $("#username").blur(function () {
    21. let username = $("#username").val();
    22. //2.jQueryuery的POST方式实现AJAX
    23. $.post(
    24. //请求的资源路径
    25. "userServlet",
    26. //请求参数
    27. // {"username":username},
    28. "username=" + username,
    29. //回调函数
    30. function (data) {
    31. //将响应的数据显示到span标签
    32. $("#uSpan").html(data);
    33. },
    34. //响应数据形式
    35. "text"
    36. );
    37. });
    38. </script>
    39. </html>

    1.6 jQueryuery的通用方式实现AJAX(重点)

  • 核心语法:

    • $.ajax(url,[settings])
    • $.ajax({name:value,name:value,…});
    • []:可省略。
    • url:请求的资源路径。
    • async:是否异步请求,true-是,false-否 (默认是 true)。
    • data:发送到服务器的数据,可以是键值对形式,也可以是 js 对象形式。如果值为数组,jQueryuery 将自动为不同值对应同一个名称。如 {foo:[“bar1”, “bar2”]} 转换为 “&foo=bar1&foo=bar2”。
    • type:请求方式,POST 或 GET (默认是 GET)。
    • dataType:预期的返回数据的类型,取值可以是 xml, html, js, json, text等。
    • success:请求成功时调用的回调函数。
    • error:请求失败时调用的回调函数。
  • 代码实现

    1. <!DOCTYPE html>
    2. <html lang="en">
    3. <head>
    4. <meta charset="UTF-8">
    5. <title>用户注册</title>
    6. </head>
    7. <body>
    8. <form autocomplete="off">
    9. 姓名:<input type="text" id="username">
    10. <span id="uSpan"></span>
    11. <br>
    12. 密码:<input type="password" id="password">
    13. <br>
    14. <input type="submit" value="注册">
    15. </form>
    16. </body>
    17. <script src="js/jQueryuery-3.3.1.min.js"></script>
    18. <script>
    19. //1.为用户名绑定失去焦点事件
    20. $("#username").blur(function () {
    21. let username = $("#username").val();
    22. //2.jQueryuery的通用方式实现AJAX
    23. $.ajax({
    24. //请求资源路径
    25. url:"userServlet",
    26. //是否异步
    27. async:true,
    28. //请求参数
    29. data:"username="+username,
    30. //data:{"username":username},
    31. //请求方式
    32. type:"POST",
    33. //数据形式
    34. dataType:"text",
    35. //请求成功后调用的回调函数
    36. success:function (data) {
    37. //将响应的数据显示到span标签
    38. $("#uSpan").html(data);
    39. },
    40. //请求失败后调用的回调函数
    41. error:function () {
    42. alert("操作失败");
    43. }
    44. });
    45. });
    46. </script>
    47. </html>

    1.7 小结

  • AJAX(Asynchronous JavaScript And XML)

    • 异步的 JavaScript 和 XML。
    • 通过浏览器与服务器进行少量数据交换,就可以使网页实现异步更新。也就是在不重新加载整个页面的情况下,对网页的部 分内容进行局部更新。
  • 同步和异步
    • 同步:服务器端在处理过程中,无法进行其他操作。
    • 异步:服务器端在处理过程中,可以进行其他操作。
  • GET 方式实现:$.get();
  • POST 方式实现:$.post();
    • url:请求的资源路径。
    • data:发送给服务器端的请求参数,格式可以是key=value,也可以是 js 对象。
    • callback:当请求成功后的回调函数,可以在函数中编写我们的逻辑代码。
    • type:预期的返回数据的类型,取值可以是 xml, html, js, json, text等。
  • 通用方式实现:$.ajax();

    • url:请求的资源路径。
    • async:是否异步请求,true-是,false-否 (默认是 true)。
    • data:发送到服务器的数据,可以是键值对形式,也可以是 js 对象形式。
    • type:请求方式,POST 或 GET (默认是 GET)。
    • dataType:预期的返回数据的类型,取值可以是 xml, html, js, json, text等。
    • success:请求成功时调用的回调函数。
    • error:请求失败时调用的回调函数。

      二、JSON的处理

      2.1 JSON回顾

  • JSON(JavaScript Object Notation):是一种轻量级的数据交换格式。

  • 它是基于 ECMAScript 规范的一个子集,采用完全独立于编程语言的文本格式来存储和表示数据。
  • 简洁和清晰的层次结构使得 JSON 成为理想的数据交换语言。易于人阅读和编写,同时也易于计算机解析和生成,并有效的 提升网络传输效率。
    json回顾.png
  • 语法格式
    { "k1":obj,"k2": [o1,o2, {"k3":o3} ] } 一定要看外层是{对象}还是[数组]
    [ o1,o2, {"k":v,"k2": [03,04] } ] | 类型 | 语法 | 说明 | | —- | —- | —- | | 对象类型 | {}name:value,name:value,… | name是字符串类型, value可以是任意类型 | | 数组/集合类型 | []value,value,value,… | 其中value是任意类型 | | 混合类型 | =={==name: [{name:value,…},{name:value,…}] } | 对象格式和数组格式可以互相嵌套 |

  • 常用方法
    | 成员方法 | 说明 | | —- | —- | | stringify(对象) | 将指定对象转换为json格式字符串 | | parse(字符串) | 将指定json格式字符串解析成对象 |

2.2 JSON转换工具的介绍

  • 我们除了可以在 JavaScript 中来使用 JSON 以外,在 JAVA 中同样也可以使用 JSON。
  • JSON 的转换工具是通过 JAVA 封装好的一些 JAR 工具包。
  • 可以将 JAVA 对象或集合转换成 JSON 格式的字符串,也可以将 JSON 格式的字符串转成 JAVA 对象。
  • Jackson:开源免费的 JSON 转换工具,SpringMVC 转换默认使用 Jackson。
  • 实现步骤
    1. 导入 jar 包。
    2. 创建核心对象。
    3. 调用方法完成转换。
  • 常用类
    | 类名 | 说明 | | —- | —- | | ObjectMapper | 是Jackson工具包的核心类, 它提供一些方法来实现 JSON 字符串和对象之间的转换 | | TypeReference | 对集合泛型的反序列化,使用 TypeReference 可以明确的指定反序列化的对象类型 |

  • ObjectMapper常用方法
    | 方法名 | 说明 | | —- | —- | | String writeValueAsString(Object obj) | 将Java对象转换成JSON字符串 | | T readValue(String json, Class valueType) | 将JSON字符串转换成Java对象 | | T readValue(String json, TypeReference valueTypeRef) | 将JSON字符串转换成Java对象 |

2.3 JSON转换练习

  • 对象转 JSON, JSON 转对象。

    1. /*
    2. JSON转换工具的使用
    3. */
    4. public class ObjectMapperTest {
    5. private ObjectMapper mapper = new ObjectMapper();
    6. /*
    7. 1.User对象转json, json转User对象
    8. json字符串 = {"name":"张三","age":23}
    9. user对象 = User{name='张三', age=23}
    10. */
    11. @Test
    12. public void test01() throws Exception{
    13. //User对象转json
    14. User user = new User("张三",23);
    15. String json = mapper.writeValueAsString(user);
    16. System.out.println("json字符串:" + json);
    17. //json转User对象
    18. User user2 = mapper.readValue(json, User.class);
    19. System.out.println("java对象:" + user2);
    20. }
    21. }
  • Map转 JSON, JSON 转 Map。

  1. /*
  2. 2.map<String,String>转json, json转map<String,String>
  3. json字符串 = {"姓名":"张三","性别":"男"}
  4. map对象 = {姓名=张三, 性别=男}
  5. */
  6. @Test
  7. public void test02() throws Exception{
  8. //map<String,String>转json
  9. HashMap<String,String> map = new HashMap<>();
  10. map.put("姓名","张三");
  11. map.put("性别","男");
  12. String json = mapper.writeValueAsString(map);
  13. System.out.println("json字符串:" + json);
  14. //json转map<String,String>
  15. HashMap<String,String> map2 = mapper.readValue(json, HashMap.class);
  16. System.out.println("java对象:" + map2);
  17. }
  • Map转 JSON, JSON 转 Map。

    1. /*
    2. 3.map<String,User>转json, json转map<String,User>
    3. json字符串 = {"一班":{"name":"张三","age":23},"二班":{"name":"李四","age":24}}
    4. map对象 = {一班=User{name='张三', age=23}, 二班=User{name='李四', age=24}}
    5. */
    6. @Test
    7. public void test03() throws Exception{
    8. //map<String,User>转json
    9. HashMap<String,User> map = new HashMap<>();
    10. map.put("一班",new User("张三",23));
    11. map.put("二班",new User("李四",24));
    12. String json = mapper.writeValueAsString(map);
    13. System.out.println("json字符串:" + json);
    14. //json转map<String,User>
    15. HashMap<String,User> map2 = mapper.readValue(json,new TypeReference<HashMap<String,User>>(){});
    16. System.out.println("java对象:" + map2);
    17. }
  • List转 JSON, JSON 转 List。

  • List转 JSON, JSON 转 List。

    1. /*
    2. 5.List<User>转json, json转List<User>
    3. json字符串 = [{"name":"张三","age":23},{"name":"李四","age":24}]
    4. list对象 = [User{name='张三', age=23}, User{name='李四', age=24}]
    5. */
    6. @Test
    7. public void test05() throws Exception{
    8. //List<User>转json
    9. ArrayList<User> list = new ArrayList<>();
    10. list.add(new User("张三",23));
    11. list.add(new User("李四",24));
    12. String json = mapper.writeValueAsString(list);
    13. System.out.println("json字符串:" + json);
    14. //json转List<User>
    15. ArrayList<User> list2 = mapper.readValue(json,new TypeReference<ArrayList<User>>(){});
    16. System.out.println("java对象:" + list2);
    17. }

    2.4 小结

  • Jackson:开源免费的 JSON 转换工具,SpringMVC 转换默认使用 Jackson。

  • 可以将 JAVA 对象或集合转换成 JSON 格式的字符串,也可以将 JSON 格式的字符串转成 JAVA 对象。
  • 常用类
  • ObjectMapper

    • TypeReference

      三、综合案例 搜索联想

      3.1 案例效果和环境介绍

      用户搜索案例.jpg

      1. /*
      2. 4.List<String>转json, json转 List<String>
      3. json字符串 = ["张三","李四"]
      4. list对象 = [张三, 李四]
      5. */
      6. @Test
      7. public void test04() throws Exception{
      8. //List<String>转json
      9. ArrayList<String> list = new ArrayList<>();
      10. list.add("张三");
      11. list.add("李四");
      12. String json = mapper.writeValueAsString(list);
      13. System.out.println("json字符串:" + json);
      14. //json转 List<String>
      15. ArrayList<String> list2 = mapper.readValue(json,ArrayList.class);
      16. System.out.println("java对象:" + list2);
      17. }
  • 环境搭建
    用户搜索环境搭建.jpg

  • 数据库搭建
    ```sql — 创建db10数据库 CREATE DATABASE db10;

— 使用db10数据库 USE db10;

— 创建user表 CREATE TABLE USER( id INT PRIMARY KEY AUTO_INCREMENT, — 主键id NAME VARCHAR(20), — 姓名 age INT, — 年龄 search_count INT — 搜索数量 );

— 插入测试数据 INSERT INTO USER VALUES (NULL,’张三’,23,25),(NULL,’李四’,24,5),(NULL,’王五’,25,3) ,(NULL,’赵六’,26,7),(NULL,’张三丰’,93,20),(NULL,’张无忌’,18,23),(NULL,’张强’,33,21),(NULL,’张果老’,65,6);

  1. <a name="0a7df40b"></a>
  2. ## 3.2 案例分析
  3. - **页面**
  4. 1. 为用户名输入框绑定鼠标点击事件。
  5. 1. 获取输入的用户名数据。
  6. 1. 判断用户名是否为空。
  7. 1. 如果为空,则将联想提示框隐藏。
  8. 1. 如果不为空,则发送 AJAX 请求,并将响应的数据显示到联想框。
  9. - **控制层**
  10. 1. 获取请求参数。
  11. 1. 调用业务层的模糊查询方法。
  12. 1. 将返回的数据转成 JSON,并响应给客户端。
  13. <a name="884ba35a"></a>
  14. ## 3.3 代码实现
  15. - **JavaBean类**
  16. ```java
  17. package com.yuwang.bean;
  18. /*
  19. 用户的实体类
  20. */
  21. public class User {
  22. private Integer id; // 主键id
  23. private String name; // 姓名
  24. private Integer age; // 年龄
  25. private Integer search_count; //搜索数量
  26. public User() {
  27. }
  28. public User(Integer id, String name, Integer age, Integer search_count) {
  29. this.id = id;
  30. this.name = name;
  31. this.age = age;
  32. this.search_count = search_count;
  33. }
  34. public Integer getSearch_count() {
  35. return search_count;
  36. }
  37. public void setSearch_count(Integer search_count) {
  38. this.search_count = search_count;
  39. }
  40. public Integer getId() {
  41. return id;
  42. }
  43. public void setId(Integer id) {
  44. this.id = id;
  45. }
  46. public String getName() {
  47. return name;
  48. }
  49. public void setName(String name) {
  50. this.name = name;
  51. }
  52. public Integer getAge() {
  53. return age;
  54. }
  55. public void setAge(Integer age) {
  56. this.age = age;
  57. }
  58. @Override
  59. public String toString() {
  60. return "User{" +
  61. "id=" + id +
  62. ", name='" + name + '\'' +
  63. ", age=" + age +
  64. ", search_count=" + search_count +
  65. '}';
  66. }
  67. }
  • 核心配置文件
    ```xml <?xml version=”1.0” encoding=”UTF-8” ?> <!DOCTYPE configuration PUBLIC “-//mybatis.org//DTD Config 3.0//EN”

    1. "http://mybatis.org/dtd/mybatis-3-config.dtd">

  1. - **映射配置文件**
  2. ```xml
  3. <?xml version="1.0" encoding="UTF-8" ?>
  4. <!--MyBatis的DTD约束-->
  5. <!DOCTYPE mapper
  6. PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  7. "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
  8. <!--mapper:根标签 namespace属性:名称空间-->
  9. <mapper namespace="com.yuwang.mapper.UserMapper">
  10. <!--模糊查询-->
  11. <select id="selectLike" resultType="user" parameterType="string">
  12. SELECT * FROM USER WHERE NAME LIKE CONCAT('%',#{name},'%') ORDER BY search_count LIMIT 0,3
  13. </select>
  14. </mapper>
  • 持久层接口
    ```java package com.yuwang.mapper;

import com.yuwang.bean.User;

import java.util.List;

public interface UserMapper { / 模糊查询 / List selectLike(String username); }

  1. - **业务层接口**
  2. ```java
  3. package com.yuwang.service;
  4. import com.yuwang.bean.User;
  5. import java.util.List;
  6. public interface UserService {
  7. /*
  8. 模糊查询
  9. */
  10. public abstract List<User> selectLike(String username);
  11. }
  • 业务层实现类
    ```java package com.yuwang.service.impl;

import com.yuwang.bean.User; import com.yuwang.mapper.UserMapper; import com.yuwang.service.UserService; 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 org.junit.Test;

import java.io.IOException; import java.io.InputStream; import java.util.List;

public class UserServiceImpl implements UserService { @Override @Test public List selectLike(String username) { List users = null; SqlSession sqlSession = null; InputStream is = null; try{ //1.加载核心配置文件 is = Resources.getResourceAsStream(“MyBatisConfig.xml”); //2.获取SqlSession工厂对象 SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is); //3.通过SqlSession工厂对象获取SqlSession对象 sqlSession = sqlSessionFactory.openSession(true); //4.获取UserMapper接口的实现类对象 UserMapper mapper = sqlSession.getMapper(UserMapper.class); //5.调用实现类对象的模糊查询方法 users = mapper.selectLike(username); }catch (Exception e) { e.printStackTrace(); }finally { //6.释放资源 if(sqlSession != null) { sqlSession.close(); } if(is != null) { try { is.close(); } catch (IOException e) { e.printStackTrace(); } } } //7.返回结果到控制层 return users; } }

  1. - **控制层Servlet代码**
  2. ```java
  3. @WebServlet("/userServlet")
  4. public class UserServlet extends HttpServlet {
  5. //创建业务层实现类对象
  6. UserService service = new UserServiceImpl();
  7. @Override
  8. protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
  9. //设置请求和响应的编码
  10. req.setCharacterEncoding("UTF-8");
  11. resp.setContentType("text/html;charset=UTF-8");
  12. //1.获取请求参数
  13. String username = req.getParameter("username");
  14. //2.调用业务层的模糊查询方法得到数据
  15. List<User> users = service.selectLike(username);
  16. //3.将数据转成JSON,响应到客户端
  17. ObjectMapper mapper = new ObjectMapper();
  18. String json = mapper.writeValueAsString(users);
  19. resp.getWriter().write(json);
  20. }
  21. @Override
  22. protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
  23. doPost(req,resp);
  24. }
  25. }
  • html页面

    1. <!DOCTYPE html>
    2. <html lang="en">
    3. <head>
    4. <meta charset="UTF-8">
    5. <title>用户搜索</title>
    6. <style type="text/css">
    7. .content {
    8. width: 643px;
    9. margin: 100px auto;
    10. text-align: center;
    11. }
    12. input[type='text'] {
    13. width: 530px;
    14. height: 40px;
    15. font-size: 14px;
    16. }
    17. input[type='button'] {
    18. width: 100px;
    19. height: 46px;
    20. background: #38f;
    21. border: 0;
    22. color: #fff;
    23. font-size: 15px
    24. }
    25. .show {
    26. position: absolute;
    27. width: 535px;
    28. height: 100px;
    29. border: 1px solid #999;
    30. border-top: 0;
    31. display: none;
    32. }
    33. </style>
    34. </head>
    35. <body>
    36. <form autocomplete="off">
    37. <div class="content">
    38. <img src="img/logo.jpg">
    39. <br/><br/>
    40. <input type="text" id="username">
    41. <input type="button" value="搜索一下">
    42. <!--用于显示联想的数据-->
    43. <div id="show" class="show"></div>
    44. </div>
    45. </form>
    46. </body>
    47. <script src="js/jQueryuery-3.3.1.min.js"></script>
    48. <script>
    49. //1.为用户名输入框按键弹起事件
    50. $("#username").keyup(function () {
    51. //2.获取输入的用户名
    52. let username = $("#username").val();
    53. //3.去除头尾空格,判断用户名是否为空
    54. if(username.trim() == null || username.trim() == "") {
    55. //4.如果为空,将联想框隐藏,并跳出函数
    56. $("#show").hide();
    57. return;
    58. }
    59. //5.如果不为空,发送AJAX请求。并将数据显示到联想框
    60. $.ajax({
    61. //请求的资源路径
    62. url:"userServlet",
    63. //是否异步
    64. async: true,
    65. //请求参数,去除头尾空格
    66. data:{"username":username.trim()},
    67. //请求方式
    68. type:"POST",
    69. //响应数据形式
    70. dataType:"json",
    71. //请求成功后的回调函数
    72. success:function (data) {
    73. //将返回的数据显示到show的div
    74. let names = "";
    75. //遍历json对象
    76. for(let i = 0; i < data.length; i++) {
    77. //拼接字符串
    78. names += "<div>"+data[i].name+"</div>";
    79. }
    80. //如果没有从数据库中查找到,将联想框隐藏
    81. if(names==""){
    82. $("#show").hide();
    83. }else{
    84. //如果查到数据,将数据设置到联想框中,并显式联想框
    85. $("#show").html(names);
    86. $("#show").show();
    87. }
    88. }
    89. });
    90. });
    91. </script>
    92. </html>

    四、综合案例 瀑布流和分页

    4.1 案例效果和环境准备

  • 瀑布流案例效果
    瀑布流演示.png

  • 分页案例效果
    分页演示.png
  • 环境搭建
    瀑布流和分页环境搭建.png
  • 数据库搭建
    ```sql — 创建db11数据库 CREATE DATABASE db11;

— 使用db11数据库 USE db11;

— 创建数据表 CREATE TABLE news( id INT PRIMARY KEY AUTO_INCREMENT, title VARCHAR(999) );

— 插入数据 DELIMITER $ CREATE PROCEDURE create_data() BEGIN DECLARE i INT DEFAULT 1; WHILE i<=100 DO INSERT INTO news VALUES(NULL,CONCAT(‘这是第’,i,’条正经的新闻’)); SET i=i+1; END WHILE; END$ DELIMITER ;

— 调用存储过程 CALL create_data();

  1. <a name="ca0ebf30"></a>
  2. ## 4.2 瀑布流效果分析
  3. - **如何确定当前显示的数据已经浏览完毕?**
  4. - 公式:(滚动条距底部的距离 + 滚动条上下滚动的距离 + 当前窗口的高度) >= 当前文档的高度
  5. - 当前文档高度:存储10条数据,100px。
  6. - 滚动条距底部的距离:1px。
  7. - 当前窗口的高度:80px。
  8. - 滚动条上下滚动的距离:>=19px。
  9. - **瀑布流案例实现**
  10. - **页面**
  11. 1. 定义发送请求标记。
  12. 1. 定义当前页码和每页显示的条数。
  13. 1. 定义滚动条距底部的距离。
  14. 1. 设置页面加载事件。
  15. 1. 为当前窗口绑定滚动条滚动事件。
  16. 1. 获取必要信息(当前窗口的高度,滚动条上下滚动的距离,当前文档的高度)。
  17. 1. 计算当前展示数据是否浏览完毕。判断请求标记是否为 true。将请求标记置为 false,当前异步操作完成前,不能重新发起请求。
  18. 1. 根据当前页和每页显示的条数来请求查询分页数据。
  19. 1. 当前页码+1。
  20. - **服务器**
  21. 1. 获取请求参数(当前页,每页显示的条数)。
  22. 1. 根据当前页码和每页显示的条数,调用业务层的方法,得到分页 Page 对象。
  23. 1. 将得到的数据转为 json。将数据响应给客户端。
  24. <a name="dbdf2d0a"></a>
  25. ## 4.3 瀑布流代码实现
  26. - **JavaBean类**
  27. ```java
  28. package com.yuwang.bean;
  29. /*
  30. 新闻实体类
  31. */
  32. public class News {
  33. private Integer id; //主键id
  34. private String title; //新闻标题
  35. public News() {
  36. }
  37. public News(Integer id, String title) {
  38. this.id = id;
  39. this.title = title;
  40. }
  41. public Integer getId() {
  42. return id;
  43. }
  44. public void setId(Integer id) {
  45. this.id = id;
  46. }
  47. public String getTitle() {
  48. return title;
  49. }
  50. public void setTitle(String title) {
  51. this.title = title;
  52. }
  53. }

  1. - **持久层接口**
  2. ```java
  3. package com.yuwang.mapper;
  4. import com.yuwang.bean.News;
  5. import org.apache.ibatis.annotations.Select;
  6. import java.util.List;
  7. public interface NewsMapper {
  8. /*
  9. 查询全部
  10. */
  11. @Select("SELECT * FROM news")
  12. List<News> selectAll();
  13. }
  • 业务层接口
    ```java package com.yuwang.service;

import com.github.pagehelper.Page;

public interface NewsService { / 分页查询 / Page pageQuery(Integer start, Integer pageSize); }

  1. - **业务层实现类**
  2. ```java
  3. package com.yuwang.service.impl;
  4. import com.github.pagehelper.Page;
  5. import com.github.pagehelper.PageHelper;
  6. import com.yuwang.mapper.NewsMapper;
  7. import com.yuwang.service.NewsService;
  8. import org.apache.ibatis.io.Resources;
  9. import org.apache.ibatis.session.SqlSession;
  10. import org.apache.ibatis.session.SqlSessionFactory;
  11. import org.apache.ibatis.session.SqlSessionFactoryBuilder;
  12. import java.io.IOException;
  13. import java.io.InputStream;
  14. public class NewsServiceImpl implements NewsService {
  15. @Override
  16. public Page pageQuery(Integer start, Integer pageSize) {
  17. InputStream is = null;
  18. SqlSession sqlSession = null;
  19. Page page = null;
  20. try{
  21. //1.加载核心配置文件
  22. is = Resources.getResourceAsStream("MyBatisConfig.xml");
  23. //2.获取SqlSession工厂对象
  24. SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
  25. //3.通过SqlSession工厂对象获取SqlSession对象
  26. sqlSession = sqlSessionFactory.openSession(true);
  27. //4.获取NewsMapper接口的实现类对象
  28. NewsMapper mapper = sqlSession.getMapper(NewsMapper.class);
  29. //5.封装Page对象 start:当前页码 pageSize:每页显示的条数
  30. page = PageHelper.startPage(start,pageSize);
  31. //6.调用实现类对象的查询全部方法,此时底层执行的就是MySQL的limit分页查询语句
  32. mapper.selectAll();
  33. } catch (Exception e) {
  34. e.printStackTrace();
  35. } finally {
  36. //7.释放资源
  37. if(sqlSession != null) {
  38. sqlSession.close();
  39. }
  40. if(is != null) {
  41. try {
  42. is.close();
  43. } catch (IOException e) {
  44. e.printStackTrace();
  45. }
  46. }
  47. }
  48. //8.返回page对象到控制层
  49. return page;
  50. }
  51. }
  • Servlet控制层代码
    ```java package com.yuwang.controller;

import com.fasterxml.jackson.databind.ObjectMapper; import com.github.pagehelper.Page; import com.yuwang.service.NewsService; import com.yuwang.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(“text/html;charset=UTF-8”);

  1. //1.获取请求参数
  2. String start = req.getParameter("start");
  3. String pageSize = req.getParameter("pageSize");
  4. //2.根据当前页码和每页显示的条数来调用业务层的查询方法,得到分页Page对象
  5. NewsService service = new NewsServiceImpl();
  6. Page page = service.pageQuery(Integer.parseInt(start), Integer.parseInt(pageSize));
  7. //3.将得到的数据转为JSON
  8. String json = new ObjectMapper().writeValueAsString(page);
  9. try {
  10. Thread.sleep(1000);
  11. } catch (InterruptedException e) {
  12. e.printStackTrace();
  13. }
  14. //4.将数据响应给客户端
  15. resp.getWriter().write(json);
  16. }
  17. @Override
  18. protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
  19. doPost(req,resp);
  20. }

}

  1. - **html页面**
  2. ```html
  3. <!DOCTYPE html>
  4. <html lang="en">
  5. <head>
  6. <meta charset="UTF-8">
  7. <title>网站首页</title>
  8. <link rel="stylesheet" href="css/tt.css">
  9. </head>
  10. <body>
  11. <div class="top">
  12. <span class="top-left">下载APP</span>
  13. <span class="top-left"> 北京 晴天</span>
  14. <span class="top-right">更多产品</span>
  15. </div>
  16. <div class="container">
  17. <div class="left">
  18. <a>
  19. <img src="img/logo.jpg"><br/>
  20. </a>
  21. <ul>
  22. <li>
  23. <a class="channel-item active" href="#">
  24. <span>
  25. 推荐
  26. </span>
  27. </a>
  28. </li>
  29. <li><a class="channel-item" href="#">
  30. <span>
  31. 视频
  32. </span>
  33. </a></li>
  34. <li><a class="channel-item" href="#">
  35. <span>
  36. 热点
  37. </span>
  38. </a></li>
  39. <li><a class="channel-item" href="#">
  40. <span>
  41. 直播
  42. </span>
  43. </a></li>
  44. <li><a class="channel-item" href="#">
  45. <span>
  46. 图片
  47. </span>
  48. </a></li>
  49. <li><a class="channel-item" href="#">
  50. <span>
  51. 娱乐
  52. </span>
  53. </a></li>
  54. <li><a class="channel-item" href="#">
  55. <span>
  56. 游戏
  57. </span>
  58. </a></li>
  59. <li><a class="channel-item" href="#">
  60. <span>
  61. 体育
  62. </span>
  63. </a></li>
  64. </ul>
  65. </div>
  66. <div class="center">
  67. <ul class="news_list">
  68. <li>
  69. <div class="title-box">
  70. <a href="#" class="link">
  71. 测试数据
  72. <hr>
  73. </a>
  74. </div>
  75. </li>
  76. </ul>
  77. <div class="loading" style="text-align: center; height: 80px">
  78. <img src="img/loading.gif" height="100%">
  79. </div>
  80. <div class="content">
  81. <div class="pagination-holder clearfix">
  82. <div id="light-pagination" class="pagination"></div>
  83. </div>
  84. </div>
  85. <div id="no" style="text-align: center;color: red;font-size: 20px"></div>
  86. </div>
  87. </div>
  88. </body>
  89. <script src="js/jquery-3.3.1.min.js"></script>
  90. <script>
  91. //1.定义发送请求标记
  92. let send = true;
  93. //2.定义当前页码和每页显示的条数
  94. let start = 1;
  95. let pageSize = 20;
  96. //3.定义滚动条距底部的距离
  97. let bottom = 1;
  98. //4.设置页面加载事件
  99. $(function () {
  100. //初次加载信息
  101. //根据当前页和每页显示的条数来 请求查询分页数据
  102. queryByPage(start, pageSize);
  103. //当前页码+1
  104. start++;
  105. //5.为当前窗口绑定滚动条滚动事件
  106. $(window).scroll(function () {
  107. //6.获取必要信息,用于计算当前展示数据是否浏览完毕
  108. //当前窗口的高度
  109. let windowHeight = $(window).height();
  110. //滚动条从上到下滚动距离
  111. let scrollTop = $(window).scrollTop();
  112. //当前文档的高度
  113. let docHeight = $(document).height();
  114. //7.计算当前展示数据是否浏览完毕
  115. //当 滚动条距底部的距离 + 当前滚动条滚动的距离 + 当前窗口的高度 >= 当前文档的高度
  116. if ((bottom + scrollTop + windowHeight) >= docHeight) {
  117. //8.判断请求标记是否为true
  118. if (send) {
  119. //9.将请求标记置为false,当前异步操作完成前,不能重新发起请求。
  120. send = false;
  121. //10.根据当前页和每页显示的条数来 请求查询分页数据
  122. queryByPage(start, pageSize);
  123. //11.当前页码+1
  124. start++;
  125. }
  126. }
  127. });
  128. });
  129. //定义查询分页数据的函数
  130. function queryByPage(start, pageSize) {
  131. //加载动图显示
  132. $(".loading").show();
  133. //发起AJAX请求
  134. $.ajax({
  135. //请求的资源路径
  136. url: "newsServlet",
  137. //请求的参数
  138. data: {"start": start, "pageSize": pageSize},
  139. //请求的方式
  140. type: "POST",
  141. //响应数据形式
  142. dataType: "json",
  143. //请求成功后的回调函数
  144. success: function (data) {
  145. //当无数据返回时,隐藏加载动画,显示提示信息
  146. if (data.length == 0) {
  147. $(".loading").hide();
  148. $("#no").html("我也是有底线的");
  149. return;
  150. }
  151. //加载动图隐藏
  152. $(".loading").hide();
  153. //将数据显示
  154. let titles = "";
  155. for (let i = 0; i < data.length; i++) {
  156. titles += "<li>\n" +
  157. " <div class=\"title-box\">\n" +
  158. " <a href=\"#\" class=\"link\">\n" +
  159. data[i].title +
  160. " <hr>\n" +
  161. " </a>\n" +
  162. " </div>\n" +
  163. " </li>";
  164. }
  165. //显示到页面
  166. $(".news_list").append(titles);
  167. //将请求标记设置为true
  168. send = true;
  169. }
  170. });
  171. }
  172. </script>
  173. </html>

4.4 分页效果分析

  • 案例的分析

    • 页面
      1.引入分页插件的样式文件和 js 文件。
      1. 定义当前页码和每页显示的条数。
      2. 调用查询数据的函数。
      3. 定义请求查询分页数据的函数,发起 AJAX 异步请求。
      4. 为分页按钮区域设置页数参数(总页数和当前页)。
      5. 为分页按钮绑定单击事件,完成上一页下一页查询功能。
    • 服务器
        1. 获取请求参数。
        2. 根据当前页码和每页显示的条数,调用业务层的方法,得到分页 Page 对象
        3. 封装 PageInfo 对象。
        4. 将得到的数据转为 json。
        5. 将数据响应给客户端。

          4.5 分页代码实现

  • Servlet控制层代码
    ```java package com.yuwang.controller;

import com.fasterxml.jackson.databind.ObjectMapper; import com.github.pagehelper.Page; import com.github.pagehelper.PageInfo; import com.yuwang.bean.News; import com.yuwang.service.NewsService; import com.yuwang.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; import java.util.List;

@WebServlet(“/newsServlet2”) public class NewsServlet2 extends HttpServlet { @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //设置请求和响应的编码 req.setCharacterEncoding(“UTF-8”); resp.setContentType(“text/html;charset=UTF-8”);

  1. //1.获取请求参数
  2. String start = req.getParameter("start");
  3. String pageSize = req.getParameter("pageSize");
  4. //2.根据当前页码和每页显示的条数来调用业务层的查询方法,得到分页Page对象
  5. NewsService service = new NewsServiceImpl();
  6. Page page = service.pageQuery(Integer.parseInt(start), Integer.parseInt(pageSize));
  7. //3.封装PageInfo对象
  8. PageInfo<List<News>> info = new PageInfo<>(page);
  9. //4.将得到的数据转为JSON
  10. String json = new ObjectMapper().writeValueAsString(info);
  11. //5.将数据响应给客户端
  12. resp.getWriter().write(json);
  13. }
  14. @Override
  15. protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
  16. doPost(req,resp);
  17. }

}

  1. - **html页面**
  2. ```html
  3. <!DOCTYPE html>
  4. <html lang="en">
  5. <head>
  6. <meta charset="UTF-8">
  7. <title>网站首页</title>
  8. <link rel="stylesheet" href="css/tt.css">
  9. <link rel="stylesheet" href="css/simplePagination.css">
  10. </head>
  11. <body>
  12. <div class="top">
  13. <span class="top-left">下载APP</span>
  14. <span class="top-left"> 北京 晴天</span>
  15. <span class="top-right">更多产品</span>
  16. </div>
  17. <div class="container">
  18. <div class="left">
  19. <a>
  20. <img src="img/logo.jpg"><br/>
  21. </a>
  22. <ul>
  23. <li>
  24. <a class="channel-item active" href="#">
  25. <span>
  26. 推荐
  27. </span>
  28. </a>
  29. </li>
  30. <li><a class="channel-item" href="#">
  31. <span>
  32. 视频
  33. </span>
  34. </a></li>
  35. <li><a class="channel-item" href="#">
  36. <span>
  37. 热点
  38. </span>
  39. </a></li>
  40. <li><a class="channel-item" href="#">
  41. <span>
  42. 直播
  43. </span>
  44. </a></li>
  45. <li><a class="channel-item" href="#">
  46. <span>
  47. 图片
  48. </span>
  49. </a></li>
  50. <li><a class="channel-item" href="#">
  51. <span>
  52. 娱乐
  53. </span>
  54. </a></li>
  55. <li><a class="channel-item" href="#">
  56. <span>
  57. 游戏
  58. </span>
  59. </a></li>
  60. <li><a class="channel-item" href="#">
  61. <span>
  62. 体育
  63. </span>
  64. </a></li>
  65. </ul>
  66. </div>
  67. <div class="center">
  68. <ul class="news_list">
  69. </ul>
  70. <div class="content">
  71. <div class="pagination-holder clearfix">
  72. <div id="light-pagination" class="pagination"></div>
  73. </div>
  74. </div>
  75. </div>
  76. </div>
  77. </body>
  78. <script src="js/jquery-3.3.1.min.js"></script>
  79. <script src="js/jquery.simplePagination.js"></script>
  80. <script>
  81. //1.定义当前页码和每页显示的条数
  82. let start = 1;
  83. let pageSize = 20;
  84. //2.调用查询数据的方法
  85. queryByPage(start, pageSize);
  86. //3.定义请求查询分页数据的函数,发起AJAX异步请求,将数据显示到页面
  87. function queryByPage(start, pageSize) {
  88. $.ajax({
  89. //请求的资源路径
  90. url: "newsServlet2",
  91. //请求的参数
  92. data: {"start": start, "pageSize": pageSize},
  93. //请求的方式
  94. type: "POST",
  95. //响应数据形式
  96. dataType: "json",
  97. //请求成功后的回调函数
  98. success: function (pageInfo) {
  99. //将数据显示到页面
  100. let titles = "";
  101. for (let i = 0; i < pageInfo.list.length; i++) {
  102. titles += "<li>\n" +
  103. " <div class=\"title-box\">\n" +
  104. " <a href=\"#\" class=\"link\">\n" +
  105. pageInfo.list[i].title +
  106. " <hr>\n" +
  107. " </a>\n" +
  108. " </div>\n" +
  109. " </li>";
  110. }
  111. $(".news_list").html(titles);
  112. //4.为分页按钮区域设置页数参数(总页数和当前页)
  113. $("#light-pagination").pagination({
  114. pages: pageInfo.pages,
  115. currentPage: pageInfo.pageNum
  116. });
  117. //5.为分页按钮绑定单击事件,完成上一页下一页查询功能
  118. $("#light-pagination .page-link").click(function () {
  119. //获取点击按钮的文本内容
  120. let page = $(this).html();
  121. //如果点击的是Prev,调用查询方法,查询当前页的上一页数据
  122. if (page == "Prev") {
  123. queryByPage(pageInfo.pageNum - 1, pageSize);
  124. } else if (page == "Next") {
  125. //如果点击的是Next,调用查询方法,查询当前页的下一页数据
  126. queryByPage(pageInfo.pageNum + 1, pageSize);
  127. } else {
  128. //调用查询方法,查询当前页的数据
  129. queryByPage(page, pageSize);
  130. }
  131. });
  132. }
  133. });
  134. }
  135. </script>
  136. </html>