黑马就业班(02.JavaWeb+项目实战\13.Ajax数据交互 JSON Web异步开发))

本文介绍了AJAX的概念和两种实现方式,包括原生JS和JQuery,并强调了AJAX的异步特性。同时,详细讲解了JSON的含义和使用,以及JSON与JQuery对象的区别。此外,还探讨了JSON数据与Java对象的转换,并提供了一个使用Ajax进行用户名校验的案例,展示了Ajax在不刷新页面的情况下与服务器交互的优势。
摘要由CSDN通过智能技术生成
  • 本文参考自己的项目:myday13part2(动态web项目)
    在这里插入图片描述
  • 注意区分JQuery与JSON,JQuery是JS的框架,用于简化JS的开发;而JSON是JS的对象表示法,用于表示JS的封装各类数据(键值对形式)的对象

今日内容

1. AJAX:
2. JSON

1、AJAX
  概念: ASynchronous JavaScript And XML 异步的JavaScript 和 XML。
  异步和同步:客户端和服务器端相互通信的基础上。(见视频2的解析)

* 客户端必须等待服务器端的响应。在等待的期间客户端不能做其他操作。
* 客户端不需要等待服务器端的响应。在服务器处理请求的过程中,客户端可以进行其他的操作。

Ajax 是一种在无需重新加载整个网页的情况下,能够更新部分网页的技术。 [1] 
通过在后台与服务器进行少量数据交换,Ajax 可以使网页实现异步更新。这意味着可以在不重新加载整个网页的情况下,对网页的某部分进行更新。
传统的网页(不使用 Ajax)如果需要更新内容,必须重载整个网页页面。

我们对小部分的网页进行异步更新,在更新的请求与响应的过程中,网页的其他部分同样可以进行其他请求与响应的操作;而如果使用同步的方式,我们想更新这一部分,网页的其他部分不能进行操作,这就必须要重新加载整个页面,保证在这一部分请求与响应的过程中,网页的其他部分没有其他的请求与响应。
实现方式1

  原生的JS实现方式(了解)。这一部分参考文档:w3school文档 ,十分麻烦,代码的方式基本固定,不需要记住,了解即可,需要用到再看文档。
  记得创建一个动态Web项目,在web目录下创建一个js目录,并导入相应的JQuery的包。

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

        <script>
            //原生JS实现AJAX(了解就可以)

            //定义方法
            function fun() {
                //我们点击这个按钮会执行fun()函数,在fun()函数中发送异步请求

                //1.创建核心对象
                var xmlhttp;
                if (window.XMLHttpRequest)
                {// code for IE7+, Firefox, Chrome, Opera, Safari
                    xmlhttp=new XMLHttpRequest();
                }
                else
                {// code for IE6, IE5
                    xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
                }

                //2.建立链接
                /*
               参数:
                   1. 请求方式:GET、POST
                       * get方式,请求参数在URL后边拼接。send方法为空参
                       * post方式,请求参数在send方法中定义
                   2. 请求的URL:
                   3. 同步或异步请求:true(异步)或 false(同步)

                */
                xmlhttp.open("GET","ajaxServlet?username=tom",true);

                //3.发送请求
                xmlhttp.send();

                //4.接受并处理来自服务器的响应结果
                //获取响应内容的方式 :xmlhttp.responseText,注意,我们必须等服务器响应成功后再获取,否则获取错误
                //当xmlhttp对象的就绪状态改变时,触发事件onreadystatechange。
                xmlhttp.onreadystatechange=function()
                {
                    //判断readyState就绪状态是否为4,判断status响应状态码是否为200
                    if (xmlhttp.readyState==4 && xmlhttp.status==200)
                    {
                        //响应成功,获取服务器的响应结果
                        var responseText = xmlhttp.responseText;
                        alert(responseText);
                    }
                }
            }

        </script>

    </head>
    <body>
        <input type="button" value="发送异步请求" onclick="fun();">
        <input>
    </body>
</html>

  为了测试,我们创建一个Servlet:lkj.web.servlet.AjaxServlet。

