三级联动案例

三级联动案例

效果图

写在前面:

后台思路:省级查询没有条件;市级查询根据省级主键id查询;区级查询根据市级id;根据前端事件通过Ajax获取后台转json的数据.

前端思路:通过onchange事件,运用Ajax技术获取数据并将json数据处理并绚染(拼接)到相应的select选择框中

后端代码:

代码结构

代码

dao层:数据查询结构类似:

//如:地区查询
package com.qf.dao.impl;

import com.qf.dao.DistrictDao;
import com.qf.domain.District;
import com.qf.utils.DataUtils;
import com.qf.utils.DbUtils;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;

public class DistrictDaoImpl implements DistrictDao {
    @Override
    public List<District> getDistrictByCityId(Integer cityId) {
        List<District> districts = new ArrayList<>();

        String sql = "select id,name from district where CityId = ?";

        Connection conn = DbUtils.getConnection();
        try {
            //预执行sql
            PreparedStatement ps = conn.prepareStatement(sql);
            ps.setObject(1, cityId);

            // 执行查询
            ResultSet rs = ps.executeQuery();

            // 通过反射给对象设置值
            districts = DataUtils.getAll(District.class, rs);
            //关闭连接
            DbUtils.colse(rs, ps, conn);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return districts;
    }
}

service层:没有业务要处理,自己调用数据层,不需要对数据层处理,直接return

package com.qf.service.impl;
import com.qf.dao.DistrictDao;
import com.qf.dao.impl.DistrictDaoImpl;
import com.qf.domain.District;
import com.qf.service.DistrictService;

import java.util.List;

public class DistrictServiceImpl implements DistrictService {

    DistrictDao districtDao=new DistrictDaoImpl();
    @Override
    public List<District> getDistrictByCityId(Integer cityId) {
      return districtDao.getDistrictByCityId(cityId);
    }
}

servlet层:

package com.qf.servlet;

import com.alibaba.fastjson.JSONObject;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

public class BaseServlet extends HttpServlet {


    protected void sendJson(HttpServletResponse resp, Object obj) throws ServletException, IOException {
        String jsonStr = JSONObject.toJSONString(obj);

        // 反会json的MIME类型
        resp.setContentType("application/json;charset=utf-8");
        // 告诉浏览器,我这个谁都可以拿
        resp.setHeader("Access-Control-Allow-Origin", "*");

        PrintWriter writer = resp.getWriter();
        writer.write(jsonStr);

        writer.flush();
        writer.close();
    }
}


package com.qf.servlet;

import com.alibaba.fastjson.JSONObject;
import com.qf.domain.City;
import com.qf.domain.District;
import com.qf.domain.Province;
import com.qf.service.CityService;
import com.qf.service.DistrictService;
import com.qf.service.ProvinceService;
import com.qf.service.impl.CityServiceImpl;
import com.qf.service.impl.DistrictServiceImpl;
import com.qf.service.impl.ProvinceServiceImpl;

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.io.PrintWriter;
import java.lang.reflect.Method;
import java.util.List;

@WebServlet(value = "/cascade", name = "CascadeServlet")
public class CascadeServlet extends BaseServlet{

    private ProvinceService provinceService = new ProvinceServiceImpl();

    private CityService cityService = new CityServiceImpl();

    private DistrictService districtService=new DistrictServiceImpl();

    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String methodName = req.getParameter("method");   // getProvince   getCity   getDistrict

        try {
            // 例如说methodName=getProvince,
            Method method = CascadeServlet.class.getDeclaredMethod(methodName, HttpServletRequest.class, HttpServletResponse.class);
            // 具体的方法调用
            method.invoke(this, req, resp);  // 当前对象调用 方法名叫 getProvince(HttpServletRequest x, HttpServletResponse y)
            // this.getProvince(req, resp);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void getDistrict(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String cityId = req.getParameter("cityId");

        // 获取所有的省份
        List<District> districts = districtService.getDistrictByCityId(Integer.parseInt(cityId));

        sendJson(resp, districts);

    }

    private void getCity(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String provinceId = req.getParameter("provinceId");

        // 获取所有的省份
        List<City> cities = cityService.getCitysByProvinceId(Integer.parseInt(provinceId));

        sendJson(resp, cities);
    }

