Java中的Listener监听器与Ajax技术和Axios异步框架以及JSON传递接收数据

Listener监听器与Ajax

Listener

概念

  • Listener 表示监听器,是 JavaWeb 三大组件(Servlet、Filter、Listener)之一。

  • 监听器可以监听就是在 applicationsessionrequest 三个对象创建、销毁或者往其中添加修改删除属性时自动执行代码的功能组件。

    request 和 session 我们学习过。而 applicationServletContext 类型的对象。

    ServletContext 代表整个web应用,在服务器启动的时候,tomcat会自动创建该对象。在服务器关闭时会自动销毁该对象。

分类

JavaWeb 提供了8个监听器:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5mbWcJCX-1648625672539)(image/Filter/image-20220330095258369.png)]

这里面只有 ServletContextListener 这个监听器后期我们会接触到,ServletContextListener 是用来监听 ServletContext 对象的创建和销毁。

ServletContextListener 接口中有以下两个方法

  • void contextInitialized(ServletContextEvent sce)ServletContext 对象被创建了会自动执行的方法
  • void contextDestroyed(ServletContextEvent sce)ServletContext 对象被销毁时会自动执行的方法

代码演示

  • 定义一个类,实现ServletContextListener 接口
  • 重写所有的抽象方法
  • 使用 @WebListener 注解进行配置
package com.zcl.webs.listener;

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;

/**
 * TODO:
 *
 * @author zcl
 * @date 2022/3/30 9:58
 */
@WebListener
public class ContextLoaderListener implements ServletContextListener {
    
    
    @Override
    public void contextInitialized(ServletContextEvent servletContextEvent) {
    
    
        // 加载资源
        System.out.println("加载资源");
    }

    @Override
    public void contextDestroyed(ServletContextEvent servletContextEvent) {
    
    
        // 释放资源
        System.out.println("释放资源");
    }
}

Ajax

概念:

AJAX (Asynchronous JavaScript And XML):异步的 JavaScript 和 XML。

JavaScript 表明该技术和前端相关;XML 是指以此进行数据交换。

两方面作用:

  1. 与服务器进行数据交换:通过AJAX可以给服务器发送请求,服务器将数据直接响应回给浏览器。如下图

我们先来看之前做功能的流程,如下图:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GDEuIoes-1648625672540)(image/Filter/image-20220330101005761.png)]

如上图,Servlet 调用完业务逻辑层后将数据存储到域对象中,然后跳转到指定的 jsp 页面,在页面上使用 EL表达式JSTL 标签库进行数据的展示。

学习了AJAX 后,就可以使用AJAX和服务器进行通信,以达到使用 HTML+AJAX来替换JSP页面了。如下图,浏览器发送请求servlet,servlet 调用完业务逻辑层后将数据直接响应回给浏览器页面,页面使用 HTML 来进行数据展示。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8h2FoY8k-1648625672541)(image/Filter/image-20220330101025206.png)]

2、异步交互:可以在不重新加载整个页面的情况下,与服务器交换数据并更新部分网页的技术,如:搜索联想、用户名是否可用校验,等等…

同步和异步

同步发送请求过程如下

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KtMBmoIR-1648625672541)(image/Filter/image-20220330101104765.png)]

浏览器页面在发送请求给服务器,在服务器处理请求的过程中,浏览器页面不能做其他的操作。只能等到服务器响应结束后才能,浏览器页面才能继续做其他的操作。

异步发送请求过程如下

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fZmHPDKo-1648625672542)(image/Filter/image-20220330101118309.png)]

浏览器页面发送请求给服务器,在服务器处理请求的过程中,浏览器页面还可以做其他的操作。

简单总结:同步需要等上一个资源请求完成才会处理下一个请求,需要排队

异步不需要排队等待

ajax快速入门

1、编写AjaxServley服务器,并使用response输出字符串

package com.zcl.webs; /**
 * TODO:
 *
 * @author zcl
 * @date 2022/3/30 10:23
 */

import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.IOException;

@WebServlet("/ajaxServlet")
public class AjaxServlet extends HttpServlet {
    
    
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    
        // 响应数据
        response.getWriter().write("hellow");
    }

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

2、创建XMLHttpRequest对象,用于和服务器交换数据