package lkj.web.servlet;

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("/ajaxServlet")
public class AjaxServlet extends HttpServlet
{
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
    {
        //1.获取请求参数
        String username = request.getParameter("username");

        //处理业务逻辑。耗时
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        //我们将请求设置为同步,然后访问http://localhost/JSRealize1.html,点击发送异步请求,就会访问AjaxServlet,
        // 此时会在这里延时5秒,而延时的过程中,页面的其他部分不能进行操作,因此在5秒内我们点击文本框,没有反应。
        //如果换为异步请求,5秒内我们也可以点击文本框获取其焦点,既异步请求的过程中,我们也可以对页面的其他部分进行操作。

        //2.打印username
        System.out.println(username);
        //3.响应
        response.getWriter().write("hello:"+username);//本来response往浏览器写出数据应该先设置编码为UTF-8,但是这里不写,因为只输出英文。

        //response.setContentType("text/html;charset=utf-8");//设置流的编码方式并告诉浏览器用什么方式解码

    }

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

  我们先访问:JSRealize1.html,点击按钮“发送异步请求”,控制台打印username-“tom”,说明连接成功。(此时我们还没有设置页面接收服务器的响应)
  我们添加一个的文本输入框,刷新JSRealize1.html,并往这个文本框写一些字。
在这里插入图片描述

实现方式2

  JQeury实现方式

1. $.ajax()  (通用方式,对get与post都适用)
	* 语法:$.ajax({键值对});

  这里使用的是前面的AjaxServlet。

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <!--注意,要使用JQuery的异步方式,必须先导入JQuery的包!-->
        <script src="js/jquery-3.3.1.min.js"></script>
        <script>
            //定义方法
            function  fun() {
                //使用$.ajax()发送异步请求(注意格式!!!)
                $.ajax({
                    url:"ajaxServlet111",  //请求的资源路径
                    type:"POST",        //请求方式
                    // data:"username=tom$age=23",  //请求参数

                    //可以将请求参数写为JSON的样式(注意样式)
                    data:{"username":"tom" , "age":23},
                    success:function (data) {//回调函数的参数会接收服务器响应回的数据
                        alert(data);
                    },//响应成功后的回调函数,响应成功后会自动执行这个函数
                    error:function () {
                        alert("出错啦...");//比如我们将路径改为错误的路径
                    },//表示如果请求响应出现错误,会执行的回调函数
                    dataType:"text"  //设置接受到的响应数据的格式,没有设置浏览器会自己识别
                });

            }
        </script>

    </head>
    <body>
        <input type="button" value="发送异步请求" onclick="fun();">

        <input>
    </body>
</html>

  JQeury实现方式

2. $.get():发送get请求
	* 语法:$.get(url, [data], [callback], [type])
		* 参数:
			* url:请求路径
			* data:请求参数
			* callback:回调函数,相当于$.ajax()的success属性
			* type:响应结果的类型

3. $.post():发送post请求
	* 语法:$.post(url, [data], [callback], [type])
		* 参数:
			* url:请求路径
			* data:请求参数
			* callback:回调函数
			* type:响应结果的类型

  这里使用的是前面的AjaxServlet。

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <script src="js/jquery-3.3.1.min.js"></script>
        <script>
            function fun() {
                //使用$.get方式发送异步请求
                $.get("ajaxServlet" , {"username":"zhangsan"} , function (data) {
                    alert(data);
                } , "text");//后面3个参数可选
            }


            function fun() {
                //使用$.post方式发送异步请求
                $.post("ajaxServlet" , {"username":"lisi"} , function (data) {
                    alert(data);
                } , "text");
            }

        </script>
    </head>
    <body>
        <input type="button" value="发送异步请求" onclick="fun();">

        <input>
    </body>
</html>

2、JSON
  概念: JavaScript Object Notation JavaScript对象表示法(见视频8解析)

Person p = new Person();
p.setName("张三");
p.setAge(23);
p.setGender("男");

在JS中,我们也想像上面的java一样搞一个对象来封装这些零散的数据。就可以使用JSON来表示对象。
var p = {"name":"张三","age":23,"gender":"男"};

* json现在多用于存储和交换文本信息的语法
* 进行数据的传输
* JSON 比 XML 更小、更快,更易解析。

