使用ajax实现二级联动

思路

  1. 在加载页面的时候,后台读取xml文件中的所有省份信息,显示到下拉框中
    a) 页面加载ajax发送异步请求到servlet
    b) servlet解析china.xml然后获取所有的省份的名称
    c) Servlet向jsp响应省份信息
    d) 通过jquery将每一个省份的名字添加到select下

因为在服务端需要进行xml文件的解析, 所以需要导入相应的jar包.


image.png

2.点击省份下拉框的时候触发内容改变

1.获取当前选中的省份信息
2.通过ajax请求serlvet 并且将当前的省份名称传递过去
3.Servlet根据省份名称去解析china.xml文件,获取该省份的xml片段
4.将xml片段相应给jsp
5.解析xml片段 将对应的城市信息添加到select下


image.png

首先, 将保存有中国省市信息的xml文件放到类路径下, china.xml:

<?xml version="1.0" encoding="utf-8"?>
<china>
    <province name="北京">
        <city>东城区</city>
        <city>西城区</city>
        <city>崇文区</city>
        <city>宣武区</city>
        <city>朝阳区</city>
        <city>丰台区</city>
        <city>石景山区</city>
        <city>海淀区</city>
        <city>门头沟区</city>
        <city>房山区</city>
        <city>通州区</city>
        <city>顺义区</city>
        <city>昌平区</city>
        <city>大兴区</city>
        <city>怀柔区</city>
        <city>平谷区</city>
        <city>密云县</city>
        <city>延庆县</city>
    </province>
    <province name="天津">
        <city>和平区</city>
        <city>河东区</city>
        <city>河西区</city>
        <city>南开区</city>
        <city>河北区</city>
        <city>红桥区</city>
        <city>塘沽区</city>
        <city>汉沽区</city>
        <city>大港区</city>
        <city>东丽区</city>
        <city>西青区</city>
        <city>津南区</city>
        <city>北辰区</city>
        <city>武清区</city>
        <city>宝坻区</city>
        <city>宁河县</city>
        <city>静海县</city>
        <city>蓟县</city>
    </province>
    // ...
</china>

客户端代码: province_city.jsp

<%--
  User: menglanyingfei
  Date: 2018/1/29
  Time: 10:07
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
    <title>省市联动</title>
    <script type="text/javascript" src="js/createXMLHttp.js"></script>
    <script type="text/javascript" src="js/jquery-1.4.4.js"></script>

</head>
<body>
    <select id="province">
        <option>--请选择--</option>
    </select>
    &nbsp;&nbsp;&nbsp;&nbsp;
    <select id="city">
        <option>--请选择--</option>
    </select>
</body>

<script type="text/javascript">
    // 页面加载发送请求到servlet
    $(function () {
        var xmlHttp = createXmlHttp();
//        alert(xmlHttp);

        xmlHttp.open("get",
            "${pageContext.request.contextPath}/ProvinceCityServlet", true);
        xmlHttp.send(null);
//        alert(xmlHttp);

        xmlHttp.onreadystatechange = function () {

            if (xmlHttp.readyState == 4 && xmlHttp.status == 200) {
//                alert("1");
                // 切割字符串
                var proList = xmlHttp.responseText.split("|");
//                alert(proList.length); // 34
                for (var i = 0; i < proList.length; i++) {
                    // 创建一个option jquery对象
                    var $option = $("<option>"
                        + proList[i] + "</option>");
                    // 给option设置value属性值
                    $option.val(proList[i]);
                    // 将option元素添加到select下
                    $("#province").append($option);
                }
            }
        };
    });

    // 给id为province的select 添加内容改变事件
    $("#province").change(function () {
        // 每次触发该事件的时候, 先将以前的option元素删掉, 只留下第一个
        $("#city option:gt(0)").each(function () {
            $(this).remove();
        });

       // 获取该select的value值, 也就是被选中的省份名称
       var proName = this.value;
        var xmlHttp = createXmlHttp();
        xmlHttp.open("post",
            "${pageContext.request.contextPath}/ProvinceCityServlet", true);
        // 设置请求头
        xmlHttp.setRequestHeader("content-type",
        "application/x-www-form-urlencoded");

        xmlHttp.send("proName=" + proName);
        xmlHttp.onreadystatechange = function () {

            if (xmlHttp.readyState == 4 && xmlHttp.status == 200) {
//                alert("test");
                var xmlDoc = xmlHttp.responseXML;
                // 获取所有的city子元素, 是一个集合
                var cityList = xmlDoc.getElementsByTagName("city");
                // 遍历, 得到每一个具体的city元素
//                alert(cityList.length);

                for (var i = 0; i < cityList.length; i++) {
                    // 将city子元素转换成jquery对象
                    var $city = $(cityList[i]);
                    // 获取city元素中的文本内容
                    var cityName = $city.html();
                    // 根据城市名称创建option元素
                    var $option = $("<option>" + cityName + "</option>");
                    // 设置value属性值
                    $option.val(cityName);
                    // 添加到select元素中
                    $("#city").append($option);
                }

            }
        };

    });
