学习JavaWeb(九)——AJAX和JSON

前言

我们来学习ajax和json。

 

 

 

 


AJAX

概念

Ajax 即“Asynchronous Javascript And XML”(异步 JavaScript 和 XML),是指一种创建交互式、快速动态网页应用的网页开发技术,无需重新加载整个网页的情况下,能够更新部分网页的技术(局部刷新)

通过在后台与服务器进行少量数据交换,Ajax 可以使网页实现异步更新。这意味着可以在不重新加载整个网页的情况下,对网页的某部分进行更新。

 

使用AJAX主要是为了提升用户的体验。

 

关于网络请求中的同步与异步;

 

实现方式

原生js的方式

原生的方式可以参考这里的记录

测试代码:

<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script>
        function fun() {
            //发送异步请求
            //1.创建核心对象
            var xmlhttp;
            if(window.XMLHttpRequest){
                //  IE7+, Firefox, Chrome, Opera, Safari 浏览器执行代码
                xmlhttp=new XMLHttpRequest();
            }else {
                // IE6, IE5 浏览器执行代码
                xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
            }
            //2.建立连接
            /*
                参数:
                1.请求方式:GET、POST
                    * GET:请求参数在URL后面拼接。send方法为空参
                    * POST:请求参数在send方法中定义
                2.请求的URL
                3.同步或异步请求:true(异步)false(同步)
             */
            xmlhttp.open("GET","ajaxDemoServlet?username=tom",true);
            //3.发送请求
            xmlhttp.send();
        }
    </script>
</head>
<body>
    <input type="button" value="发送异步请求" onclick="fun();" /><br/>
    <input type="text" placeholder="测试同/异步的文本框" />
</body>

对应Servlet

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //1.获取请求参数
        String username = request.getParameter("username");
        //2.打印username
        System.out.println(username);
        //3.响应
        response.getWriter().write("Hello  "+username);
    }

接下来我们在页面中点击按钮后,服务器端的控制台就会打印tom。

另外,这里我们可以更真切的感受到同步与异步的差别,我们上面的open方法后面的参数改成false(即同步请求),然后在服务端的Servlet里响应前卡断一下:

        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

重部署一下,然后在页面中,当你点击按钮后,你会发现下面的文本框就无法对焦了,因为服务端被“睡眠”了5秒,同步的ajax还没有得到响应;5秒以后,即恢复正常。

再改成true使用异步,即可体验到异步的优势了。

对于响应的处理,我们在index.html中的script声明的方法中继续处理:

            //4.接收并处理来自服务器的响应结果
            //获取方式:xmlhttp.responseText
            //当服务器响应成功之后获取
            //当xmlhttp对象的就绪状态改变时,触发事件onreadystatechange
            xmlhttp.onreadystatechange=function(){
                //判断readyState就绪状态是否为4,且http状态码为200
                if(xmlhttp.readyState==4&&xmlhttp.status==200){
                    //获取服务器的响应结果
                    alert(xmlhttp.responseText);
                }
            }

每当 readyState 改变时,就会触发 onreadystatechange 事件。

readyState 属性存有 XMLHttpRequest 的状态信息。

下面是 XMLHttpRequest 对象的三个重要的属性:

属性 描述
onreadystatechange 存储函数(或函数名),每当 readyState 属性改变时,就会调用该函数。
readyState 存有 XMLHttpRequest 的状态。从 0 到 4 发生变化。

  • 0: 请求未初始化
  • 1: 服务器连接已建立
  • 2: 请求已接收
  • 3: 请求处理中
  • 4: 请求已完成,且响应已就绪
status 200: “OK”
404: 未找到页面

在 onreadystatechange 事件中,我们规定当服务器响应已做好被处理的准备时所执行的任务。

 

jQuery的方式

  • $.ajax():发送异步请求
        function fun() {
            //发送异步请求
            $.ajax({
                url:"ajaxDemoServlet",
                type:"GET",
                // data:"username=jack&age=23",
                data:{
                    "username":"jack",
                    "age":23
                },
                success:function(data){
                    alert(data);
                }
            });
        }

相比原生的js方式,是不是简单了很多!

常用键值对:

  1. url:请求地址
  2. type:请求方式
  3. data:请求数据
  4. success:响应成功后的回调方法
  5. error:请求响应错误后的回调方法
  6. dataType:设置接收到的响应数据的格式
    1. xml:返回 XML 文档,可用 jQuery 处理。
    2. html:返回纯文本 HTML 信息;包含的 script 标签会在插入 dom 时执行。
    3. script: 返回纯文本 JavaScript 代码。不会自动缓存结果。除非设置了 “cache” 参数。注意:在远程请求时(不在同一个域下),所有 POST 请求都将转为 GET 请求。(因为将使用 DOM 的 script标签来加载)
    4. json:返回 JSON 数据 。
    5. jsonp:JSONP 格式。使用 JSONP 形式调用函数时,如 “myurl?callback=?” jQuery 将自动替换 ? 为正确的函数名,以执行回调函数。
    6. text:返回纯文本字符串

 

  • $.get()/post()