  语法

1.基本规则
	* 数据在名称/值对中:json数据是由键值对构成的
		* 键用引号(单双都行)引起来,也可以不使用引号
		* 值得取值类型:
			1. 数字(整数或浮点数)
			2. 字符串(在双引号中)
			3. 逻辑值(truefalse4. 数组(在方括号中)	{"persons":[{},{}]}
			5. JSON对象(在花括号中) {"address":{"province""陕西"....}}
			6. null
	* 数据由逗号分隔:多个键值对由逗号分隔
	* 花括号保存对象:使用{}定义json 格式
	* 方括号保存数组:[]

2. 获取数据:
	1. json对象.键名
	2. json对象["键名"]
	3. 数组对象[索引]
	4. 遍历

  值的获取测试代码

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

        <script>
            //注意,JSON是JS的对象表示法,因此必须写在<script>标签中

            //1.定义基本格式
            var person = {"name":"zhangsan" , age:23 , 'gender':true};
            // alert(person);//[object Object]
            //获取name的值
            // var name = person.name;
            // var name = person["name"];
            // alert(name);

            //2.嵌套格式1   {}———> []
            var persons = {
              "persons":[
                  {"name":"张三" , "age":23 , "gender":true},
                  {"name":"李四" , "age":24 , "gender":false},
                  {"name":"王五" , "age":52 , "gender":true}
              ]
            };
            // alert(persons);//[object Object]
            //获取王五值
            // var name1 = persons.persons[2].name;//先获取数组角标为2的对象,再获取这个对象的name键的值
            // alert(name1);

            //2.嵌套格式   []———> {}
            var ps = [{"name": "张三", "age": 23, "gender": true},
                {"name": "李四", "age": 24, "gender": true},
                {"name": "王五", "age": 25, "gender": false}];
            // alert(ps);//[object Object],[object Object],[object Object]
            //获取李四值
            var name2 = ps[1].name;
            alert(name2);

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

  遍历测试代码**(注意区分JQuery的遍历方式与JSON的遍历方式,JQuery是JS的框架,而JSON是JS的对象表示法)**
  注意,JSON是JS对象的表示法,既它也是JS,那么我们也可以将JSON转换为JQ对象并使用JQ的遍历方法!

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

        <script>
            //1.定义基本格式
            var person = {"name": "张三", age: 23, 'gender': true};

            var ps = [{"name": "张三", "age": 23, "gender": true},
                {"name": "李四", "age": 24, "gender": true},
                {"name": "王五", "age": 25, "gender": false}];

            //for in 循环  :获取person对象中所有的键和值
            for(var key in person)
            {
                //这样的方式获取不行。因为key获取出来是字符串格式"name",这样相当于  person."name"
                // alert(person.key);
                alert(person[key]);
            }

            //获取ps中的所有值
            for(var i=0 ; i<ps.length ;i++)
            {
                var p = ps[i];
                for(var key in p)
                {
                    alert(key+":"+p[key]);
                }
            }
        </script>
    </head>
    <body>
        
    </body>
</html>

3、JSON数据和Java对象的相互转换
  为什么JSON数据与java的对象要互换?(视频11解析)

JSON解析器
* 常见的解析器:Jsonlib,Gson,fastjson,jackson(SpringMVC框架内置的解析器)

  装换方法

JSON转为Java对象
	1) 导入jackson的相关jar包
	2) 创建Jackson核心对象 ObjectMapper
	3) 调用ObjectMapper的相关方法进行转换
		1. readValue(json字符串数据,Class)
Java对象转换JSON,使用步骤:
1. 导入jackson的相关jar包(放入web下的WEB-INF的lib包中)
2. 创建Jackson核心对象 ObjectMapper
3. 调用ObjectMapper的相关方法进行转换
	1) 转换方法:
		* writeValue(参数1,obj):
                  参数1:
                      File:将obj对象转换为JSON字符串,并保存到指定的文件中
                      Writer:将obj对象转换为JSON字符串,并将json数据填充到字符输出流中(可以写入File的Writer流,也可以写入其他类型的流)
                      OutputStream:将obj对象转换为JSON字符串,并将json数据填充到字节输出流中
        	
        * writeValueAsString(obj):将对象转为json字符串

	2) 注解:
		1. @JsonIgnore:排除属性。
		2. @JsonFormat:属性值的格式化
			* @JsonFormat(pattern = "yyyy-MM-dd")

	3) 复杂java对象转换
		1. List:数组
		2. Map:对象格式一致

  我们可以在服务器端将数据转换为JSON数据,并将JSON数据发送到客户端,客户端浏览器(支持JS语言)可以解析JSON,而且,通过Ajax的形式也可以解析JSON。
  代码如下,包括domain类Person.java,test包下的JacksonTest.java(使用Test注解测试),

package lkj.test;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import lkj.domain.Person;
import org.junit.Test;

import java.io.File;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.util.*;

