Filter&Listener&Ajax

Table of contents

Quick Start with Filter

Filet execution process

Filter usage details

Filter interception path configuration

filter chain

the case

 Listener

Ajax

AJAX Quick Start

the case

Axios asynchronous framework

quick start

JSON

Basic JSON syntax

JSON data and Java object conversion

the case


Filter概述
Filter 表示过滤器,是 JavaWeb 三大组件(Servlet、Filter、Listener)之一。
过滤器可以把对资源的请求拦截下来,从而实现一些特殊的功能。
如下图所示,浏览器可以访问服务器上的所有的资源(servlet、jsp、html等)
而在访问到这些资源之前可以使过滤器拦截来下,也就是说在访问资源之前会先经过 Filter

拦截器拦截到后可以做什么功能呢?
过滤器一般完成一些通用的操作。
之前做的品牌数据管理的案例中就已经做了登陆的功能,而如果不登录能不能访问到数据?
在浏览器直接访问首页 ,可以看到 查询所有 的超链接
当点击该按钮,居然可以看到品牌的数据

 

这显然和我们的要求不符。我们希望实现的效果是用户如果登陆过了就跳转到品牌数据展示的页面;
如果没有登陆就跳转到登陆页面让用户进行登陆,要实现这个效果需要在每一个资源中都写上这段逻辑,
而像这种通用的操作,我们就可以放在过滤器中进行实现。
这个就是权限控制,以后我们还会进行细粒度权限控制。
过滤器还可以做 统一编码处理 、 敏感字符处理 等等.

Quick Start with Filter

development steps

1、定义类,实现 Filter接口,并重写其所有方法

 

