package com.hai.service.impl; import com.alibaba.fastjson.JSONObject; import com.hai.common.exception.ErrorCode; import com.hai.common.exception.ErrorHelp; import com.hai.common.exception.SysCode; import com.hai.dao.SecDictionaryMapper; import com.hai.dao.SecRegionMapper; import com.hai.entity.SecDictionary; import com.hai.entity.SecDictionaryExample; import com.hai.entity.SecRegion; import com.hai.entity.SecRegionExample; import com.hai.service.CommonService; import org.apache.commons.lang3.StringUtils; import org.springframework.stereotype.Service; import javax.annotation.Resource; import java.util.*; import java.util.concurrent.locks.ReentrantLock; @Service("iCommonService") public class CommonServiceImpl implements CommonService { private long READ_STEP = 30*60*1000; //半小时刷新一次缓存的字典数据 private ReentrantLock lock = new ReentrantLock(); private ReentrantLock regionLock = new ReentrantLock(); private long lastReadTime = 0; private long regionLastReadTime = 0; @Resource private SecRegionMapper regionMapper; @Resource private SecDictionaryMapper dicMapper; private Map> dicCache = new HashMap>(); private List citiesCache = new ArrayList<>(); private Map> regionsCache = new HashMap<>(); private Map> streetCache = new HashMap<>(); private Map> communityCache = new HashMap<>(); private Map singleRegionCache = new HashMap<>(); @Override public Map> getDictionaries() { refreshDic(); return dicCache; } /** * @param codeType * @param codeValue * @throws * @Title: getDictionary * @Description: 精确查找数据字典值 * @author: 机器猫 * @param: @param codeType * @param: @param codeValue * @param: @return * @param: @throws Exception * @return: SysDictionary */ @Override public String getDictionaryCodeName(String codeType, String codeValue) { refreshDic(); if(StringUtils.isBlank(codeType)){ throw ErrorHelp.genException(SysCode.System, ErrorCode.REQ_PARAMS_ERROR, ""); } Map m = dicCache.get(codeType); if (null == m) { return ""; } SecDictionary sd = m.get(codeValue); if (null == sd) { return ""; } return sd.getCodeName(); } /** * @param codeType * @param codeValue * @throws * @Title: mappingSysCode * @Description: 根据codetype,codevalue获取系统字典数据 * @author: 机器猫 * @param: @param codeType * @param: @param codeValue * @param: @return * @param: @throws Exception * @return: SysDictionary */ @Override public SecDictionary mappingSysCode(String codeType, String codeValue) { refreshDic(); if(StringUtils.isBlank(codeType)){ throw ErrorHelp.genException(SysCode.System, ErrorCode.REQ_PARAMS_ERROR, ""); } Map m = dicCache.get(codeType); if (null == m) { return null; } SecDictionary sd = m.get(codeValue); return sd; } @Override public SecDictionary mappingSysName(String codeType, String codeName) { refreshDic(); if(StringUtils.isBlank(codeType)){ throw ErrorHelp.genException(SysCode.System, ErrorCode.REQ_PARAMS_ERROR, ""); } Map m = dicCache.get(codeType); if (null == m) { return null; } for(Map.Entry entry : m.entrySet()){ String mapKey = entry.getKey(); SecDictionary mapValue = entry.getValue(); if (mapValue.getCodeName().equals(codeName)) { return mapValue; } } return null; } /** * 根据codeType获取该类的所有字典数据 * * @param codeType * @return */ @Override public List getDictionarys(String codeType) { refreshDic(); if (StringUtils.isEmpty(codeType)) { throw ErrorHelp.genException(SysCode.System, ErrorCode.REQ_PARAMS_ERROR, "codeType is null"); } Map maps = dicCache.get(codeType); if (null == maps) { return new ArrayList<>(); } List rtn = new ArrayList<>(); rtn.addAll(maps.values()); return rtn; } @Override public List getDictionarysAndExt(String codeType, String ext1) { refreshDic(); if (StringUtils.isEmpty(codeType)) { throw ErrorHelp.genException(SysCode.System, ErrorCode.REQ_PARAMS_ERROR, "codeType is null"); } Map maps = dicCache.get(codeType); if (null == maps) { return new ArrayList<>(); } List rtn = new ArrayList<>(); for(SecDictionary dictionary : maps.values()){ if (ext1.equals(dictionary.getExt1())) { rtn.add(dictionary); } } return rtn; } @Override public List getIdAndName(String codeType) { refreshDic(); if (StringUtils.isEmpty(codeType)) { throw ErrorHelp.genException(SysCode.System, ErrorCode.REQ_PARAMS_ERROR, "codeType is null"); } Map maps = dicCache.get(codeType); if (null == maps) { return new ArrayList<>(); } List rtn = new ArrayList<>(); for(SecDictionary dictionary : maps.values()){ JSONObject jo = new JSONObject(); jo.put("codeValue",dictionary.getCodeValue()); jo.put("codeName",dictionary.getCodeName()); rtn.add(jo); } return rtn; } private void getDicFormDB(){ SecDictionaryExample example = new SecDictionaryExample(); example.createCriteria().andStatusEqualTo(1); example.setOrderByClause(" sort_id asc"); List dicList = dicMapper.selectByExample(example); for(SecDictionary dic : dicList){ if(dicCache.get(dic.getCodeType()) != null){ Map typeList = dicCache.get(dic.getCodeType()); typeList.put(dic.getCodeValue(), dic); }else{ Map temp = new HashMap(); temp.put(dic.getCodeValue(), dic); dicCache.put(dic.getCodeType(), temp); } } lastReadTime = System.currentTimeMillis(); } private void refreshDic() { if (System.currentTimeMillis() - lastReadTime < READ_STEP) { return; } if (lock.isLocked()) { //说明有线程已经在刷数据了 if (null != dicCache && dicCache.size() > 0) { //如果有数据说明已经初始化过了,直接返回老数据 return; } while (null == dicCache || dicCache.size()<1) { //说明初始化刷数据 等待10毫秒 try { Thread.sleep(10); //此处是否需要添加一个超时机制? } catch (InterruptedException ie) { //忽略 } } return; } try { lock.lock(); if (System.currentTimeMillis() - lastReadTime < READ_STEP) { return; } getDicFormDB(); } finally { if (lock.isLocked()) { lock.unlock(); } } } @Override public List getCities() { refreshRegion(); return citiesCache; } private void refreshRegion(){ if (System.currentTimeMillis() - regionLastReadTime < READ_STEP) { return; } if (regionLock.isLocked()) { //说明有线程已经在刷数据了 if (null != dicCache && dicCache.size() > 0) { //如果有数据说明已经初始化过了,直接返回老数据 return; } while (null == dicCache || dicCache.size()<1) { //说明初始化刷数据 等待10毫秒 try { Thread.sleep(10); //此处是否需要添加一个超时机制? } catch (InterruptedException ie) { //忽略 } } return; } try { regionLock.lock(); if (System.currentTimeMillis() - regionLastReadTime < READ_STEP) { return; } getRegionFromDB(); } finally { if (regionLock.isLocked()) { regionLock.unlock(); } } } private void getRegionFromDB(){ SecRegionExample example = new SecRegionExample(); example.createCriteria().andStatusEqualTo(1).andParentIdIsNull(); citiesCache = regionMapper.selectByExample(example); for(SecRegion city : citiesCache){//市 singleRegionCache.put(city.getRegionId(), city); List regions = getRegions(city.getRegionId()); regionsCache.put(city.getRegionId(),regions); for(SecRegion region : regions){//区 singleRegionCache.put(region.getRegionId(), region); List streets = getRegions(region.getRegionId()); streetCache.put(region.getRegionId(), streets); for(SecRegion street : streets){ singleRegionCache.put(street.getRegionId(), street); List communities = getRegions(street.getRegionId()); communityCache.put(street.getRegionId(),communities); for (SecRegion community : communities){ singleRegionCache.put(community.getRegionId(),community); } } } } regionLastReadTime = System.currentTimeMillis(); } private List getRegions(Long parentId) { SecRegionExample example = new SecRegionExample(); example.createCriteria().andStatusEqualTo(1).andParentIdEqualTo(parentId); return regionMapper.selectByExample(example); } @Override public List getRegionsByParentId(Long parentId) { if(parentId == null){ throw ErrorHelp.genException(SysCode.System, ErrorCode.REQ_PARAMS_ERROR); } refreshRegion(); if(null != regionsCache.get(parentId)){ return regionsCache.get(parentId); }else if(null != streetCache.get(parentId)){ return streetCache.get(parentId); }else if(null != communityCache.get(parentId)){ return communityCache.get(parentId); }else{ return null; } } @Override public Map getParentInfoByRegionId(Long regionId) { if(regionId == null){ throw ErrorHelp.genException(SysCode.System, ErrorCode.REQ_PARAMS_ERROR); } refreshRegion(); Map map = new HashMap(); Stack regionStack = getRegionStack(regionId,new Stack<>()); if (regionStack.size() == 4){ map.put("city",regionStack.pop()); map.put("region",regionStack.pop()); map.put("street",regionStack.pop()); map.put("community",regionStack.pop()); }else if (regionStack.size() == 3){ map.put("city",regionStack.pop()); map.put("region",regionStack.pop()); map.put("street",regionStack.pop()); }else if (regionStack.size() == 2){ map.put("city",regionStack.pop()); map.put("region",regionStack.pop()); }else if (regionStack.size() == 1){ map.put("city",regionStack.pop()); } return map; } @Override public String getRegionName(Long regionId) { String regionName = ""; Map map = getParentInfoByRegionId(regionId); if (map.get("city") != null) { regionName += map.get("city").getRegionName(); } if (map.get("region") != null) { regionName += map.get("region").getRegionName(); } if (map.get("street") != null) { regionName += map.get("street").getRegionName(); } if (map.get("community") != null) { regionName += map.get("community").getRegionName(); } return regionName; } private Stack getRegionStack(Long regionId, Stack regionStack){ SecRegion region = singleRegionCache.get(regionId); if (region != null){ regionStack.push(region); getRegionStack(region.getParentId(),regionStack); } return regionStack; } @Override public SecRegion getRegionsById(Long regionId) { return regionMapper.selectByPrimaryKey(regionId); } @Override public List findByName(String name) { SecRegionExample example = new SecRegionExample(); example.createCriteria().andStatusEqualTo(1).andRegionNameEqualTo(name); return regionMapper.selectByExample(example); } @Override public SecRegion getParentByRegion(Long regionId) { SecRegion secRegion = getRegionsById(regionId); if (secRegion != null && secRegion.getParentId() != null) { while (true) { secRegion = getRegionsById(secRegion.getParentId()); if (secRegion.getParentId() == null) { return secRegion; } } } return secRegion; } }