简化$.ajax(),直接发送GET/POST请求

        function fun() {
            //发送异步请求
            $.get("ajaxDemoServlet",{username:"rose"},function(data){
                alert(data);
            },"text");
        }

 

 


JSON

概念

JSON(JavaScript Object Notation, JS 对象表示法) 是一种轻量级的数据交换格式。它基于 ECMAScript (欧洲计算机协会制定的js规范)的一个子集,采用完全独立于编程语言的文本格式来存储和表示数据。简洁和清晰的层次结构使得 JSON 成为理想的数据交换语言。 易于人阅读和编写,同时也易于机器解析和生成,并有效地提升网络传输效率。

json在早期就是javascript的对Object对象的一种表示

var person={"name":"tom","age":23};

现在json多用于存储和交换文本信息的语法。

进行数据的传输,比xml更小更快更方便。

语法

基本规则

  • 数据在名称/值对中:json数据是由键值对构成的
    • 键用引号(单双都行)引起来,也可以不用引号
    • 值的取值类型:
      • 数字(整数或浮点数)
      • 字符串(在双引号中)
      • 逻辑值(true或false)
      • 数组(在方括号中)
      • 对象(在花括号中)
      • null
  • 数据由逗号进行分隔:多个键值对由逗号分隔
  • 花括号保存对象:使用{}定义json格式
        //1.定义基本格式
        var person={"name":"张三","age":23,'gender':true};
        //2.嵌套格式
        var persons={"persons":[
                {"name":"张三","age":23,'gender':true},
                {"name":"李四","age":16,'gender':true},
                {"name":"王五","age":28,'gender':true}
            ]
        };

获取数据

  • json对象.键名
  • json对象[“键名”]

遍历数据

        //1.定义基本格式
        var person={"name":"张三","age":23,'gender':true};
        for(var item in person){
            //item就是key,即"name"、"age"、"gender"
            alert(item+":"+person[item]);
        }

 

解析器

我们经常需要JSON数据和Java对象相互转换。

我们这里为了方便一般会直接使用解析器来解析:

  • 常见的解析器:Jsonlib、Gson、fastjson、jackson

我们重点来学习jackson

Java对象转变成JSON

使用步骤:

  1. 导入jackson的相关jar包
  2.  创建jackson核心对象 ObjectMapper
  3. 调用 ObjectMapper的相关方法进行转换

下面我们来代码示例,首先下载Junit包Jackson包,Jackson的core、databind、annotations(内核、数据绑定、注解),都需要下载jar包。

导入我们的jar包。

创建一个JavaBean

public class Person {
    private String name;
    private Integer age;
    private String gender;
   ……
}

创建测试代码

