AJAX 和 JSON

AJAX 和 JSON

AJAX 基本概念

考虑客户端(如浏览器)与服务器端相互通信的情况,服务器处理客户端的请求并作出响应是需要一定的时间的,同步是指客户端在等待服务器端响应期间,无法进行其他操作,而异步是指,此期间内客户端可以进行其他操作。

AJAX,Asynchronous JavaScript And XML,即异步的 JavaScript 和 XML。

AJAX 是一种无需重新加载整个网页的情况下,更新部分网页内容的技术,通过与服务器进行少量的数据交换,AJAX可以实现网页的异步更新。传统的网页,例如之前 JSP 页面,如果需要更新内容,必须重载整个网页页面。

原生 JavaScript 实现 AJAX

首先写一个简单的页面,包含一个 button 表单,和一个 h1 用于展示服务器的返回结果

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>js原生方式实现Ajax</title>
</head>
<body>
    <h1>异步请求</h1>
    <input type="button" id="username" value="发送异步请求">
    <h1 id="response">这里是服务器返回的内容</h1>
</body>
</html>

然后是一段 js 脚本,给 button 绑定一个点击事件

<script>
    var button = document.getElementById("username");
    button.onclick = sendRequest;
    function sendRequest() {
        // AJAX 核心对象
        var xmlhttp;
        // 根据浏览器不同,获取不同的 xmlhttp 对象
        if (window.XMLHttpRequest) {
            // code for IE7+, Firefox, Chrome, Opera, Safari
            xmlhttp=new XMLHttpRequest();
        }
        else {
            // code for IE6, IE5
            xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
        }
        // 建立连接,参数:
        // 1. 请求方式 : GET、POST
        // 2. 请求的 URL(需要虚拟路径),如果是 GET 请求,直接拼接参数
        // 3. 是否使用异步请求
        xmlhttp.open("GET","/AjaxDemo/ajaxServlet?username=张三",true);
        // 发送请求
        xmlhttp.send();

        // 接受并处理来自服务器的响应结果
        xmlhttp.onreadystatechange=function() {
            // 判断readyState就绪状态是否是4,判断status响应状态码是否是200
            if (xmlhttp.readyState==4 && xmlhttp.status==200) {
                // 获取响应结果并替换原始的页面内容
                document.getElementById("response").innerHTML=xmlhttp.responseText;
            }
        }
    }
</script>

服务器端准备一个 Servlet

@WebServlet(urlPatterns = {"/ajaxServlet"})
public class AjaxServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        request.setCharacterEncoding("utf-8");
        String username = request.getParameter("username");
        System.out.println("收到AJAX异步请求,username="+username);
        // 使用流的方式响应,需要设置MIME类型和编码方式
        response.setContentType("html/text;charset=utf-8");
        response.getWriter().write("hello "+username+",服务器收到信息");
    }

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

可以看到,使用原生 js 的方式实现 AJAX 请求响应还是比较麻烦的,推荐使用 jQuery 框架实现

使用 jQuery 实现 AJAX

方式一:使用 $.ajax()

基本语法:$.ajax({键值对})

<script>
    // 文档就绪事件
    $(function() {
        // 获取元素,设置点击事件
        $("#username").click(function() {
            // 发送 ajax 请求 {键值对  k:v}
            $.ajax({
                // 请求url
                url:"/AjaxDemo/ajaxServlet",
                // 请求方式
                type:"POST",
                // 请求参数,使用json格式
                data:{"username":"jack","age":18},
                // 响应成功的回调函数
                success:function (text) {
                    $("#response").text(text);
                },
                // 响应失败的回调函数
                error:function() {
                    alert("响应出错");
                },
                // 响应数据的格式
                dataType:"text"
            });
        });
    });
</script>

方式二:使用 $.get()

基本语法:$.get([url], [data], [callback], [type]),其中参数
url:请求的 url 路径
data:请求参数,一般使用 json 格式
callback:回调函数
type:响应数据格式

$.get("/AjaxDemo/ajaxServlet",{"username":"tom","age":18},function (text) {
        $("#response").text(text);
    },"text");

方式三:使用 $.post()

基本语法:$.post([url], [data], [callback], [type]),其中参数
url:请求的 url 路径
data:请求参数,一般使用 json 格式
callback:回调函数
type:响应数据格式

$.post("/AjaxDemo/ajaxServlet",{"username":"tom","age":18},function (text) {
        $("#response").text(text);
    },"text");

JSON 基本概念和语法

JSON,JavaScript Object Notation,即 JavaScript 对象表示法,现在多用于存储和交换文本信息,JSON 比 XML 更小、更快,更易解析。

JSON 基本语法规则

JSON 对象整体由花括号 {} 定义,数据由键值对构成,键值对之间由逗号 , 分隔,键名建议使用双引号引起(单引号或不使用引号也可),值可以有以下类型:

  • 数字:整型或浮点型
  • 字符串:使用双引号引起
  • 布尔值:truefalse
  • 数组:使用方括号 [],例如 {"persons":[{},{}]}
  • JSON 对象:使用花括号 {},例如 {"address":{"province":"山东","city":"济南"}}
  • null:较少使用
var person = {"name":"张三","age":19,"gender":"男"};

var persons = {"persons":[{"name":"张三","age":19,"gender":"男"},
            {"name":"李四","age":20,"gender":"男"},
            {"name":"王五","age":21,"gender":"女"}]};

JS 中获取 JSON 数据

  1. 获取 json 对象中的值

json对象.键名 或者 json对象["键名"]