配置Filter拦截资源的路径:在类上定义 @WebFilter 注解。
而注解的 value 属性值 /* 表示拦截所有的资源

 

在doFilter方法中输出一句话,并放行

 code demo

<!-- hello.jsp 页面内容如下:-->
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<h1>hello JSP~</h1>
</body>
</html>
现在在浏览器输入 http://localhost/filter-demo/hello.jsp 访问 hello.jsp 页面,
这里是可以访问到hello.jsp 页面内容的。

 

//创建在 com.green.web.filter 包下,起名为FilterDemo
@WebFilter("/*")
public class FilterDemo implements Filter {
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        System.out.println("hello FilterDemo~~");
    }

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }
    @Override
    public void destroy() {

    }
}
重启启动服务器,再次重新访问 hello.jsp 页面,这次发现页面没有任何效果,
但是在 idea 的控制台可以看到如下内容

 

FilterDemo 这个过滤器的 doFilter() 方法执行了,看不到 hello.jsp 页面的内容
在 doFilter() 方法中添加放行的代码,
//放行
filterChain.doFilter(servletRequest,servletResponse);
再次重启服务器并访问 hello.jsp 页面,发现这次就可以在浏览器上看到页面效果。
//完整代码
@WebFilter("/*")
public class FilterDemo implements Filter {
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        System.out.println("hello FilterDemo~~");

        //放行
        filterChain.doFilter(servletRequest,servletResponse);
    }

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void destroy() {

    }
}

Filet execution process

如上图是使用过滤器的流程,我们通过以下问题来研究过滤器的执行流程:
放行后访问对应资源,资源访问完成后,还会回到Filter中吗?
从上图就可以看出肯定会回到Filter中
如果回到Filter中,是重头执行还是执行放行后的逻辑呢?
如果是重头执行的话,就意味着 放行前逻辑 会被执行两次,肯定不会这样设计了;
所以访问完资源后,会回到 放行后逻辑 ,执行该部分代码。
通过上述的说明,我们就可以总结Filter的执行流程如下:

 

 

  At the same time , add an output statement to the hello.jsp page, as follows

执行访问该资源打印的顺序是按照标记的标号进行打印的话,说明上边总结出来的流程是没有问题的。
启动服务器访问 hello.jsp 页面,在控制台打印的内容如下:

 

Filter usage details

Filter interception path configuration

拦截路径表示 Filter 会对请求的哪些资源进行拦截,使用 @WebFilter 注解进行配置。
如: @WebFilter("拦截路径") 拦截路径有如下四种配置方式:
拦截具体的资源:/index.jsp:只有访问index.jsp时才会被拦截
目录拦截:/user/*:访问/user下的所有资源,都会被拦截
后缀名拦截:*.jsp:访问后缀名为jsp的资源,都会被拦截
拦截所有:/*:访问所有资源,都会被拦截

filter chain

概述
过滤器链是指在一个Web应用,可以配置多个过滤器,这多个过滤器称为过滤器链。

上图中的过滤器链执行是按照以下流程执行:
1. 执行 Filter1 的放行前逻辑代码
2. 执行 Filter1 的放行代码
3. 执行 Filter2 的放行前逻辑代码
4. 执行 Filter2 的放行代码
5. 访问到资源
6. 执行 Filter2 的放行后逻辑代码
7. 执行 Filter1 的放行后逻辑代码

 code demo

//编写第一个过滤器 FilterDemo ,配置成拦截所有资源
@WebFilter("/*")
public class FilterDemo implements Filter {
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {

        //1. 放行前,对 request数据进行处理
        System.out.println("1.hello FilterDemo~~");
        //放行
        filterChain.doFilter(servletRequest, servletResponse);
        //2.  放行后,对Response  数据进行处理
        System.out.println("5.hello FilterDemo~~");
    }

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    }

    @Override
    public void destroy() {
    }
}
//编写第二个过滤器 FilterDemo2 ,配置拦截所有资源
@WebFilter("/*")
public class FilterDemo2 implements Filter {
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        System.out.println("2.hello FilterDemo~~");

        //放行
        filterChain.doFilter(servletRequest,servletResponse);
        System.out.println("4.hello FilterDemo~~");
    }

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void destroy() {

    }
}
<!-- 修改 hello.jsp 页面中脚本的输出语句 -->
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<h1>hello JSP~</h1>
<%
    System.out.println("3.hello jsp");
%>
</body>
</html>
启动服务器,在浏览器输入 http://localhost/filter-demo/hello.jsp 进行测试

 

question

上面代码中为什么是先执行 FilterDemo ,后执行 FilterDemo2 呢?
使用的是注解配置Filter,而这种配置方式的优先级是按照过滤器类名(字符串)的自然排序。
比如两个名称的过滤器 :BFilterDemo和AFilterDemo,那一定是 AFilterDemo 过滤器先执行。

the case

需求
访问服务器资源时,需要先进行登录验证,如果没有登录,则自动跳转到登录页面

 

Code

创建Filter
在 brand-demo工程创建com.filter.web.filter包,在该下创建名为LoginFilter 的过滤器
@WebFilter("/*")
public class LoginFilter implements Filter {
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {

    }
    public void init(FilterConfig config) throws ServletException { }
    public void destroy() { }
}

write logic code 

在 doFilter() 方法中编写登陆状态校验的逻辑代码。
首先需要从 session 对象中获取用户信息,
但是 ServletRequest类型的requset对象没有获取session对象的方法,
所以此时需要将 request对象强转成 HttpServletRequest 对象。
HttpServletRequest req = (HttpServletRequest) request;
然后完成以下逻辑
获取Session对象
从Session对象中获取名为 user 的数据
判断获取到的数据是否是 null
    如果不是,说明已经登陆,放行
    如果是,说明尚未登陆,将提示信息存储到域对象中并跳转到登陆页面代码如下:

/**
 * 登录验证的过滤器
 */
@WebFilter("/*")
public class LoginFilter implements Filter {
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {

        HttpServletRequest req = (HttpServletRequest) request;//类型强转
        //1、判断session中是否有user
        HttpSession session = req.getSession();//获取session对象
        Object user = session.getAttribute("user");//根据键 取值

        //2、判断user是否为null
        if (user != null){
            //登录过 放行
            chain.doFilter(request, response);
        }else {
            //没登录 存储提示信息 跳转登录页面
            req.setAttribute("login_msg","您尚未登录");
            req.getRequestDispatcher("/login.jsp").forward(req,response);
        }
    }
    public void init(FilterConfig config) throws ServletException {
    }
    public void destroy() {
    }
}

test and ask questions

清理之前缓存的css 的cookie
在浏览器上输入 http://localhost:8080/brand-demo/ ,可以看到如下页面效果

 Problem analysis and solution

因为登陆页面需要 css/login.css 这个文件进行样式的渲染,下图是登陆页面引入的css文件图解