//1. 创建核心对象
var xhttp;
if (window.XMLHttpRequest) {
    
    
    xhttp = new XMLHttpRequest();
} else {
    
    
    // code for IE6, IE5
    xhttp = new ActiveXObject("Microsoft.XMLHTTP");
}

3、向服务器发送请求

请求路径写绝对路径

//2. 发送请求
xhttp.open("GET", "http://localhost:8080/ajax-demo/ajaxServlet");
xhttp.send();

4、获取服务器响应数据

//3. 获取响应
xhttp.onreadystatechange = function() {
    
    
    if (this.readyState == 4 && this.status == 200) {
    
    
        alert(this.responseText);
    }
};
Axios异步框架

Axios 对原生的AJAX进行封装,简化书写。

Axios官网是:https://www.axios-http.cn

Axios快速入门

axios 使用是比较简单的,分为以下两步:

1、引入 axios 的 js 文件【官网下载】

<script src="js/axios-0.18.0.js"></script>

2、使用axios 发送请求,并获取响应结果

  • 发送 get 请求

    axios({
          
          
        method:"get",
        url:"http://localhost:8080/ajax-demo1/aJAXDemo1?username=zhangsan"
    }).then(function (resp){
          
          
        alert(resp.data);
    })
    
  • 发送 post请求

    axios({
          
          
        method:"post",
        url:"http://localhost:8080/ajax-demo1/aJAXDemo1",
        data:"username=zhangsan"
    }).then(function (resp){
          
          
        alert(resp.data);
    });
    
  • 后端服务器代码

    package com.zcl.webs; /**
     * TODO:
     *
     * @author zcl
     * @date 2022/3/30 10:23
     */
    
    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("/axiosServlet")
    public class AxiosServlet extends HttpServlet {
          
          
        @Override
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
          
          
            System.out.println("get...");
            String username = request.getParameter("username");
            System.out.println(username);
            // 响应数据
            response.getWriter().write("hellow axios");
        }
    
        @Override
        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
          
          
            System.out.println("post...");
            this.doGet(request, response);
        }
    }
    
    

axios() 是用来发送异步请求的,小括号中使用 js 对象传递请求相关的参数:

  • method 属性:用来设置请求方式的。取值为 get 或者 post
  • url 属性:用来书写请求的资源路径。如果是 get 请求,需要将请求参数拼接到路径的后面,格式为: url?参数名=参数值&参数名2=参数值2
  • data 属性:作为请求体被发送的数据。也就是说如果是 post 请求的话,数据需要作为 data 属性的值。

then() 需要传递一个匿名函数。我们将 then() 中传递的匿名函数称为 回调函数,意思是该匿名函数在发送请求时不会被调用,而是在成功响应后调用的函数。而该回调函数中的 resp 参数是对响应的数据进行封装的对象,通过 resp.data 可以获取到响应的数据。

执行流程:启动服务器,直接访问页面,页面会通过axios请求服务器获取数据

请求方法别名