public class JacksonTest {
    //Java对象转为JSON字符串
    @Test
    public void test1(){
        //1.创建Person对象
        Person p=new Person();
        p.setName("张三");
        p.setAge(23);
        p.setGender("男");
        //2.创建jackson核心对象,ObjectMapper
        ObjectMapper mapper=new ObjectMapper();
        //3.转换
        /*
            转换方法:
                writeValue(参数1,obj);
                    参数1:
                        File:将obj对象转换为JSON字符串,并保存到指定的文件中
                        Writer:将obj对象转换为JSON字符串,并将json数据填充到字符输出流中
                        OutputStream:将obj对象转换为JSON字符串,并将json数据填充到字节输出流中
                writeValueAsString(obj):将对象转换为json字符串
         */
        try {
            //将对象转换成json字符串
            String s = mapper.writeValueAsString(p);
            System.out.println(s);
            //将数据写到D://a.tzt中
            mapper.writeValue(new File("d://a.txt"),p);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

测试很成功,这样我们就将Java类转换成了json。

 

下面介绍两个注解annotation:

  • @JsonIgnore:忽略属性

在JavaBean中,如果有某个字段是你不需要转换成JSON时转换的,则可以在该字段上添加@JsonIgnore注解,这样Jackson就会忽略该字段。

  • @JsonFormat:对属性格式化

例如有属性birthday,它的值可以选择格式化:@JsonFormat(pattern=”yyyy-MM-dd”)。

 

下面我们再来补充一下对于复杂数据的转换

  • List:集合关系会被封装成数组
  @Test
    public void test1(){
        //1.创建Person对象
        Person p=new Person();
        p.setName("张三");
        p.setAge(23);
        p.setGender("男");
        Person p2=new Person();
        p2.setName("李四");
        p2.setAge(26);
        p2.setGender("男");
        Person p3=new Person();
        p3.setName("王五");
        p3.setAge(19);
        p3.setGender("男");
        //创建List
        List<Person> ps=new ArrayList();
        ps.add(p);
        ps.add(p2);
        ps.add(p3);
        //2.创建jackson核心对象,ObjectMapper
        ObjectMapper mapper=new ObjectMapper();
        //3.转换
        try {
            //将对象转换成json字符串
            String s = mapper.writeValueAsString(ps);
            System.out.println(s);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

[{“name”:”张三”,”age”:23,”gender”:”男”},{“name”:”李四”,”age”:26,”gender”:”男”},{“name”:”王五”,”age”:19,”gender”:”男”}]

  • Map:映射关系直接被封装成json格式
    public void test1(){
        //创建map
        Map<String,Object> map=new HashMap<String,Object>();
        map.put("name","张三");
        map.put("age",23);
        map.put("gender","男");
        //2.创建jackson核心对象,ObjectMapper
        ObjectMapper mapper=new ObjectMapper();
        //3.转换
        try {
            //将对象转换成json字符串
            String s = mapper.writeValueAsString(map);
            System.out.println(s);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

{“gender”:”男”,”name”:”张三”,”age”:23}

 

JSON转变成Java对象

使用步骤:

  1. 导入jackson的相关jar包
  2.  创建jackson核心对象 ObjectMapper
  3. 调用 ObjectMapper的相关方法进行转换
    1. readValue(json字符数据,Class)
    @Test
    public void test1(){
        //1.初始化JSON字符串
        String json="{\"gender\":\"男\",\"name\":\"张三\",\"age\":23}";
        //2.创建ObjectMapper对象
        ObjectMapper mapper = new ObjectMapper();
        //3.转换为Java的对象
        try {
            Person s = mapper.readValue(json,Person.class);
            System.out.println(s);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

Person{name=’张三’, age=23, gender=’男’}

 

案例:检验重复用户名

需求与原理

在我们做网站时候,注册功能中经常要实现检验用户的用户名是否已经存在。

具体实现原理:

当输入文本框失去焦点后,发送ajax请求,查询数据库是否存在该用户的用户名,如果存在,则提示“用户名已存在”;如果不存在,则提示可用。

示例

前台:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>注册页面</title>
    <script src="https://cdn.jsdelivr.net/npm/jquery@1.12.4/dist/jquery.min.js"></script>
    <script>
        //在页面加载完成后
        $(function(){
            //给username绑定blur事件
            $("#username").blur(function(){
                //获取username文本输入框的值
                var username=$(this).val();
                //发送ajax请求
                //服务器数据格式:{"userExsit":true,"msg":"此用户名重复"}
                //服务器数据格式:{"userExsit":false,"msg":"此用户名可用"}
                $.get("findUserServlet",{username:username},function(data){
                    //判断userExist的值是否为true
                    var span=$("#s_username");
                    if(data.userExist){
                        //用户名存在
                        span.css("color","red");
                    }else{
                        //用户名不存在
                        span.css("color","green");
                    }
                    span.html(data.msg);
                },"json");
            });
        });
    </script>
</head>
<body style="background-color: silver">
<div style="text-align: center;margin: 10%">
    <form>
        <label for="username">用户名:</label>
        <input type="text" name="username" id="username"
               placeholder="请输入用户名"/>
        <span id="s_username"></span>
        <br/>
        <label for="password">密码:</label>
        <input type="password" name="password" id="password"
               placeholder="请输入密码"/>
        <br/>
        <input type="submit" value="注册"
               style="background-color: wheat;border-radius: 30%">
        <br/>
    </form>
</div>
</body>
</html>

后台:

@WebServlet("/findUserServlet")
public class FindUserServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) 
                   throws ServletException, IOException {
        response.setContentType("text/html;charset=utf-8");
        //1.获取用户名
        String username = request.getParameter("username");
        //2.判断用户名是否存在
        Map<String, Object> map = new HashMap<>();
        if("tom".equals(username)){
            //存在
            map.put("userExist",true);
            map.put("msg","此用户名重复");
        }else {
            //不存在
            map.put("userExist",false);
            map.put("msg","此用户名可用");
        }
        //将map转为json并且写到页面上
        ObjectMapper mapper=new ObjectMapper();
        mapper.writeValue(response.getWriter(),map);
    }

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

其中,我们在html中通过设定jQuery  ajax的get方法中的第四个参数type设置为“json”从而使得响应数据为json格式,我们才能正确读取,其实我们也可以直接在服务端设置响应的数据格式:

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

这样我们的响应数据就自动是json类型了,不需要在ajax的get方法的第四个参数位置指定类型了。

 


 

 

 

 

商业转载 请联系作者获得授权,非商业转载 请标明出处,谢谢

 

发表评论