public class Jackson
{
    //Java对象转换为JSON的方法测试
    @Test
    public void test1() throws Exception
    {
        //1、创建Person对象并给各个属性赋值
        Person p  = new Person();
        p.setName("张三");
        p.setAge(23);
        p.setGender("男");

        //2、创建Jackson的核心对象  ObjectMapper
        ObjectMapper om = new ObjectMapper();

        //3、转换
//        String json = om.writeValueAsString(p);
//        System.out.println(json);//{"name":"张三","age":23,"gender":"男"}

        //writeValue,将数据写到d://a.txt文件中
        om.writeValue(new File("d://a.txt"), p);//对应位置文件夹内容为:{"name":"张三","age":23,"gender":"男"}

        //writeValue.将数据关联到Writer中,使用FileWrite将数据写入d://b.txt
        om.writeValue(new FileWriter("d://b.txt") , p);

        //同样,使用FileOutputStream将数据写入d://c.txt
        om.writeValue(new FileOutputStream("d://c.txt") , p);
    }

    //JSON 注解
    @Test
    public void test2() throws Exception
    {
        //1.创建Person对象
        Person p = new Person();
        p.setName("张三");
        p.setAge(23);
        p.setGender("男");
        p.setBirthday(new Date());

        //2.将p对象抓换为JSON对象
        ObjectMapper om = new ObjectMapper();
        String json = om.writeValueAsString(p);

        System.out.println(json);//{"name":"张三","age":23,"gender":"男","birthday":1582947909327},我们不希望birthday的格式是毫秒值
        //注意,注解@JsonIgnore与@JsonFormat都是应用在要转换为JSON对象的java类中对应的属性
        //忽略birthday属性:{"name":"张三","age":23,"gender":"男"}
        //给birthday属性设置格式:pattern = "yyyy:MM:dd",最后打印:{"name":"张三","age":23,"gender":"男","birthday":"2020:02:29"}
    }

    //复杂java对象List与Map抓换为JSON
    @Test
    public void test3() throws Exception
    {
        //1.创建Person对象
        Person p = new Person();
        p.setName("张三");
        p.setAge(23);
        p.setGender("男");
        p.setBirthday(new Date());

        Person p1 = new Person();
        p1.setName("张三");
        p1.setAge(23);
        p1.setGender("男");
        p1.setBirthday(new Date());

        Person p2 = new Person();
        p2.setName("张三");
        p2.setAge(23);
        p2.setGender("男");
        p2.setBirthday(new Date());

        List<Person> list = new ArrayList<Person>();
        list.add(p);
        list.add(p1);
        list.add(p2);

        ObjectMapper om = new ObjectMapper();
        String json = om.writeValueAsString(list);
        System.out.println(json);
//[{"name":"张三","age":23,"gender":"男","birthday":"2020:02:29"},{"name":"张三","age":23,"gender":"男","birthday":"2020:02:29"},{"name":"张三","age":23,"gender":"男","birthday":"2020:02:29"}]
    }

    @Test
    public void test4() throws Exception
    {
        //1.创建map对象
        Map<String , Object> map = new HashMap<String , Object>();
        map.put("name" , "张三");
        map.put("age" , 23);
        map.put("gender" , "男");

        ObjectMapper om = new ObjectMapper();
        String json = om.writeValueAsString(map);
        System.out.println(json);//{"gender":"男","name":"张三","age":23}
    }


    //JSON转为Java对象
    @Test
    public void test5() throws Exception
    {
        //1.初始化JSON字符串
        String json = "{\"gender\":\"男\",\"name\":\"张三\",\"age\":23}";//这里也可以将/" 换为'

        //2.创建ObjectMapper对象
        ObjectMapper om = new ObjectMapper();

        //3.转换为Java对象 Person对象
        Person person = om.readValue(json, Person.class);
        System.out.println(person);//"gender":"男","name":"张三","age":23
    }
}

3、案例
  校验用户名是否存在。
  之前是使用JS校验用户名的格式是否正确,是在浏览器本地使用正则表达式验证。而这里需要用户名区域失去焦点的时候去访问数据库,查询数据库是否存在相应的用户名。这里需要使用Ajax的方式发送请求,因为在校验的时候,Ajax请求的方式不会影响页面的其他区域的操作,也就是不需要整个页面发送请求到服务器去验证这个用户名。