// 获取 person 对象的 age 并赋值
var age = person.age;
    age = person["age"];
  1. 获取数组对象中的
    数组对象[索引]
// 获取persons中第二个对象的name并弹出
alert(persons.persons[1].name);
  1. 遍历

遍历一个 JSON 对象,弹出所有键值对

for(var key in person) {
    // 错误方式,因为相当于 person."key"
    // alert(key +":"+ person.key);
    // 正确方式
    alert(key +":"+ person[key]);
}

遍历一个 JSON 对象数组,并弹出所有 JSON 对象的键值对

// 一个json对象的数组
var ps = [{"name":"张三","age":19,"gender":"男"},
    {"name":"李四","age":20,"gender":"男"},
    {"name":"王五","age":21,"gender":"女"}];

// 双层循环
for(var i=0;i<ps.length;i++) {
    var p = ps[i];
    for(var key in p) {
        alert(key+":"+p[key]);
    }
}

JSON 与 Java 对象的互转

前后端通常使用 JSON 进行交互和文本信息的传输,这就涉及到 JSON 数据与 Java 对象的互相转换,这个过程可以使用 JSON 解析器完成,例如 Jackson

若要使用解析器 Jackson,首先要导入相关 jar 包,然后创建其核心对象,ObjectMapper,然后调用该对象的相关方法即可完成转换

JSON 转为 Java 对象

调用 ObjectMapperreadValue(String json,Class class) 方法,参数 Class 即要解析为的目标 Java 类的 Class 对象

例如,要解析为的目标 Java 类 Person

public class Person {
    private String name;
    private int age;
    private String gender;
    /*
    这里省略其 setter、getter、toString 方法
    */
}

解析过程如下

// 创建 jackson 的关键对象 ObjectMapper
ObjectMapper mapper = new ObjectMapper();
// 待解析的 json
String str = "{\"name\":\"张三\",\"age\":19,\"gender\":\"男\"}";
// 目标类的对象
Person p = new Person();
try {
    p = mapper.readValue(str, Person.class));
} catch (IOException e) {
    e.printStackTrace();
}
System.out.println(p);

打印结果:Person{name='张三', age=19, gender='男'},解析成功

Java 对象转为 Json

  1. 使用 ObjectMapper 的方法 String writeVlueAsString(Object obj):将对象 obj 转换为 JSON 字符串
Person p = new Person();
p.setName("张三");
p.setAge(25);
p.setGender("男");

ObjectMapper mapper = new ObjectMapper();

try {
    String json = mapper.writeValueAsString(p);
    System.out.println(json);
} catch (JsonProcessingException e) {
    e.printStackTrace();
}

打印结果:{"name":"张三","age":25,"gender":"男"}

  1. 使用 ObjectMapper 的方法 void writeValue([参数1],Object obj):该方法是一个重载的方法,其中的参数1可以选择以下类型
    • File:将对象 obj 转换为 JSON 字符串并保存到文件中
    • Writer:将对象 obj 转换为 JSON 字符串并写入字符输出流中
    • OutputStream:将对象 obj 转换为 JSON 字符串并写入字节输出流中
// 在一个 Servlet 中,给客户端发送 JSON 数据
Person p = new Person();
p.setName("张三");
p.setAge(25);
p.setGender("男");

ObjectMapper mapper = new ObjectMapper();
// 设置响应数据的MIME类型为 JSON ,流的编码为 utf-8
response.setContentType("application/json;charset=utf-8");
// 将对象转为 JSON 并写如响应流中
mapper.writeValue(response.getWriter(),p);
  1. 两个有用的注解
    可以在自定义的类如上面的例子 Person 中对类的成员变量使用注解
  • @JsonIgnore:转换该类对象为 JSON 时会忽略该属性
  • @JsonFormat:加在 Data 类型的成员变量上可以转换为 JSON 是按指定形式格式化日期
@JsonIgnore
private String gender;

@JsonFormat(pattern = "yyyy-MM-dd")
private Date birthday;
  1. 转换其他对象
    除了可以将普通的 JavaBean 对象与 JSON 互转,其他复杂的 Java 对象例如 List 和 Map 也可以转换为 JSON
  • List
    Jackson 可以将 Java List 对象转为 JS 中的数组,数组元素为 json 格式
p1.setName("张三");
p1.setAge(25);
p1.setGender("男");

Person p2 = new Person();
p2.setName("李四");
p2.setAge(24);
p2.setGender("男");

Person p3 = new Person();
p3.setName("王五");
p3.setAge(23);
p3.setGender("女");

List<Person> list = new ArrayList<>();

list.add(p1);
list.add(p2);
list.add(p3);

ObjectMapper mapper = new ObjectMapper();

try {
    String json = mapper.writeValueAsString(list);
    System.out.println(json);
} catch (JsonProcessingException e) {
    e.printStackTrace();
}

打印结果为:[{"name":"张三","age":25},{"name":"李四","age":24},{"name":"王五","age":23}]

  • Map
    Map 以键值对的形式存储数据,转换成 json,仍然保持原有的键值对结构
Map<String,Object> map = new HashMap<>();
map.put("name","张三");
map.put("age",25);
map.put("gender","男");
ObjectMapper mapper = new ObjectMapper();

try {
    String json = mapper.writeValueAsString(map);
    System.out.println(json);
} catch (JsonProcessingException e) {
    e.printStackTrace();
}

打印结果为:{"gender":"男","name":"张三","age":25}

参考

Copyright: 采用 知识共享署名4.0 国际许可协议进行许可

Links: https://yzt.cool/archives/ajax和json