    private void getProvince(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 获取所有的省份
        List<Province> provinces = provinceService.getAll();

        sendJson(resp, provinces);
      
    }
}

前端代码:

写在前面:

一.回调

1.ajax(url, method, proccess)-----------方法A

2.processDistrict(ds); processCity(cs); processProvince(ps);---------分别称为方法B

方法B作为方法A的实参,方法B中的实参为方法A中的数据--(var arry = JSON.parse(xhr.responseText))

二:每个完整数据的拼接最好使用创造DOM节点的方式

思路:上一个联级被选择后(事件触发后),就应该利用Ajax去服务器查询并获取下一级的数据展示.因为城市和地区查询分别需要省级或市级id,所以,需要传递参数到服务器

//TODO

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
省份:<select id="province">
    <option value="">请选择省份</option>
</select>
城市:<select id="city">
    <option value="">请选择城市</option>
</select>
地区:<select id="district">
    <option value="">请选择地区</option>
</select>
</body>
<script>
    var province = document.getElementById('province');
    var city = document.getElementById('city');
    var district = document.getElementById('district');

    // 创建一个option的节点
    // obj -> {value: 1, text: '请选择城市'}
    function createOptionNode(obj) {
        var optNode = document.createElement('option');   //创建一个元素
        // optNode.value 是给 <option></option> 的value赋值 -> <option value="1"></option>
        optNode.value = obj.value;
        // 给option中的文本赋值, <option value="34">请选择城市</option>
        optNode.innerText = obj.text;
        return optNode;
    }

    function processDistrict(ds) {
        // district.length = 1;
        for (var i = 0; i < ds.length; i++) {
            var d = ds[i];  //获取到每个城市
            // 创建城市的节点
            var optNode = createOptionNode({value: d.id, text: d.name});
            district.append(optNode);
        }
    }

    // 渲染城市的数据 -> [{id: 100, name: '大同'}, {id: 100, name: '太原'}]
    function processCity(cs) {

        for (var i = 0; i < cs.length; i++) {
            var c = cs[i];  //获取到每个城市

            // 创建城市的节点
            var optNode = createOptionNode({value: c.id, text: c.name});
            city.append(optNode);
        }
    }

    // onchange 事件应用的场景上 checkbox  radio   select
    // 切换省份的时候,去获取城市
    province.onchange = function () {
        city.length = 1;
        district.length = 1;
        // 获取省份id, 因为是单选,this.value指的就是被选中的option的value的值
        var provinceId = this.value;
        // 省份有数据
        if (provinceId) {
            ajax('http://localhost:8080/ProvincialLinkage_war_exploded/cascade?method=getCity&provinceId=' + provinceId, null, processCity);
        }

    }

    city.onchange = function () {
        district.length = 1;
        var cityId = this.value;
        if (cityId) {
            ajax('http://localhost:8080/ProvincialLinkage_war_exploded/cascade?method=getDistrict&cityId=' + cityId, null, processDistrict);
        }

    }

    function ajax(url, method, proccess) {
        if (!url.trim()) {
            console.log('url 为必选参数.')
            return;
        }

        // 初始化异步请求的对象
        var xhr = new XMLHttpRequest();

        // 监听请求过程状态的变化
        xhr.onreadystatechange = function () {
            // 服务器端放回了数据,并且数据正确
            if (xhr.readyState == 4 && xhr.status == 200) {
                // 将字符串转换为json的数组
                var arry = JSON.parse(xhr.responseText);
                proccess(arry);
            }
        }

        //如果用户名没有传入 method, 默认走GET
        if (!method || 'GET' == method.toUpperCase()) {
            // 初始化请求
            xhr.open('GET', url);
            // 发送请求
            xhr.send();
        }
    }

    // ps -> [{id: 1, name: '北京'}, {id: 1, name: '山西'}]
    function processProvince(ps) {
        // var str = '';
        for (var i = 0; i < ps.length; i++) {
            // 获取到省份的数据  {"id": 34, "name": "广东省"}
            var pro = ps[i];
            var optNode = createOptionNode({value: pro.id, text: pro.name});
            province.append(optNode);
        }
    }

    // 获取省份的数据
    ajax('http://localhost:8080/ProvincialLinkage_war_exploded/cascade?method=getProvince', null, processProvince)
</script>
</html>
posted @ 2020-04-30 12:32  JerryMouseJDK  阅读(406)  评论(0)    收藏  举报