为了方便起见, Axios 已经为所有支持的请求方法提供了别名。如下:

  • get 请求 : axios.get(url[,config])

  • delete 请求 : axios.delete(url[,config])

  • head 请求 : axios.head(url[,config])

  • options 请求 : axios.option(url[,config])

  • post 请求:axios.post(url[,data[,config])

  • put 请求:axios.put(url[,data[,config])

  • patch 请求:axios.patch(url[,data[,config])

而我们只关注 get 请求和 post 请求。

axios.get("http://localhost:8080/ajax-demo/axiosServlet?username=zhangsan").then(function (resp) {
    
    
    alert(resp.data);
});

post请求

axios.post("http://localhost:8080/ajax-demo/axiosServlet","username=zhangsan").then(function (resp) {
    
    
    alert(resp.data);
})

JSON 基础语法

概念:JavaScript Object Notation。JavaScript 对象表示法.

如下是 JavaScript 对象的定义格式:

{
    
    
	name:"zhangsan",
	age:23,
	city:"北京"
}

接下来我们再看看 JSON 的格式:

{
    
    
	"name":"zhangsan",
	"age":23,
	"city":"北京"
}

作用:由于其语法格式简单,层次结构鲜明,现多用于作为数据载体,在网络中进行数据传输。

JSON 本质就是一个字符串,但是该字符串内容是有一定的格式要求的。 定义格式如下:

var 变量名 = '{"key":value,"key":value,...}';

JSON 串的键要求必须使用双引号括起来,而值根据要表示的类型确定。value 的数据类型分为如下

  • 数字(整数或浮点数)
  • 字符串(使用双引号括起来)
  • 逻辑值(true或者false)
  • 数组(在方括号中)
  • 对象(在花括号中)
  • null

示例:

var jsonStr = '{"name":"zhangsan","age":23,"addr":["北京","上海","西安"]}'

如果它是一个 js 对象,我们就可以通过 js对象.属性名 的方式来获取数据。JS 提供了一个对象 JSON ,该对象有如下两个方法:

  • parse(str) :将 JSON串转换为 js 对象。使用方式是: var jsObject = JSON.parse(jsonStr);
  • stringify(obj) :将 js 对象转换为 JSON 串。使用方式是:var jsonStr = JSON.stringify(jsObject)

演示代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<script>
    //1. 定义JSON字符串
    var jsonStr = '{"name":"zhangsan","age":23,"addr":["北京","上海","西安"]}'
    alert(jsonStr);

    //2. 将 JSON 字符串转为 JS 对象
    let jsObject = JSON.parse(jsonStr);
    alert(jsObject)
    alert(jsObject.name)
    //3. 将 JS 对象转换为 JSON 字符串
    let jsonStr2 = JSON.stringify(jsObject);
    alert(jsonStr2)
</script>
</body>
</html>

JSON串和Java对象的相互转换

前端发送请求时,如果是复杂的数据就会以 json 提交给后端;而后端如果需要响应一些复杂的数据时,也需要以 json 格式将数据响应回给浏览器。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RoUcxcuz-1648625672542)(image/Filter/image-20220330121057581.png)]

  • 请求数据:JSON字符串转为Java对象
  • 响应数据:Java对象转为JSON字符串

使用的api是Fastjson

Fastjson 概述

Fastjson 是阿里巴巴提供的一个Java语言编写的高性能功能完善的 JSON 库,是目前Java语言中最快的 JSON 库,可以实现 Java 对象和 JSON 字符串的相互转换。

Fastjson 使用

Fastjson 使用也是比较简单的,分为以下三步完成

1、导入坐标

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.2.62</version>
</dependency>

2、Java对象转JSON

String jsonStr = JSON.toJSONString(obj);

将 Java 对象转换为 JSON 串,只需要使用 Fastjson 提供的 JSON 类中的 toJSONString() 静态方法即可。

3、JSON字符串转Java对象

User user = JSON.parseObject(jsonStr, User.class);

将 json 转换为 Java 对象,只需要使用 Fastjson 提供的 JSON 类中的 parseObject() 静态方法即可。

代码演示
  • 引入坐标

  • 创建一个类,专门用来测试 Java 对象和 JSON 串的相互转换,代码如下:

public class FastjsonDemo {
    
    
    public static void main(String[] args) {
    
    
        // Java对象转JSON
        User user = new User();
        user.setId(1);
        user.setName("展会上");
        user.setAge(56);
        String s = JSON.toJSONString(user);
        System.out.println(s);
        // {"age":56,"id":1,"name":"展会上"}

        // 3、JSON字符串转Java对象
        //2. 将JSON字符串转为Java对象
        User u = JSON.parseObject("{\"id\":1,\"name\":\"123\",\"age\":56}", User.class);
        System.out.println(u);
        // User{id=1, name='123', age=56}
    }
}

案例

需求:使用Axios + JSON 完成品牌列表数据查询和添加。页面效果还是下图所示:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OfPShhey-1648625672543)(image/Filter/image-20220330142857616.png)]

1、查询所有功能

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1NlxJbHQ-1648625672543)(image/Filter/image-20220330142922606.png)]

如上图所示就该功能的整体流程。前后端需以 JSON 格式进行数据的传递;由于此功能是查询所有的功能,前端发送 ajax 请求不需要携带参数,而后端响应数据需以如下格式的 json 数据

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WHLFPhLj-1648625672544)(image/Filter/image-20220330142944484.png)]