而在请求这个css资源时被过滤器拦截,就相当于没有加载到样式文件导致的。
解决这个问题,只需要对所以的登陆相关的资源进行放行即可。
还有一种情况就是当我没有用户信息时需要进行注册,而注册时也希望被过滤器放行。
需要在判断session中是否包含用户信息之前,应该加上对登陆及注册相关资源放行的逻辑处理
/**
 * 登录验证的过滤器
 */
@WebFilter("/*")
public class LoginFilter implements Filter {
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {

        HttpServletRequest req = (HttpServletRequest) request;//类型强转

        //判断访问资源路径是否和登录注册相关
        //1,在数组中存储登陆和注册相关的资源路径
        String[] urls = {"/login.jsp", "/imgs/", "/css/", "/loginServlet", "/register.jsp", "/registerServlet", "/checkCodeS ervlet"};
        //2,获取当前访问的资源路径
        String url = req.getRequestURL().toString();
        System.out.println(url);

        //3,遍历数组,获取到每一个需要放行的资源路径
        for (String u : urls) {
            //4,判断当前访问的资源路径字符串是否包含要放行的的资源路径字符串
            /*
            比如当前访问的资源路径是  /brand-demo/login.jsp
            而字符串 /brand-demo/login.jsp 包含了  字符串 /login.jsp ,所以这个字符串就需要放行
            */
            if (url.contains(u)) {
                //找到了,放行
                chain.doFilter(request, response);
                //break;
                return;
            }
        }

        //1、判断session中是否有user
        HttpSession session = req.getSession();//获取session对象
        Object user = session.getAttribute("user");//根据键 取值

        //2、判断user是否为null
        if (user != null) {
            //登录过 放行
            chain.doFilter(request, response);
        } else {
            //没登录 存储提示信息 跳转登录页面
            req.setAttribute("login_msg", "您尚未登录");
            req.getRequestDispatcher("/login.jsp").forward(req, response);
        }
    }

    public void init(FilterConfig config) throws ServletException {
    }

    public void destroy() {
    }
}

 Listener

概述
Listener 表示监听器,是 JavaWeb 三大组件(Servlet、Filter、Listener)之一。
监听器可以监听就是在application ,session ,request 
三个对象创建、销毁或者往其中添加修改删除属性时自动执行代码的功能组件。
application 是 ServletContext 类型的对象。
ServletContext 代表整个web应用,在服务器启动的时候,tomcat会自动创建该对象。
在服务器关闭时会自动销毁该对象。

Classification

JavaWeb provides 8 listeners:

ServletContextListener 是用来监听ServletContext 对象的创建和销毁。
ServletContextListener 接口中有以下两个方法
void contextInitialized(ServletContextEvent sce) :ServletContext 对象被创建了会自动执行的方法
void contextDestroyed(ServletContextEvent sce) :ServletContext 对象被销毁时会自动执行的方法

 code demo

定义一个类,实现 ServletContextListener 接口
重写所有的抽象方法
使用 @WebListener 进行配置
代码如下:
@WebListener
public class ContextLoaderListener implements ServletContextListener {
    @Override
    public void contextInitialized(ServletContextEvent servletContextEvent) {
        //加载资源
        System.out.println("ContextLoaderListener....");
    }

    @Override
    public void contextDestroyed(ServletContextEvent servletContextEvent) {
        //释放资源
    }
}

//启动服务器,就可以在启动的日志信息中看到 contextInitialized() 方法输出的内容,
//同时也说明了 ServletContext对象在服务器启动的时候被创建了。

Ajax

AJAX (Asynchronous JavaScript And XML):异步的 JavaScript 和 XML。
AJAX 作用有以下两方面:
1. 与服务器进行数据交换:通过AJAX可以给服务器发送请求,服务器将数据直接响应回给浏览器
    使用AJAX和服务器进行通信,以达到使用 HTML+AJAX来替换JSP页面了。
2. 异步交互:可以在不重新加载整个页面的情况下,与服务器交换数据并更新部分网页的技术,
如:搜索联想、用户名是否可用校验,等等.
Servlet 调用完业务逻辑层后将数据存储到域对象中,然后跳转到指定的 jsp 页面,
在页面上使用 EL表达式 和JSTL 标签库进行数据的展示。

 

