Java学习路线-47:Ajax学习XMLHttpRequest、XStream、json-lib(2)

课时8 8.ajax第四例:响应内容为xml

服务端响应头

Content-Type: text/xml; charset=utf-8

客户端设置

var doc = xmlHttp.responseXML; // 得到Document对象

服务端代码

@app.route("/xml")
def xml():
    data = """
        <person>
            <name>Tom</name>
            <age>23</age>
        </person>
    """
    res = make_response(data)
    res.headers['Content-Type'] = 'text/xml; charset=utf-8'
    return res

客户端代码

<button id="btn">点击</button>
<h2 id="text"></h2>
<script>
    // 获取XMLHttpRequest对象
    function createXMLHttpRequest() {
        try {
            // 大多数浏览器
            return new XMLHttpRequest();
        } catch (e) {
            try {
                // IE6.0
                new ActiveXObject("Msxml2.XMLHTTP");
            } catch (e) {
                try {
                    // IE<=5.5
                    new ActiveXObject("Microsoft.XMLHTTP");
                } catch (e) {
                    console.log("浏览器版本太老了!");
                    throw e;
                }
            }
        }
    }
    // 判断是否为IE浏览器
    function isIE() {
        if (window.addEventListener) {
            return false;
        } else {
            return true;
        }
    }
    // 文档加载完成后马上执行
    window.onload = function () {
        let btn = document.getElementById("btn");
        // 注册事件监听
        btn.onclick = function () {
            let xmlHttp = createXMLHttpRequest();
            xmlHttp.open("GET", "http://127.0.0.1:5000/xml", true);
            xmlHttp.send(null);
            xmlHttp.onreadystatechange = function () {
                // 双重判断 xmlHttp状态为服务器响应结束,服务器状态响应结束
                if (xmlHttp.readyState == 4 && xmlHttp.status == 200) {
                    // 获取响应结果
                    var doc = xmlHttp.responseXML;
                    // IE 和非IE有所区别
                    let name = doc.getElementsByTagName("name")[0].textContent;
                    let age = doc.getElementsByTagName("age")[0].textContent;
                    let text = document.getElementById("text");
                    text.innerHTML = `name: ${name}, age: ${age}`;
                }
            }
        }
    }
</script>

课时9-10 ajax第五例:省市联动

<select name="province" id="">
    <option value="">请选择省份</option>
</select>
<select name="city" id="">
    <option value="">请选择城市</option>
</select>

服务端提供两个接口

province

city?province=北京

完整代码

一、前端代码

1、util.js

// 获取XMLHttpRequest对象
function createXMLHttpRequest() {
    try {
        // 大多数浏览器
        return new XMLHttpRequest();
    } catch (e) {
        try {
            // IE6.0
            new ActiveXObject("Msxml2.XMLHTTP");
        } catch (e) {
            try {
                // IE<=5.5
                new ActiveXObject("Microsoft.XMLHTTP");
            } catch (e) {
                console.log("浏览器版本太老了!");
                throw e;
            }
        }
    }
}
// 判断是否为IE浏览器
function isIE() {
    if (window.addEventListener) {
        return false;
    } else {
        return true;
    }
}

2、demo.html

<select name="province" id="province">
    <option value="">请选择省份</option>
</select>
<select name="city" id="city">
    <option value="">请选择城市</option>
</select>
<script src="./util.js"></script>
<script>
    function createOption(name) {
        // 创建option元素
        let option = document.createElement("option");
        option.value = name;
        // 创建文本节点
        let textNode = document.createTextNode(name);
        option.appendChild(textNode);
        return option;
    }
    // 文档加载完成后马上执行
    window.onload = function () {
        // 第一步:先获取省级列
        let xmlHttp = createXMLHttpRequest();
        xmlHttp.open("GET", "http://127.0.0.1:5000/provinces", true);
        xmlHttp.send(null);
        let province = document.getElementById("province");
        xmlHttp.onreadystatechange = function () {
            // 双重判断 xmlHttp状态为服务器响应结束,服务器状态响应结束
            if (xmlHttp.readyState == 4 && xmlHttp.status == 200) {
                // 获取响应结果
                var text = xmlHttp.responseText;
                let list = text.split("|"); // 拆分数据得到数组
                for (let item of list) {
                    let option = createOption(item);
                    province.appendChild(option);
                }
            }
        }
        // 第二步:监听省级列表变动,获取城市列表
        province.onchange = function () {
            if (province.value == "") {
                return
            }
            let xmlHttp = createXMLHttpRequest();
            xmlHttp.open("POST", "http://127.0.0.1:5000/cities", true);
            xmlHttp.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
            xmlHttp.send(`province=${province.value}`);
            xmlHttp.onreadystatechange = function () {
                // 双重判断 xmlHttp状态为服务器响应结束,服务器状态响应结束
                if (xmlHttp.readyState == 4 && xmlHttp.status == 200) {
                    // 移除所有结果
                    let city = document.getElementById("city");
                    let optionList = city.getElementsByTagName("option");
                    while (optionList.length > 1) {
                        city.removeChild(optionList[1]);
                    }
                    // 获取响应结果
                    var doc = xmlHttp.responseXML;
                    let cities = doc.getElementsByTagName("city");
                    for (let item of cities) {
                        let cityName = "";
                        // 兼容IE浏览器和其他浏览器
                        if (isIE()) {
                            cityName = item.text; // IE
                        } else {
                            cityName = item.textContent; // FireFox等
                        }
                        let option = createOption(cityName);
                        city.appendChild(option);
                    }
                }
            }
        }
    }