</script>
</html>

createXMLHttp.js: 用来创建XMLHttpRequest对象

// ajax的四个步骤
// 创建XMLHttpRequest对象
function createXmlHttp() {
    var xmlHttp;
    try {
        xmlHttp = new XMLHttpRequest();
    } catch (e) {
        try {
            xmlHttp = new ActiveXObject("Msxml2.XMLHTTP");
        } catch (e) {
            try {
                xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
            } catch (e) {
                alert("浏览器太老,不能使用ajax");
            }
        }
    }

    return xmlHttp;
}

服务端代码:

@WebServlet(name = "ProvinceCityServlet", value = "/ProvinceCityServlet")
public class ProvinceCityServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        // 请求编码
        request.setCharacterEncoding("utf-8");
        // 响应格式
        response.setContentType("text/xml;charset=utf-8");
        // 获取请求参数
        String proName = request.getParameter("proName");
        // 创建解析器
        SAXReader reader = new SAXReader();

        try {
            // 解析china.xml得到Document对象
            Document doc = reader.read(this.getClass().getResourceAsStream("/china.xml"));
            // 查询name为proName的province片段
            Element proEle = (Element) doc.selectSingleNode("//province[@name='" +proName +"']");
            // 将proEle转换成xml格式的字符串
            String strEle = proEle.asXML();
            // 响应
            response.getWriter().print(strEle);
        } catch (DocumentException e) {
            e.printStackTrace();
        }
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        // 设置响应编码
        response.setContentType("text/html;charset=utf-8");
        // 创建解析器
        SAXReader reader = new SAXReader();
        // 得到xml文件对应的Document对象
        try {
            Document doc = reader.read(this.getClass().getResourceAsStream("/china.xml"));
            // 获取province元素的属性节点(XPath)
            List<Attribute> attrList =
                    doc.selectNodes("//province/@name");
            // 采用StringBuilder来拼接所有的省份名称
            StringBuilder sb = new StringBuilder();

            for (int i = 0; i < attrList.size(); i++) {
                // 获取每一个属性节点的属性值
                String proName = attrList.get(i).getValue();
                sb.append(proName);
                // 北京,天津...台湾
                if (i < attrList.size() - 1) {
                    sb.append("|");
                }

            }
            // 响应
            response.getWriter().print(sb.toString());

        } catch (DocumentException e) {
            e.printStackTrace();
        }


    }
}

成功运行演示:


demo.gif

完整代码地址

https://github.com/menglanyingfei/front-end-Learning/tree/master/ajax%26json/ajax-day02

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,835评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,598评论 1 295
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,569评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,159评论 0 213
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,533评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,710评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,923评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,674评论 0 203
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,421评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,622评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,115评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,428评论 2 254
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,114评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,097评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,875评论 0 197
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,753评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,649评论 2 271

推荐阅读更多精彩内容

  • 一. Java基础部分.................................................
    wy_sure阅读 3,731评论 0 11
  • 1. Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语...
    子非鱼_t_阅读 31,296评论 18 399
  • 转自陈明乾的博客,可能有一定更新。 转原文声明:原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 、...
    C86guli阅读 4,603评论 6 72
  • 我很慢热,我很冷漠;我很直接,讨厌转弯;我的倔强是本性,伪装是天生。坚硬的外壳下,是柔软的心;我喜欢自由的感觉,讨...
    四郎2015阅读 2,205评论 0 4
  • 今天在和几个朋友闲聊时突然意识到自己的嘴不知道从什么时候变成了一张碎碎的嘴,它不停将肚子中有用的、没用的东西都一股...
    共一两阅读 335评论 0 0