2、后端实现

com.zcl.web 包下创建名为 SelectAllServletservlet,具体的逻辑如下:

  • 调用 service 的 selectAll() 方法进行查询所有的逻辑处理
  • 将查询到的集合数据转换为 json 数据。我们将此过程称为 序列化;如果是将 json 数据转换为 Java 对象,我们称之为 反序列化
  • 将 json 数据响应回给浏览器。这里一定要设置响应数据的类型及字符集 response.setContentType("text/json;charset=utf-8");

SelectAllServlet 代码如下:

package com.itheima.webs; /**
 * TODO:
 *
 * @author zcl
 * @date 2022/3/30 14:37
 */

import com.alibaba.fastjson.JSON;
import com.itheima.pojo.Brand;
import com.itheima.service.BrandService;

import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.IOException;
import java.util.List;

@WebServlet("/selectAllServlet")
public class SelectAllServlet extends HttpServlet {
    
    
    private BrandService brandService = new BrandService();
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    
        // 调用方法查询数据
        List<Brand> brands = brandService.selectAll();

        // 2、讲集合转换成JSON数据 序列化
        String jsonString = JSON.toJSONString(brands);
        // 3、响应数据
        response.setContentType("text/json;charset=utf-8");
        response.getWriter().write(jsonString);

    }

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

3、前端实现
  1. 引入 js 文件

brand.html 页面引入 axios 的 js 文件

<script src="js/axios-0.18.0.js"></script>
  1. 绑定 页面加载完毕 事件

brand.html 页面绑定加载完毕事件,该事件是在页面加载完毕后被触发,代码如下

window.onload = function() {
    
    
	
}
  1. 发送异步请求

在页面加载完毕事件绑定的匿名函数中发送异步请求,代码如下:

 //2. 发送ajax请求
axios({
    
    
    method:"get",
    url:"http://localhost:8080/brand-demo/selectAllServlet"
}).then(function (resp) {
    
    

});
  1. 处理响应数据

then 中的回调函数中通过 resp.data 可以获取响应回来的数据,而数据格式如下

现在我们需要拼接字符串,将下面表格中的所有的 tr 拼接到一个字符串中,然后使用 document.getElementById("brandTable").innerHTML = 拼接好的字符串 就可以动态的展示出用户想看到的数据

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<a href="addBrand.html"><input type="button" value="新增"></a><br>
<hr>
<table id="brandTable" border="1" cellspacing="0" width="100%">
   
</table>

<script src="js/axios-0.18.0.js"></script>

<script>
    //1. 当页面加载完成后,发送ajax请求
    window.onload = function () {
      
      
        //2. 发送ajax请求
        axios({
      
      
            method:"get",
            url:"http://localhost:8080/brand-demo/selectAllServlet"
        }).then(function (resp) {
      
      
            //获取数据
            let brands = resp.data;
            let tableData = " <tr>\n" +
                "        <th>序号</th>\n" +
                "        <th>品牌名称</th>\n" +
                "        <th>企业名称</th>\n" +
                "        <th>排序</th>\n" +
                "        <th>品牌介绍</th>\n" +
                "        <th>状态</th>\n" +
                "        <th>操作</th>\n" +
                "    </tr>";

            for (let i = 0; i < brands.length ; i++) {
      
      
                let brand = brands[i];

                tableData += "\n" +
                    "    <tr align=\"center\">\n" +
                    "        <td>"+(i+1)+"</td>\n" +
                    "        <td>"+brand.brandName+"</td>\n" +
                    "        <td>"+brand.companyName+"</td>\n" +
                    "        <td>"+brand.ordered+"</td>\n" +
                    "        <td>"+brand.description+"</td>\n" +
                    "        <td>"+brand.status+"</td>\n" +
                    "\n" +
                    "        <td><a href=\"#\">修改</a> <a href=\"#\">删除</a></td>\n" +
                    "    </tr>";
            }
            // 设置表格数据
            document.getElementById("brandTable").innerHTML = tableData;
        })
    }
</script>
</body>
</html>

输出效果

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nYl1ut2b-1648625672544)(image/Filter/image-20220330145906563.png)]