服务器响应的数据,在客户端使用时,要想当做json数据格式使用。有两种解决方案:
	1. $.get(type):将最后一个参数type指定为"json"
	2. 在服务器端设置MIME类型
		response.setContentType("application/json;charset=utf-8");//JSON的MIME类型是application/json

  相应的代码与说明如下:

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <script src="js/jquery-3.3.1.min.js"></script>
        <script>
            //在页面加载完成后执行下列代码
            $(function () {
                //给username绑定blur事件
                $("#username").blur(function () {
                    //当文本框失去焦点,我们获取它的值并发送给服务器进行验证
                    /*
                    注意,不管是前面JQ的each遍历下设置的回调函数,还是这种JQ普通事件下的回调函数,下面所使用的this都是代表JS对象,
                    且each的function中所使用的element元素,也是JS对象。
                     */
                    var username = $(this).val();//使用JQ的方法获取username输入框的内容

                    /*
                    发送ajax请求,使用get方式,期望服务器响应回的数据格式:
                   {"userExsit":true,"msg":"此用户名太受欢迎,请更换一个"}
                   {"userExsit":false,"msg":"用户名可用"}
                     */
                    $.get("findUserServlet" , {"username":username} , function (data) {
                        //alert(data);//返回的data是JSON数据
                        /*
                        如果我们在FindUserServlet中没有设置返回消息的字符集以及推荐解析的方式,返回的data数据为:{"userExsit":false,"msg":"?????"},
                        我们响应回来的仅仅是一个字符串,而浏览器没有将其当做JSON处理,因此我们没有办法通过JSON的方式获取数据。
                        其次,我们没有设置返回数据的字符集与浏览器相同,解析的中文内容出现乱码。

                        1、我们可以在get请求中指定接收的数据为JSON类型,这样返回数据data数据为:[object Object],被当做JSON处理。
                        而且用户名后面显示出绿/红颜色的数据,但是数据的编码不相同仍然是乱码。
                        然后我们在FindUserServlet设置 response.setContentType("text/html;charset=utf-8");,这样中文乱码问题也解决。

                        2、在FindUserServlet设置:response.setContentType("application/json;charset=utf-8");
                        这样直接设置了浏览器解析的字符集以及JSON的MIME类型,浏览器接收到会直接识别MIME类型将数据作为JSON处理
                         */


                        //获取返回的JSON数据中的 userExsit 键的值
                        var userExsit = data.userExsit;
                        //获取id="s_username"的span区域的JQ对象
                        var span = $("#s_username");

                        if(userExsit)
                        {
                            //用户名存在
                            span.css("color","red");//将span区域的文字设置为红色
                            span.html(data.msg);//将JSON中存储的msg数据取出
                        }
                        else
                        {
                            //用户名不存在
                            span.css("color" , "green");
                            span.html(data.msg);
                        }
                    } );
                });

            });

        </script>

    </head>

    <body>

        <form>
            <input type="text" id="username" name="username" placeholder="请输入用户名">
            <span id="s_username"></span>
            <br>
            <input type="password" name="password" placeholder="请输入密码"><br>
            <input type="submit" value="注册"><br>
        </form>

    </body>
</html>
package lkj.web.servlet;

import com.fasterxml.jackson.databind.ObjectMapper;

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.HashMap;
import java.util.Map;

@WebServlet("/findUserServlet")
public class FindUserServlet extends HttpServlet
{
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
    {
        //1.获取用户名
        String username = request.getParameter("username");

        /*
            发送ajax请求,使用get方式,期望服务器响应回的数据格式:
           {"userExsit":true,"msg":"此用户名太受欢迎,请更换一个"}
           {"userExsit":false,"msg":"用户名可用"}
         */

        //设置响应的数据格式为json
        response.setContentType("application/json;charset=utf-8");//注意JSON的MIME格式,这里设置JSON的MIME格式,浏览器接收到会直接识别将数据作为JSON处理
//        response.setContentType("text/html;charset=utf-8");

        //由于我们要返回的数据是json,而且是键值对的数据,我们可以将相应的数据封装为Map集合,再抓换为JSON发送回浏览器
        Map<String , Object> map = new HashMap<String , Object>();
        //本来应该调用service层查询数据库,这里为了方便演示就拿一个数据测试就可以
        if("Tom".equals(username))
        {
            map.put("userExsit" , true);
            map.put("msg" , "此用户名太受欢迎,请更换一个");
        }
        else
        {
            map.put("userExsit" , false);
            map.put("msg" , "用户名可用");
        }

        //最后,将Map集合抓换为JSON对象并发送回客户端
        ObjectMapper om = new ObjectMapper();//先获取JSON解析器Jackson核心对象(注意先导包)
        //将Map抓换为JSON对象并发送回去
        om.writeValue(response.getWriter() , map);//直接转换并写入Response对想的写出流
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
    {
        this.doPost(request, response);
    }
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值