三级联动案例
三级联动案例
效果图

写在前面:
后台思路:省级查询没有条件;市级查询根据省级主键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>
Don't just do it. Show me your Blog. 语雀地址 : https://www.yuque.com/bigbeardhk/java

浙公网安备 33010602011771号