添加品牌功能

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BcJ1kESn-1648625672545)(image/Filter/image-20220330145929389.png)]

点击 新增 按钮,会跳转到 addBrand.html 页面。在 addBrand.html 页面输入数据后点击 提交 按钮,就会将数据提交到后端,而后端将数据保存到数据库中。

具体的前后端交互的流程如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-antSFQcL-1648625672545)(image/Filter/image-20220330145938729.png)]

说明:

前端需要将用户输入的数据提交到后端,这部分数据需要以 json 格式进行提交,数据格式如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8qtXAjum-1648625672546)(image/Filter/image-20220330145950651.png)]

后端实现

com.zcl.web 包下创建名为 AddServletservlet,具体的逻辑如下:

  • 获取请求参数

    由于前端提交的是 json 格式的数据,所以我们不能使用 request.getParameter() 方法获取请求参数

    • 如果提交的数据格式是 username=zhangsan&age=23 ,后端就可以使用 request.getParameter() 方法获取
    • 如果提交的数据格式是 json,后端就需要通过 request 对象获取输入流,再通过输入流读取数据
  • 将获取到的请求参数(json格式的数据)转换为 Brand 对象

  • 调用 service 的 add() 方法进行添加数据的逻辑处理

  • 将 json 数据响应回给浏览器。

AddServlet 代码如下:

java中不可以直接接收json数据,需要获取字符输入流对象来转转

package com.itheima.webs; /**
 * TODO:
 *
 * @author zcl
 * @date 2022/3/30 15:00
 */

import com.alibaba.fastjson.JSON;
import com.itheima.pojo.Brand;
import com.itheima.service.BrandService;

import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.BufferedReader;
import java.io.IOException;

@WebServlet("/addServlet")
public class AddServlet extends HttpServlet {
    
    
    private BrandService brandService = new BrandService();
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    
        // 1、接收数据【不能接收JSON数据】
        // String brandName = request.getParameter("brandName");

        // 获取请求体数据
        BufferedReader reader = request.getReader();
        // 读取一行
        String s = reader.readLine();
        // 转换成Brand格式【json转换成java对象】
        Brand brand = JSON.parseObject(s, Brand.class);
//        System.out.println(brand);
        // 调用添加的方法
        brandService.add(brand);
        // 响应成功的标识
        response.getWriter().write("success");

    }

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

前端实现

addBrand.html 页面给 提交 按钮绑定点击事件,并在绑定的匿名函数中发送异步请求,代码如下:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>添加品牌</title>
</head>
<body>
<h3>添加品牌</h3>
<form action="" method="post">
    品牌名称:<input id="brandName" name="brandName"><br>
    企业名称:<input id="companyName" name="companyName"><br>
    排序:<input id="ordered" name="ordered"><br>
    描述信息:<textarea rows="5" cols="20" id="description" name="description"></textarea><br>
    状态:
    <input type="radio" name="status" value="0">禁用
    <input type="radio" name="status" value="1">启用<br>

    <input type="button" id="btn" value="提交">
</form>
<script src="js/axios-0.18.0.js"></script>
<script>
    // 1、绑定按钮的点击事件
    document.getElementById("btn").onclick = function () {
      
      
        // 将表单的数据转换成JSON
        var forData = {
      
      
            brandName: "",
            companyName: "",
            ordered: "",
            description: "",
            status: ""
        }
        // 获取表单数据
        forData.brandName = document.getElementById("brandName").value;
        forData.companyName = document.getElementById("companyName").value;
        forData.ordered = document.getElementById("ordered").value;
        forData.description = document.getElementById("description").value;

        let status = document.getElementsByName("status");
        for (let i = 0; i < status.length; i++) {
      
      
            if (status[i].checked) {
      
      
                forData.status = status[i].value;
            }
        }
        console.log(forData)

        // 2、发起请求
        axios({
      
      
            method: 'post',
            url: 'http://localhost:8080/brand-demo/addServlet',
            data: forData
        }).then(function (rep) {
      
      
            if (rep.data == "success") {
      
      
                location.href = "http://localhost:8080/brand-demo/brand.html";
            }
        });
    }
</script>

</body>
</html>

猜你喜欢

转载自blog.csdn.net/baidu_39378193/article/details/123847936