</script>

二、后端代码

1、数据文件china.xml

<china>
    <province name="北京">
        <city>东城区</city>
        <city>西城区</city>
    </province>
    <province name="天津">
        <city>和平区</city>
        <city>河东区</city>
    </province>
</china>

2、数据解析文件demo.py

# pip install lxml
from lxml import etree
class China():
    path = "china.xml"
    @classmethod
    def getProvinces(cls):
        """获取省份
        """
        tree = etree.parse(cls.path)
        return tree.xpath('//province/@name')
    @classmethod
    def getCities(cls, province):
        """获取城市
        """
        tree = etree.parse(cls.path)
        result = tree.xpath(f"//province[@name='{province}']")
        if result:
            return etree.tostring(result[0], encoding="UTF-8")
        else:
            return ""
if __name__ == "__main__":
    print(China.getProvinces())
    print(China.getCities("北京"))

3、接口文件

from flask import Flask, request, make_response
from flask_cors import CORS
from demo import China
app = Flask(__name__)
CORS(app, supports_credentials=True)
@app.route("/provinces")
def provinces():
    return "|".join(China.getProvinces())
@app.route("/cities", methods=['POST'])
def cities():
    province = request.form.get("province")
    res = make_response(China.getCities(province))
    res.headers['Content-Type'] = 'text/xml; charset=utf-8'
    return res
if __name__ == '__main__':
    app.run(debug=True)

课时11 11.XStream(可把Javabean转换成XMl的小工具)

依赖

<dependency>
    <groupId>xstream</groupId>
    <artifactId>xstream</artifactId>
    <version>1.2.2</version>
</dependency>

代码实例

import com.thoughtworks.xstream.XStream;
import java.util.ArrayList;
import java.util.List;
class City {
    private String name;
    public City(String name) {
        this.name = name;
    }
}
class Province {
    private String name;
    private List<City> cities = new ArrayList<>();
    public void addCity(City city){
        cities.add(city);
    }
    public Province(String name) {
        this.name = name;
    }
}
public class TestXStream {
    public static void main(String[] args) {
        // 数据准备
        List<Province> list = new ArrayList<Province>();
        Province province = new Province("北京");
        province.addCity(new City("东城区"));
        province.addCity(new City("昌平区"));
        list.add(province);
        XStream xStream = new XStream();
        // 指定别名
        xStream.alias("china", List.class);
        xStream.alias("province", Province.class);
        xStream.alias("city", City.class);
        // 属性设置
        xStream.useAttributeFor(Province.class, "name");
        // 去除无用的标签
        xStream.addImplicitCollection(Province.class, "cities");
        String str = xStream.toXML(list);
        System.out.println(str);
    }
}

课时12 12.JSON的概述

js提供的一种数据交换格式

Json语法

属性名必须使用双引号括起来

对象:{}

属性:

   null、数值、字符串、数组[]、boolean(true/false)

var s = "1 + 2";

eval(s);

// 3

1、示例

(1)服务端代码

from flask import Flask, jsonify
from flask_cors import CORS
app = Flask(__name__)
CORS(app, supports_credentials=True)
@app.route("/json")
def json():
    return jsonify({"name": "Tom"})
if __name__ == '__main__':
    app.run(debug=True)

(2)客户端代码

<button id="btn">点击</button>
<h2 id="text"></h2>
<script src="./util.js"></script>
<script>
    // 文档加载完成后马上执行
    window.onload = function () {
        let btn = document.getElementById("btn");
        btn.onclick = function () {
            let xmlHttp = createXMLHttpRequest();
            xmlHttp.open("GET", "http://127.0.0.1:5000/json", true);
            xmlHttp.send(null);
            xmlHttp.onreadystatechange = function () {
                // 双重判断 xmlHttp状态为服务器响应结束,服务器状态响应结束
                if (xmlHttp.readyState == 4 && xmlHttp.status == 200) {
                    // 获取响应结果
                    let text = xmlHttp.responseText;
                    let obj = JSON.parse(text);
                    document.getElementById("text").innerHTML = `name: ${obj.name}`;
                }
            }
        }
    }
</script>