如下图,浏览器发送请求servlet,servlet 调用完业务逻辑层后将数据直接响应回给浏览器页面,页面使用 HTML 来进行数据展示。

 

在用户名的输入框输入用户名,当输入框一失去焦点,如果用户名已经被占用就会在下方展示提示的信息;
在这整个过程中也没有页面的刷新,只是在局部展示出了提示信息,这就是 更新局部页面 的效果。

 

 synchronous and asynchronous

 The process of sending a request synchronously

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

The asynchronous sending request process is as follows 

 

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

AJAX Quick Start

Server implementation

在项目的创建 com.green.web.servlet ,并在该包下创建名为 AjaxServlet 的servlet
@WebServlet("/ajaxServlet")
public class AjaxServlet extends HttpServlet { 

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    //1. 响应数据
    response.getWriter().write("hello ajax~"); }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws    ServletException, IOException {
this.doGet(request, response); 
    }
}
客户端实现
在 webapp 下创建名为 01-ajax-demo1.html 的页面,在该页面书写 ajax 代码
创建核心对象,不同的浏览器创建的对象是不同的
var xhttp;
if (window.XMLHttpRequest) {
xhttp = new XMLHttpRequest(); } else {
// code for IE6, IE5
xhttp = new ActiveXObject("Microsoft.XMLHTTP"); }

 send request

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

get response 

xhttp.onreadystatechange = function() {
    if (this.readyState == 4 && this.status == 200) {
        // 通过 this.responseText 可以获取到服务端响应的数据
        alert(this.responseText); 
    }
};

 full code

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>


<script>
    //1、创建核心对象
    var xhttp;
    if (window.XMLHttpRequest) {
        xhttp = new XMLHttpRequest();
    } else {
        // code for IE6, IE5
        xhttp = new ActiveXObject("Microsoft.XMLHTTP");
    }
    
    //2、发送请求
    /**
     * open(method, url, async)  规定请求的类型
             method:请求的类型:GET 还是 POST
             url:服务器(文件)位置
             async:true(异步)或 false(同步)
     * send()向服务器发送请求(用于 GET)
     * send(string)向服务器发送请求(用于 POST)
     */
    xhttp.open("GET", "http://localhost:8080/ajax-demo/ajaxServlet");
    xhttp.send();

    //3、获取响应
    /**
     * readyState:保存了 XMLHttpRequest 的状态。
                 0: 请求未初始化
                 1: 服务器连接已建立
                 2: 请求已接收
                 3: 正在处理请求
                 4: 请求已完成且响应已就绪
     * status:响应状态码
                 200: "OK"
                 403: "Forbidden"
                 404: "Page not found"
     */
    xhttp.onreadystatechange = function() {
        if (this.readyState == 4 && this.status == 200) {
                alert(this.responseText);//此处是AjaxServlet的响应数据
        }
    };
    
</script>
</body>
</html>

test 

在浏览器地址栏输入 http://localhost:8080/ajax-demo/01-ajax-demo1.html ,
在 01-ajax-demo1.html 加载的时候就会发送 ajax 请求,效果如下

 

可以通过 开发者模式 查看发送的 AJAX 请求。在浏览器上按 F12 快捷键

 

the case

需求:在完成用户注册时,当用户名输入框失去焦点时,校验用户名是否在数据库已存在

 analyze

前端完成的逻辑
    1. 给用户名输入框绑定光标失去焦点事件 onblur
    2. 发送 ajax请求,携带username参数
    3. 处理响应:是否显示提示信息
后端完成的逻辑
    1. 接收用户名
    2. 调用service查询User。此案例是为了演示前后端异步交互,所以此处我们不做业务逻辑处理
    3. 返回标记

 backend implementation

在 com.green.web.servlet 包中定义名为 SelectUserServlet 的servlet。代码如下
package com.green.web.servlet;

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

@WebServlet("/selectUserServlet")
public class SelectUserServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //1、接收前端数据username
        String username = request.getParameter("username");

        //2、调用service查询用户名是否存在
        boolean flag = true;

        //3、响应标记
        response.getWriter().write("" + flag);
    }

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

Front-end implementation

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>欢迎注册</title>
    <link href="css/register.css" rel="stylesheet">
</head>
<body>

