对应的sql脚本 :
[ SQL脚本 ](https://gitee.com/liurunyong/address-sql)
一、流程
1、先把对应的SpringBoot 工程创建起来;
2、让你创建的工程连接对应的数据库,Redis服务;
3、开始编写代码,(此次我只提供对应的类、方法、和sql文件)
4、因为我使用的MyBatisPlus,所以mapper接口我就不展示了;
二、开始
1、model类:
ProvinceModel:
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.annotations.ApiModel;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
import java.io.Serializable;
/**
* @Author: battery
* @Date: 2021/03/26
* @Description:
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
@Accessors(chain = true)
@ApiModel(description = "省")
@TableName(value = "province")
public class ProvinceModel implements Serializable {
private Long provinceCode;
private String provinceName;
@TableField(exist=false)
private CityModel cityModel;
}
CityModel
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.annotations.ApiModel;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
import java.io.Serializable;
/**
* @Author: battery
* @Date: 2021/03/26
* @Description:
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
@Accessors(chain = true)
@ApiModel(description = "市")
@TableName(value = "city")
public class CityModel implements Serializable {
private Long cityCode;
private String cityName;
private Long superiorCode;
}
AreaModel
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.annotations.ApiModel;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
import java.io.Serializable;
/**
* @Author: battery
* @Date: 2021/03/26
* @Description:
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
@Accessors(chain = true)
@ApiModel(description = "区/县")
@TableName(value = "area")
public class AreaModel implements Serializable {
private Long areaCode;
private String areaName;
private Long superiorCode;
}
SubDistirct
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.annotations.ApiModel;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
import java.io.Serializable;
/**
* @Author: battery
* @Date: 2021/03/26
* @Description:
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
@Accessors(chain = true)
@ApiModel(description = "街道办")
@TableName(value = "sub_district")
public class SubDistrictModel implements Serializable {
private Long subDistrictCode;
private String subDistrictName;
private Long superiorCode;
}
2、Mapper
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.liu.health.model.dictionary.ProvinceModel;
/**
* @Author: battery
* @Date: 2021/03/26
* @Description:
*/
public interface ProvinceMapper extends BaseMapper<ProvinceModel> {
}
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.liu.health.model.dictionary.CityModel;
/**
* @Author: battery
* @Date: 2021/03/26
* @Description:
*/
public interface CityMapper extends BaseMapper<CityModel> {
}
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.liu.health.model.dictionary.AreaModel;
/**
* @Author: battery
* @Date: 2021/03/26
* @Description:
*/
public interface AreaMapper extends BaseMapper<AreaModel> {
}
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.liu.health.model.dictionary.SubDistrictModel;
/**
* @Author: battery
* @Date: 2021/03/26
* @Description:
*/
public interface SubDistrictMapper extends BaseMapper<SubDistrictModel> {
}
3、Service
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.IService;
import com.liu.health.model.dictionary.ProvinceModel;
import java.util.List;
/**
* @Author: battery
* @Date: 2021/03/26
* @Description:
*/
public interface ProvinceService extends IService<ProvinceModel> {
/**
* 获取所有的省份
* @param queryWrapper 查询条件
* @return list
*/
List<ProvinceModel> selectAllData(QueryWrapper<ProvinceModel> queryWrapper);
}
import com.baomidou.mybatisplus.extension.service.IService;
import com.liu.health.model.dictionary.CityModel;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
/**
* @Author: battery
* @Date: 2021/03/26
* @Description:
*/
public interface CityService extends IService<CityModel> {
/**
* 根据省份编号查询城市信息
* @param provinceCode 省份编号
* @return list
*/
List<CityModel> selectCityDataByProvinceCode(Long provinceCode);
}
import com.baomidou.mybatisplus.extension.service.IService;
import com.liu.health.model.dictionary.AreaModel;
import java.util.List;
/**
* @Author: battery
* @Date: 2021/03/26
* @Description:
*/
public interface AreaService extends IService<AreaModel> {
/**
* 根据城市编号查询区县信息
* @param cityCode 城市编号
* @return
*/
List<AreaModel> selectAreaDataByCityCode(Long cityCode);
}
import com.baomidou.mybatisplus.extension.service.IService;
import com.liu.health.model.dictionary.SubDistrictModel;
import java.util.List;
/**
* @Author: battery
* @Date: 2021/03/26
* @Description:
*/
public interface SubDistrictService extends IService<SubDistrictModel> {
/**
* 根据区县编号查询乡镇街道信息
* @param areaCode 区县编号
* @return
*/
List<SubDistrictModel> selectSubDistrictDataByAreaCode(Long areaCode);
}
4、ServiceImpl (redis核心)
ProvinceServiceImpl
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.liu.health.dao.dictionary.ProvinceMapper;
import com.liu.health.model.dictionary.ProvinceModel;
import com.liu.health.service.dictionary.ProvinceService;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.math.BigDecimal;
import java.util.List;
/**
* @Author: battery
* @Date: 2021/03/26
* @Description:
*/
@Service
@Transactional(rollbackFor = Exception.class)
public class ProvinceServiceImpl extends ServiceImpl<ProvinceMapper, ProvinceModel> implements ProvinceService {
final ProvinceMapper provinceMapper;
final RedisTemplate redisTemplate;
ProvinceServiceImpl(ProvinceMapper provinceMapper, RedisTemplate redisTemplate) {
this.provinceMapper = provinceMapper;
this.redisTemplate = redisTemplate;
}
@Override
public List<ProvinceModel> selectAllData(QueryWrapper<ProvinceModel> queryWrapper) {
List<ProvinceModel> provinceList = redisTemplate.opsForList().range("provinceList", 0, 30);
if (provinceList.size() == 0) {
provinceList = provinceMapper.selectList(queryWrapper);
redisTemplate.opsForList().rightPushAll("provinceList", provinceList);
}
return provinceList;
}
}
CityServiceImpl
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.liu.health.dao.dictionary.CityMapper;
import com.liu.health.model.dictionary.CityModel;
import com.liu.health.service.dictionary.CityService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* @Author: battery
* @Date: 2021/03/26
* @Description:
*/
@Service
@Transactional(rollbackFor = Exception.class)
public class CityServiceImpl extends ServiceImpl<CityMapper, CityModel> implements CityService {
final RedisTemplate redisTemplate;
final CityMapper cityMapper;
CityServiceImpl(RedisTemplate redisTemplate, CityMapper cityMapper) {
this.redisTemplate = redisTemplate;
this.cityMapper = cityMapper;
}
@Override
public List<CityModel> selectCityDataByProvinceCode(Long provinceCode) {
// 获取redis中的数据
List<CityModel> cityModelList = getRedisCityData(provinceCode);
if (cityModelList.size() == 0) {
cityModelList = cityMapper.selectList(new QueryWrapper<CityModel>().in("superior_code", provinceCode));
}
// 可以在这里将数据同步上redis
return cityModelList;
}
/**
* 获取redis的城市数据
*
* @param provinceCode 省份代码
*/
private List<CityModel> getDataBaseCityData(Long provinceCode) {
List<CityModel> cityModelList = cityMapper.selectList(new QueryWrapper<CityModel>().in("superior_code", provinceCode));
return cityModelList;
}
/**
* 获取redis的城市数据
*
* @param provinceCode 省份代码
*/
private List<CityModel> getRedisCityData(Long provinceCode) {
Map<Long, CityModel> cityData = redisTemplate.opsForHash().entries("cityData");
List<CityModel> cityModelList = new ArrayList<>(cityData.size());
CityModel cityModel = null;
for (Map.Entry<Long, CityModel> data : cityData.entrySet()) {
if (StringUtils.equals(provinceCode.toString(), data.getValue().getSuperiorCode().toString())) {
cityModel = data.getValue();
cityModelList.add(new CityModel().setCityCode(cityModel.getCityCode()).setCityName(cityModel.getCityName())
.setSuperiorCode(cityModel.getSuperiorCode()));
}
}
return cityModelList;
}
}
AreaServiceImpl
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.liu.health.dao.dictionary.AreaMapper;
import com.liu.health.model.dictionary.AreaModel;
import com.liu.health.service.dictionary.AreaService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* @Author: battery
* @Date: 2021/03/26
* @Description:
*/
@Service
@Transactional(rollbackFor = Exception.class)
public class AreaServiceImpl extends ServiceImpl<AreaMapper, AreaModel> implements AreaService {
final RedisTemplate redisTemplate;
final AreaMapper areaMapper;
AreaServiceImpl(RedisTemplate redisTemplate, AreaMapper areaMapper) {
this.areaMapper = areaMapper;
this.redisTemplate = redisTemplate;
}
@Override
public List<AreaModel> selectAreaDataByCityCode(Long cityCode) {
// 先获取redis中的区县 数据
List<AreaModel> redisAreaData = getRedisAreaData(cityCode);
if (redisAreaData.size() == 0) {
redisAreaData= getDataBaseAreaData(cityCode);
}
return redisAreaData;
}
/**
* 获取redis的区县数据
*
* @param cityCode 城市代码
*/
private List<AreaModel> getDataBaseAreaData(Long cityCode) {
List<AreaModel> areaModelList = areaMapper.selectList(new QueryWrapper<AreaModel>().in("superior_code", cityCode));
return areaModelList;
}
/**
* 获取redis的区县数据
*
* @param cityCode 城市代码
*/
private List<AreaModel> getRedisAreaData(Long cityCode) {
Map<Long, AreaModel> areaData = redisTemplate.opsForHash().entries("areaData");
List<AreaModel> areaModelList = new ArrayList<>(areaData.size());
AreaModel areaModel = null;
for (Map.Entry<Long, AreaModel> data : areaData.entrySet()) {
if (StringUtils.equals(cityCode.toString(), data.getValue().getSuperiorCode().toString())) {
areaModel = data.getValue();
areaModelList.add(new AreaModel().setAreaCode(areaModel.getAreaCode()).setAreaName(areaModel.getAreaName())
.setSuperiorCode(areaModel.getSuperiorCode()));
}
}
return areaModelList;
}
}
SubDistrictServiceImpl
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.liu.health.dao.dictionary.AreaMapper;
import com.liu.health.dao.dictionary.SubDistrictMapper;
import com.liu.health.model.dictionary.AreaModel;
import com.liu.health.model.dictionary.SubDistrictModel;
import com.liu.health.service.dictionary.SubDistrictService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* @Author: battery
* @Date: 2021/03/26
* @Description:
*/
@Service
@Transactional(rollbackFor = Exception.class)
public class SubDistrictServiceImpl extends ServiceImpl<SubDistrictMapper, SubDistrictModel> implements SubDistrictService {
final RedisTemplate redisTemplate;
final SubDistrictMapper subDistrictMapper;
SubDistrictServiceImpl(RedisTemplate redisTemplate, SubDistrictMapper subDistrictMapper) {
this.subDistrictMapper = subDistrictMapper;
this.redisTemplate = redisTemplate;
}
@Override
public List<SubDistrictModel> selectSubDistrictDataByAreaCode(Long areaCode) {
// 先获取redis中的区县 数据
List<SubDistrictModel> subDistrictModelList = getRedisSubDistrictData(areaCode);
if (subDistrictModelList.size() == 0) {
subDistrictModelList= getDataBaseSubDistrictData(areaCode);
}
return subDistrictModelList;
}
/**
* 获取redis的乡镇、街道数据
*
* @param areaCode 区、县代码
*/
private List<SubDistrictModel> getDataBaseSubDistrictData(Long areaCode) {
List<SubDistrictModel> subDistrictModelList = subDistrictMapper.selectList(new QueryWrapper<SubDistrictModel>().in("superior_code", areaCode));
return subDistrictModelList;
}
/**
* 获取redis的乡镇、街道数据
*
* @param areaCode 区县代码
*/
private List<SubDistrictModel> getRedisSubDistrictData(Long areaCode) {
Map<Long, SubDistrictModel> subDistrictData = redisTemplate.opsForHash().entries("subDistrictData");
List<SubDistrictModel> subDistrictModelList = new ArrayList<>(subDistrictData.size());
SubDistrictModel subDistrictModel = null;
for (Map.Entry<Long, SubDistrictModel> data : subDistrictData.entrySet()) {
if (StringUtils.equals(areaCode.toString(), data.getValue().getSuperiorCode().toString())) {
subDistrictModel = data.getValue();
subDistrictModelList.add(new SubDistrictModel().setSubDistrictCode(subDistrictModel.getSubDistrictCode())
.setSubDistrictName(subDistrictModel.getSubDistrictName())
.setSuperiorCode(subDistrictModel.getSuperiorCode()));
}
}
return subDistrictModelList;
}
}
5、Controller
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.liu.health.common.response.ServerResponse;
import com.liu.health.model.dictionary.AreaModel;
import com.liu.health.model.dictionary.CityModel;
import com.liu.health.model.dictionary.ProvinceModel;
import com.liu.health.model.dictionary.SubDistrictModel;
import com.liu.health.service.dictionary.AreaService;
import com.liu.health.service.dictionary.CityService;
import com.liu.health.service.dictionary.ProvinceService;
import com.liu.health.service.dictionary.SubDistrictService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @Author: battery
* @Date: 2021/03/26
* @Description:
*/
@RestController
@RequestMapping("/address/")
@Api(tags = "地址模块")
public class AddressController {
final ProvinceService provinceService;
final CityService cityService;
final AreaService areaService;
final SubDistrictService subDistrictService;
final RedisTemplate redisTemplate;
public AddressController(ProvinceService provinceService, CityService cityService,
AreaService areaService, SubDistrictService subDistrictService,
RedisTemplate redisTemplate) {
this.provinceService = provinceService;
this.cityService = cityService;
this.areaService = areaService;
this.subDistrictService = subDistrictService;
this.redisTemplate = redisTemplate;
}
@GetMapping(value = "selectProvince")
@ApiOperation(value = "获取所有省份")
public ServerResponse getProvinceData() {
QueryWrapper<ProvinceModel> queryWrapper = new QueryWrapper<>();
queryWrapper.orderByAsc("province_code");
return ServerResponse.createBySuccess(provinceService.selectAllData(queryWrapper));
}
@GetMapping(value = "selectCity")
@ApiOperation(value = "根据省份获取城市")
@ApiImplicitParam(value = "省份code", name = "provinceCode", paramType = "Long", required = true)
public ServerResponse getCityData(Long provinceCode) {
if (provinceCode <= 0L) {
ServerResponse.createByErrorMessage("请选择省份");
}
return ServerResponse.createBySuccess(cityService.selectCityDataByProvinceCode(provinceCode));
}
@GetMapping(value = "selectArea")
@ApiOperation(value = "根据城市获取区县")
@ApiImplicitParam(value = "城市code", name = "cityCode", paramType = "Long", required = true)
public ServerResponse getAreaData(Long cityCode) {
if (cityCode <= 0L) {
ServerResponse.createByErrorMessage("请选择城市");
}
return ServerResponse.createBySuccess(areaService.selectAreaDataByCityCode(cityCode));
}
@GetMapping(value = "selectSubDistrict")
@ApiOperation(value = "根据区县获取乡镇、街道")
@ApiImplicitParam(value = "区县code", name = "areaCode", paramType = "Long", required = true)
public ServerResponse getSubDistrictData(Long areaCode) {
if (areaCode <= 0L) {
ServerResponse.createByErrorMessage("请选择区/县");
}
return ServerResponse.createBySuccess(subDistrictService.selectSubDistrictDataByAreaCode(areaCode));
}
@GetMapping(value = "initAddress")
@ApiOperation(value = "初始化地址信息")
public ServerResponse initAddressData() {
// 所有的城市
List<CityModel> newData = cityService.list(new QueryWrapper<CityModel>().orderByAsc("city_code"));
Map<Long, CityModel> cityMap = new HashMap<>();
for (CityModel cityModel : newData) { cityMap.put(cityModel.getCityCode(), cityModel); }
redisTemplate.opsForHash().putAll("cityData", cityMap);
// 所有的区县
List<AreaModel> areaData = areaService.list(new QueryWrapper<AreaModel>().orderByAsc("area_code"));
Map<Long, AreaModel> areaMap = new HashMap<>();
for (AreaModel areaModel : areaData) { areaMap.put(areaModel.getAreaCode(), areaModel); }
redisTemplate.opsForHash().putAll("areaData", areaMap);
// 所有的乡镇、街道
List<SubDistrictModel> subDistrictData = subDistrictService.list(new QueryWrapper<SubDistrictModel>().orderByAsc("sub_district_code"));
Map<Long, SubDistrictModel> subDistrictMap = new HashMap<>();
for (SubDistrictModel subDistrictModel : subDistrictData) { subDistrictMap.put(subDistrictModel.getSubDistrictCode(), subDistrictModel); }
redisTemplate.opsForHash().putAll("subDistrictData", subDistrictMap);
return ServerResponse.createBySuccess();
}
}
演示结果: