模組化設計核心在於高內聚、低耦合、可插拔。本文實現一個通用的省市區三級聯動組件,技術棧:jQuery、Redis、SpringMVC、MyBatis(可替換)。
<script src="/js/jquery-2.2.4.min.js"></script>
<script src="/cityselect/js/jquery.cityselect.js"></script>
HTML 只需放置三個 select,以唯一 div#id 隔離多實例:
<div id="city">
<select class="prov"></select>
<select class="city" disabled="disabled"></select>
<select class="dist" disabled="disabled"></select>
</div>
<div id="city2">...</div>
<div id="city3">...</div>
$(function(){
$("#city").citySelect({ prov:"江蘇省", city:"無錫市", dist:"南長區", required:false });
$("#city2").citySelect({ nodata:"none", required:false });
$("#city3").citySelect({ nodata:"none", required:false });
});
Controller:暴露 /getCities 返回 JSON。
@RequestMapping("/getCities")
@ResponseBody
public CitiesDataResult getCities() throws Exception {
return commonService.getAllCities();
}
Service:優先讀 Redis 緩存,未命中則查庫組裝三級結構再回寫緩存。
@Override
public CitiesDataResult getAllCities() {
// 1. 嘗試從 Redis 獲取
String cached = jedisClient.get(REDIS_CITIES_KEY);
if (StringUtils.isNotBlank(cached)) {
return JsonUtils.jsonToPojo(cached, CitiesDataResult.class);
}
// 2. 查庫組裝 Province -> City -> District
List<AreaProvince> provList = areaProvinceMapper.getProvinceList();
List<Province> result = new ArrayList<>();
for (AreaProvince p : provList) {
List<AreaCity> cityList = areaProvinceMapper.getCityListBypId(p.getProvinceId());
List<City> cities = new ArrayList<>();
for (AreaCity c : cityList) {
List<District> districts = areaProvinceMapper.getDistrictListBycId(c.getCityId());
cities.add(new City(c.getCityName(), districts));
}
result.add(new Province(p.getProvinceName(), cities));
}
CitiesDataResult data = new CitiesDataResult();
data.setCitylist(result);
// 3. 寫入 Redis
jedisClient.set(REDIS_CITIES_KEY, JsonUtils.objectToJson(data));
return data;
}
省市區數據可存資料庫表、JS 文件或 JSON 文件,亦可從淘寶購買高精度數據腳本/Excel 導入。