<div class="form-div">
    <div class="reg-content">
        <h1>欢迎注册</h1>
        <span>已有帐号?</span> <a href="login.html">登录</a>
    </div>
    <form id="reg-form" action="#" method="get">

        <table>

            <tr>
                <td>用户名</td>
                <td class="inputs">
                    <input name="username" type="text" id="username">
                    <br>
                    <span id="username_err" class="err_msg" style="display: none">用户名已存在</span>
                </td>

            </tr>

            <tr>
                <td>密码</td>
                <td class="inputs">
                    <input name="password" type="password" id="password">
                    <br>
                    <span id="password_err" class="err_msg" style="display: none">密码格式有误</span>
                </td>
            </tr>


            <tr>
                <td>验证码</td>
                <td class="inputs">
                    <input name="checkCode" type="text" id="checkCode">
                    <img src="imgs/a.jpg">
                    <a href="#" id="changeImg">看不清?</a>
                </td>
            </tr>

        </table>

        <div class="buttons">
            <input value="注 册" type="submit" id="reg_btn">
        </div>
        <br class="clear">
    </form>

</div>

<script>
    //1、给用户名输入框绑定事件  失去焦点事件
    document.getElementById("username").onblur = function () {
        //2、发送ajax请求

        //获取用户名的值
        var username = this.value;   //this : 给谁绑定的事件,this就代表谁

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

        //2.2、发送请求
        xhttp.open("GET", "http://localhost:8080/ajax-demo/selectUserServlet?username=" + username);
        xhttp.send();

        //2.3、获取响应
        xhttp.onreadystatechange = function () {
            if (this.readyState == 4 && this.status == 200) {
                //alert(this.responseText);//此处是AjaxServlet的响应数据
                //判断
                if (this.responseText == "true") {
                    //用户名存在,提示信息
                    document.getElementById("username_err").style.display = '';
                } else {
                    //用户名不存在,清除提示信息
                    document.getElementById("username_err").style.display = 'none';
                }
            }
        };
    }

</script>
</body>
</html>

Axios asynchronous framework

Axios 对原生的AJAX进行封装,简化书写。
Axios官网是: https://www.axios-http.cn

basic use

axios 使用分为以下两步:
引入 axios 的 js 文件
<script src="js/axios-0.18.0.js"></script>
使用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);
    });

axios() 是用来发送异步请求的,小括号中使用 js 对象传递请求相关的参数:
method 属性:用来设置请求方式的。取值为 get 或者 post 。
url 属性:用来书写请求的资源路径。如果是 get 请求,需要将请求参数拼接到路径的后面,格式为: url?参数名=参数值&参数名2=参数值2 。
data 属性:作为请求体被发送的数据。也就是说如果是post请求的话,数据需要作为data属性的值。

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

quick start

backend implementation


@WebServlet("/axiosServlet")
public class AxiosServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("get......");

        //1、接收请求参数
        String username = request.getParameter("username");
        System.out.println(username);

        //2、响应数据
        response.getWriter().write("hello axios~~");
    }

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

Front-end implementation

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

<script src="js/axios-0.18.0.js"></script>
<script>
    /*//1、get
    axios({
        method:"get",
        url:"http://localhost:8080/ajax-demo/axiosServlet?username=zhangsan"
    }).then(function (resp){
        alert(resp.data);
    })
*/
    //2、post
    axios({
        method:"post",
        url:"http://localhost:8080/ajax-demo/axiosServlet",
        data:"username=zhangsan"
    }).then(function (resp){
        alert(resp.data);
    })
</script>

</body>
</html>

 request method alias

为了方便起见, 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 请求代码可以改为如下:
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":"北京"
}
js 对象格式和 json 格式进行对比,发现两个格式特别像。
只不过 js 对象中的属性名可以使用引号(可以是单引号,也可以是双引号);
而 json 格式中的键要求必须使用双引号括起来,这是 json 格式的规定

Basic syntax of JSON

定义格式
JSON 本质就是一个字符串,但是该字符串内容是有一定的格式要求的。 定义格式如下:
var 变量名 = '{"key":value,"key":value,...}';
JSON 串的键要求必须使用双引号括起来,而值根据要表示的类型确定。value 的数据类型分为如下
数字(整数或浮点数)
字符串(使用双引号括起来)
逻辑值(true或者false)
数组(在方括号中)
对象(在花括号中)
null
例:var jsonStr = '{"name":"zhangsan","age":23,"addr":["北京","上海","西安"]}'
获取数据:变量名.key
jsonStr.name

code demo

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

<script>

    //定义JSON
    var  json = {
        "name":"zhangsan",
        "age":23,
        "addr":["北京","上海","深圳"]
    };

    //获取值
    alert(json.name);

</script>

</body>
</html>

JSON data and Java object conversion

请求数据:JSON字符串转换为js对象
响应数据:js对象转换为JSON字符串

Fastjson overview

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

Fastjson uses

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()静态方法

 code demo

引入坐标
创建User类和FastJsonDemo类 ,专门用来测试 Java 对象和 JSON 串的相互转换,代码如下:
package com.green.web.json;
import com.alibaba.fastjson.JSON;
public class FastJsonDemo {
    public static void main(String[] args) {
        //1、将Java对象转换成JSON字符串
        User user = new User();
        user.setId(1);
        user.setUsername("zhagnsan");
        user.setPassword("123");

        String jsonString = JSON.toJSONString(user);
        System.out.println(jsonString);//{"id":1,"password":"123","username":"zhagnsan"}

        //2、将JSON字符串转换成Java对象
        //User u = JSON.parseObject("{\"id\":1,\"password\":\"123\",\"username\":\"zhagnsan\"}", User.class);
        User u = JSON.parseObject(jsonString, User.class);
        System.out.println(u);
    }
}

the case

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

 

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

new brand

点击 新增 按钮,会跳转到 addBrand.html 页面。
在 addBrand.html 页面输入数据后点击 提交 按钮,
就会将数据提交到后端,而后端将数据保存到数据库中。
说明:
前端需要将用户输入的数据提交到后端,这部分数据需要以 json 格式进行提交

 

 backend implementation

在 com.green.web 包下创建名为 AddServlet 的 servlet ,具体的逻辑如下:
获取请求参数
由于前端提交的是 json 格式的数据,所以不能使用 request.getParameter() 方法获取请求参数
如果提交的数据格式是username=zhangsan&age=23 ,后端就可以使用request.getParameter() 方法获取
如果提交的数据格式是 json,后端就需要通过 request 对象获取输入流,再通过输入流读取数据
将获取到的请求参数(json格式的数据)转换为 Brand 对象
调用 service 的 add() 方法进行添加数据的逻辑处理
将 json 数据响应回给浏览器。
@WebServlet("/addServlet")
public class AddServlet extends HttpServlet {

private BrandService brandService = new BrandService();

@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException 
{
    //1. 接收数据,request.getParameter 不能接收json的数据
    /* String brandName = request.getParameter("brandName");
    System.out.println(brandName);*/

    //  获取请求体数据
    BufferedReader br = request.getReader(); 
    String params = br.readLine();
    //  将JSON字符串转为Java对象
    Brand brand = JSON.parseObject(params, Brand.class);
    //2. 调用service 添加
    brandService.add(brand);
    //3. 响应成功标识
    response.getWriter().write("success");
}


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

Front-end implementation

在 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 formData = {
            brandName: "",
            companyName: "",
            ordered: "",
            description: "",
            status: "",
        };
        // 获取表单数据
        let brandName = document.getElementById("brandName").value;
        // 设置数据
        formData.brandName = brandName;

        // 获取表单数据
        let companyName = document.getElementById("companyName").value;
        // 设置数据
        formData.companyName = companyName;

        // 获取表单数据
        let ordered = document.getElementById("ordered").value;
        // 设置数据
        formData.ordered = ordered;

        // 获取表单数据
        let description = document.getElementById("description").value;
        // 设置数据
        formData.description = description;

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

        console.log(formData);
        //2. 发送ajax请求
        axios({
            method: "post",
            url: "http://localhost:8080/brand-demo/addServlet",
            data: formData
        }).then(function (resp) {
            // 判断响应数据是否为 success
            if (resp.data == "success") {
                location.href = "http://localhost:8080/brand-demo/brand.html";
            }
        })
    }


</script>
</body>
</html>

Guess you like

Origin blog.csdn.net/weixin_52270382/article/details/130166414