¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.jeecg.common.aspect; |
| | | |
| | | import com.alibaba.fastjson.JSON; |
| | | import com.alibaba.fastjson.JSONObject; |
| | | import com.alibaba.fastjson.parser.Feature; |
| | | import com.baomidou.mybatisplus.core.metadata.IPage; |
| | | import com.fasterxml.jackson.core.JsonProcessingException; |
| | | import com.fasterxml.jackson.databind.ObjectMapper; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.aspectj.lang.ProceedingJoinPoint; |
| | | import org.aspectj.lang.annotation.Around; |
| | | import org.aspectj.lang.annotation.Aspect; |
| | | import org.aspectj.lang.annotation.Pointcut; |
| | | import org.jeecg.common.api.CommonAPI; |
| | | import org.jeecg.common.api.vo.Result; |
| | | import org.jeecg.common.aspect.annotation.Dict; |
| | | import org.jeecg.common.constant.CommonConstant; |
| | | import org.jeecg.common.system.vo.DictModel; |
| | | import org.jeecg.common.util.oConvertUtils; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.context.annotation.Lazy; |
| | | import org.springframework.data.redis.core.RedisTemplate; |
| | | import org.springframework.stereotype.Component; |
| | | import org.springframework.util.StringUtils; |
| | | |
| | | import java.lang.reflect.Field; |
| | | import java.util.*; |
| | | import java.util.concurrent.TimeUnit; |
| | | import java.util.stream.Collectors; |
| | | |
| | | /** |
| | | * @Description: åå
¸aopç±» |
| | | * @Author: dangzhenghui |
| | | * @Date: 2019-3-17 21:50 |
| | | * @Version: 1.0 |
| | | */ |
| | | @Aspect |
| | | @Component |
| | | @Slf4j |
| | | public class DictAspect { |
| | | @Lazy |
| | | @Autowired |
| | | private CommonAPI commonApi; |
| | | @Autowired |
| | | public RedisTemplate redisTemplate; |
| | | |
| | | @Autowired |
| | | private ObjectMapper objectMapper; |
| | | |
| | | private static final String JAVA_UTIL_DATE = "java.util.Date"; |
| | | |
| | | /** |
| | | * å®ä¹åç¹Pointcut |
| | | */ |
| | | @Pointcut("execution(public * org.jeecg.modules..*.*Controller.*(..)) || @annotation(org.jeecg.common.aspect.annotation.AutoDict)") |
| | | public void excudeService() { |
| | | } |
| | | |
| | | @Around("excudeService()") |
| | | public Object doAround(ProceedingJoinPoint pjp) throws Throwable { |
| | | long time1=System.currentTimeMillis(); |
| | | Object result = pjp.proceed(); |
| | | long time2=System.currentTimeMillis(); |
| | | log.debug("è·åJSONæ°æ® èæ¶ï¼"+(time2-time1)+"ms"); |
| | | long start=System.currentTimeMillis(); |
| | | result=this.parseDictText(result); |
| | | long end=System.currentTimeMillis(); |
| | | log.debug("注å
¥åå
¸å°JSONæ°æ® èæ¶"+(end-start)+"ms"); |
| | | return result; |
| | | } |
| | | |
| | | /** |
| | | * æ¬æ¹æ³é对è¿å对象为Result çIPageçå页åè¡¨æ°æ®ãListæ°æ®ï¼éåéé¢åå¥äºä¸å±é忝䏿¯æï¼è¿è¡å¨æåå
¸æ³¨å
¥ |
| | | * åå
¸æ³¨å
¥å®ç° éè¿å¯¹å®ä½ç±»æ·»å 注解@dict æ¥æ è¯éè¦çåå
¸å
容,åå
¸å为ååå
¸codeå³å¯ ï¼tableåå
¸ code table texté
å使ç¨ä¸åæ¥jeecgçç¨æ³ç¸å |
| | | * 示ä¾ä¸ºSysUser åæ®µä¸ºsex æ·»å äºæ³¨è§£@Dict(dicCode = "sex") ä¼å¨åå
¸æå¡ç«é©¬æ¥åºæ¥å¯¹åºçtext ç¶åå¨è¯·æ±listçæ¶åå°è¿ä¸ªåå
¸textï¼å·²å段åç§°å _dictTextå½¢å¼è¿åå°å端 |
| | | * ä¾è¾å
¥å½åè¿åå¼çå°±ä¼å¤åºä¸ä¸ªsex_dictTextåæ®µ |
| | | * { |
| | | * sex:1, |
| | | * sex_dictText:"ç·" |
| | | * } |
| | | * åç«¯ç´æ¥åå¼sext_dictTextå¨tableé颿 éåè¿è¡å端çåå
¸è½¬æ¢äº |
| | | * customRender:function (text) { |
| | | * if(text==1){ |
| | | * return "ç·"; |
| | | * }else if(text==2){ |
| | | * return "女"; |
| | | * }else{ |
| | | * return text; |
| | | * } |
| | | * } |
| | | * ç®åvueæ¯è¿ä¹è¿è¡åå
¸æ¸²æå°tableä¸çå¤äºå°±å¾éº»ç¦äº è¿ä¸ªç´æ¥å¨æå¡ç«¯æ¸²æå®æå端å¯ä»¥ç´æ¥ç¨ |
| | | * @param result |
| | | */ |
| | | private Object parseDictText(Object result) { |
| | | if (result instanceof Result) { |
| | | if (((Result) result).getResult() instanceof IPage) { |
| | | List<JSONObject> items = new ArrayList<>(); |
| | | |
| | | //step.1 çéåºå äº Dict 注解çåæ®µå表 |
| | | List<Field> dictFieldList = new ArrayList<>(); |
| | | // åå
¸æ°æ®åè¡¨ï¼ key = åå
¸codeï¼value=æ°æ®å表 |
| | | Map<String, List<String>> dataListMap = new HashMap<>(5); |
| | | //ååºç»æé |
| | | List<Object> records=((IPage) ((Result) result).getResult()).getRecords(); |
| | | //update-begin--Author:zyf -- Date:20220606 ----forï¼ãVUEN-1230ã 夿æ¯å¦å«æåå
¸æ³¨è§£,æ²¡ææ³¨è§£è¿å----- |
| | | Boolean hasDict= checkHasDict(records); |
| | | if(!hasDict){ |
| | | return result; |
| | | } |
| | | |
| | | log.debug(" __ è¿å
¥åå
¸ç¿»è¯åé¢ DictAspect ââ " ); |
| | | //update-end--Author:zyf -- Date:20220606 ----forï¼ãVUEN-1230ã 夿æ¯å¦å«æåå
¸æ³¨è§£,æ²¡ææ³¨è§£è¿å----- |
| | | for (Object record : records) { |
| | | String json="{}"; |
| | | try { |
| | | //update-begin--Author:zyf -- Date:20220531 ----forï¼ãissues/#3629ã DictAspect Jacksonåºå忥é----- |
| | | //è§£å³@JsonFormat注解解æä¸äºçé®é¢è¯¦è§SysAnnouncementç±»ç@JsonFormat |
| | | json = objectMapper.writeValueAsString(record); |
| | | //update-end--Author:zyf -- Date:20220531 ----forï¼ãissues/#3629ã DictAspect Jacksonåºå忥é----- |
| | | } catch (JsonProcessingException e) { |
| | | log.error("jsonè§£æå¤±è´¥"+e.getMessage(),e); |
| | | } |
| | | //update-begin--Author:scott -- Date:20211223 ----forï¼ãissues/3303ãrestcontrollerè¿åjsonæ°æ®åkey顺åºéä¹± ----- |
| | | JSONObject item = JSONObject.parseObject(json, Feature.OrderedField); |
| | | //update-end--Author:scott -- Date:20211223 ----forï¼ãissues/3303ãrestcontrollerè¿åjsonæ°æ®åkey顺åºéä¹± ----- |
| | | |
| | | //update-begin--Author:scott -- Date:20190603 ----forï¼è§£å³ç»§æ¿å®ä½åæ®µæ æ³ç¿»è¯é®é¢------ |
| | | //for (Field field : record.getClass().getDeclaredFields()) { |
| | | // éåææåæ®µï¼æåå
¸Codeååºæ¥ï¼æ¾å° map é |
| | | for (Field field : oConvertUtils.getAllFields(record)) { |
| | | String value = item.getString(field.getName()); |
| | | if (oConvertUtils.isEmpty(value)) { |
| | | continue; |
| | | } |
| | | //update-end--Author:scott -- Date:20190603 ----forï¼è§£å³ç»§æ¿å®ä½åæ®µæ æ³ç¿»è¯é®é¢------ |
| | | if (field.getAnnotation(Dict.class) != null) { |
| | | if (!dictFieldList.contains(field)) { |
| | | dictFieldList.add(field); |
| | | } |
| | | String code = field.getAnnotation(Dict.class).dicCode(); |
| | | String text = field.getAnnotation(Dict.class).dicText(); |
| | | String table = field.getAnnotation(Dict.class).dictTable(); |
| | | |
| | | List<String> dataList; |
| | | String dictCode = code; |
| | | if (!StringUtils.isEmpty(table)) { |
| | | dictCode = String.format("%s,%s,%s", table, text, code); |
| | | } |
| | | dataList = dataListMap.computeIfAbsent(dictCode, k -> new ArrayList<>()); |
| | | this.listAddAllDeduplicate(dataList, Arrays.asList(value.split(","))); |
| | | } |
| | | //dateç±»åé»è®¤è½¬æ¢stringæ ¼å¼åæ¥æ |
| | | //update-begin--Author:zyf -- Date:20220531 ----forï¼ãissues/#3629ã DictAspect Jacksonåºå忥é----- |
| | | //if (JAVA_UTIL_DATE.equals(field.getType().getName())&&field.getAnnotation(JsonFormat.class)==null&&item.get(field.getName())!=null){ |
| | | //SimpleDateFormat aDate=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); |
| | | // item.put(field.getName(), aDate.format(new Date((Long) item.get(field.getName())))); |
| | | //} |
| | | //update-end--Author:zyf -- Date:20220531 ----forï¼ãissues/#3629ã DictAspect Jacksonåºå忥é----- |
| | | } |
| | | items.add(item); |
| | | } |
| | | |
| | | //step.2 è°ç¨ç¿»è¯æ¹æ³ï¼ä¸æ¬¡æ§ç¿»è¯ |
| | | Map<String, List<DictModel>> translText = this.translateAllDict(dataListMap); |
| | | |
| | | //step.3 å°ç¿»è¯ç»æå¡«å
å°è¿åç»æé |
| | | for (JSONObject record : items) { |
| | | for (Field field : dictFieldList) { |
| | | String code = field.getAnnotation(Dict.class).dicCode(); |
| | | String text = field.getAnnotation(Dict.class).dicText(); |
| | | String table = field.getAnnotation(Dict.class).dictTable(); |
| | | |
| | | String fieldDictCode = code; |
| | | if (!StringUtils.isEmpty(table)) { |
| | | fieldDictCode = String.format("%s,%s,%s", table, text, code); |
| | | } |
| | | |
| | | String value = record.getString(field.getName()); |
| | | if (oConvertUtils.isNotEmpty(value)) { |
| | | List<DictModel> dictModels = translText.get(fieldDictCode); |
| | | if(dictModels==null || dictModels.size()==0){ |
| | | continue; |
| | | } |
| | | |
| | | String textValue = this.translDictText(dictModels, value); |
| | | log.debug(" åå
¸Val : " + textValue); |
| | | log.debug(" __ç¿»è¯åå
¸å段__ " + field.getName() + CommonConstant.DICT_TEXT_SUFFIX + "ï¼ " + textValue); |
| | | |
| | | // TODO-sun æµè¯è¾åºï¼å¾
å |
| | | log.debug(" ---- dictCode: " + fieldDictCode); |
| | | log.debug(" ---- value: " + value); |
| | | log.debug(" ----- text: " + textValue); |
| | | log.debug(" ---- dictModels: " + JSON.toJSONString(dictModels)); |
| | | |
| | | record.put(field.getName() + CommonConstant.DICT_TEXT_SUFFIX, textValue); |
| | | } |
| | | } |
| | | } |
| | | |
| | | ((IPage) ((Result) result).getResult()).setRecords(items); |
| | | } |
| | | |
| | | } |
| | | return result; |
| | | } |
| | | |
| | | /** |
| | | * list å»éæ·»å |
| | | */ |
| | | private void listAddAllDeduplicate(List<String> dataList, List<String> addList) { |
| | | // çéåºdataList䏿²¡æçæ°æ® |
| | | List<String> filterList = addList.stream().filter(i -> !dataList.contains(i)).collect(Collectors.toList()); |
| | | dataList.addAll(filterList); |
| | | } |
| | | |
| | | /** |
| | | * 䏿¬¡æ§æææçåå
¸é½ç¿»è¯äº |
| | | * 1. ææçæ®éæ°æ®åå
¸çæææ°æ®åªæ§è¡ä¸æ¬¡SQL |
| | | * 2. 表åå
¸ç¸åçæææ°æ®åªæ§è¡ä¸æ¬¡SQL |
| | | * @param dataListMap |
| | | * @return |
| | | */ |
| | | private Map<String, List<DictModel>> translateAllDict(Map<String, List<String>> dataListMap) { |
| | | // ç¿»è¯åçåå
¸ææ¬ï¼key=dictCode |
| | | Map<String, List<DictModel>> translText = new HashMap<>(5); |
| | | // éè¦ç¿»è¯çæ°æ®ï¼æäºå¯ä»¥ä»redisç¼åä¸è·åï¼å°±ä¸èµ°æ°æ®åºæ¥è¯¢ï¼ |
| | | List<String> needTranslData = new ArrayList<>(); |
| | | //step.1 å
éè¿redisä¸è·åç¼ååå
¸æ°æ® |
| | | for (String dictCode : dataListMap.keySet()) { |
| | | List<String> dataList = dataListMap.get(dictCode); |
| | | if (dataList.size() == 0) { |
| | | continue; |
| | | } |
| | | // 表åå
¸éè¦ç¿»è¯çæ°æ® |
| | | List<String> needTranslDataTable = new ArrayList<>(); |
| | | for (String s : dataList) { |
| | | String data = s.trim(); |
| | | if (data.length() == 0) { |
| | | continue; //è·³è¿å¾ªç¯ |
| | | } |
| | | if (dictCode.contains(",")) { |
| | | String keyString = String.format("sys:cache:dictTable::SimpleKey [%s,%s]", dictCode, data); |
| | | if (redisTemplate.hasKey(keyString)) { |
| | | try { |
| | | String text = oConvertUtils.getString(redisTemplate.opsForValue().get(keyString)); |
| | | List<DictModel> list = translText.computeIfAbsent(dictCode, k -> new ArrayList<>()); |
| | | list.add(new DictModel(data, text)); |
| | | } catch (Exception e) { |
| | | log.warn(e.getMessage()); |
| | | } |
| | | } else if (!needTranslDataTable.contains(data)) { |
| | | // å»éæ·»å |
| | | needTranslDataTable.add(data); |
| | | } |
| | | } else { |
| | | String keyString = String.format("sys:cache:dict::%s:%s", dictCode, data); |
| | | if (redisTemplate.hasKey(keyString)) { |
| | | try { |
| | | String text = oConvertUtils.getString(redisTemplate.opsForValue().get(keyString)); |
| | | List<DictModel> list = translText.computeIfAbsent(dictCode, k -> new ArrayList<>()); |
| | | list.add(new DictModel(data, text)); |
| | | } catch (Exception e) { |
| | | log.warn(e.getMessage()); |
| | | } |
| | | } else if (!needTranslData.contains(data)) { |
| | | // å»éæ·»å |
| | | needTranslData.add(data); |
| | | } |
| | | } |
| | | |
| | | } |
| | | //step.2 è°ç¨æ°æ®åºç¿»è¯è¡¨åå
¸ |
| | | if (needTranslDataTable.size() > 0) { |
| | | String[] arr = dictCode.split(","); |
| | | String table = arr[0], text = arr[1], code = arr[2]; |
| | | String values = String.join(",", needTranslDataTable); |
| | | log.debug("translateDictFromTableByKeys.dictCode:" + dictCode); |
| | | log.debug("translateDictFromTableByKeys.values:" + values); |
| | | List<DictModel> texts = commonApi.translateDictFromTableByKeys(table, text, code, values); |
| | | log.debug("translateDictFromTableByKeys.result:" + texts); |
| | | List<DictModel> list = translText.computeIfAbsent(dictCode, k -> new ArrayList<>()); |
| | | list.addAll(texts); |
| | | |
| | | // å redis ç¼å |
| | | for (DictModel dict : texts) { |
| | | String redisKey = String.format("sys:cache:dictTable::SimpleKey [%s,%s]", dictCode, dict.getValue()); |
| | | try { |
| | | // update-begin-author:taoyan date:20211012 for: åå
¸è¡¨ç¿»è¯æ³¨è§£ç¼åæªæ´æ° issues/3061 |
| | | // ä¿ç5åé |
| | | redisTemplate.opsForValue().set(redisKey, dict.getText(), 300, TimeUnit.SECONDS); |
| | | // update-end-author:taoyan date:20211012 for: åå
¸è¡¨ç¿»è¯æ³¨è§£ç¼åæªæ´æ° issues/3061 |
| | | } catch (Exception e) { |
| | | log.warn(e.getMessage(), e); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | //step.3 è°ç¨æ°æ®åºè¿è¡ç¿»è¯æ®éåå
¸ |
| | | if (needTranslData.size() > 0) { |
| | | List<String> dictCodeList = Arrays.asList(dataListMap.keySet().toArray(new String[]{})); |
| | | // å°ä¸å
å«éå·çåå
¸codeçéåºæ¥ï¼å 为带éå·çæ¯è¡¨åå
¸ï¼è䏿¯æ®éçæ°æ®åå
¸ |
| | | List<String> filterDictCodes = dictCodeList.stream().filter(key -> !key.contains(",")).collect(Collectors.toList()); |
| | | String dictCodes = String.join(",", filterDictCodes); |
| | | String values = String.join(",", needTranslData); |
| | | log.debug("translateManyDict.dictCodes:" + dictCodes); |
| | | log.debug("translateManyDict.values:" + values); |
| | | Map<String, List<DictModel>> manyDict = commonApi.translateManyDict(dictCodes, values); |
| | | log.debug("translateManyDict.result:" + manyDict); |
| | | for (String dictCode : manyDict.keySet()) { |
| | | List<DictModel> list = translText.computeIfAbsent(dictCode, k -> new ArrayList<>()); |
| | | List<DictModel> newList = manyDict.get(dictCode); |
| | | list.addAll(newList); |
| | | |
| | | // å redis ç¼å |
| | | for (DictModel dict : newList) { |
| | | String redisKey = String.format("sys:cache:dict::%s:%s", dictCode, dict.getValue()); |
| | | try { |
| | | redisTemplate.opsForValue().set(redisKey, dict.getText()); |
| | | } catch (Exception e) { |
| | | log.warn(e.getMessage(), e); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | return translText; |
| | | } |
| | | |
| | | /** |
| | | * åå
¸å¼æ¿æ¢ææ¬ |
| | | * |
| | | * @param dictModels |
| | | * @param values |
| | | * @return |
| | | */ |
| | | private String translDictText(List<DictModel> dictModels, String values) { |
| | | List<String> result = new ArrayList<>(); |
| | | |
| | | // å
许å¤ä¸ªéå·åéï¼å
è®¸ä¼ æ°ç»å¯¹è±¡ |
| | | String[] splitVal = values.split(","); |
| | | for (String val : splitVal) { |
| | | String dictText = val; |
| | | for (DictModel dict : dictModels) { |
| | | if (val.equals(dict.getValue())) { |
| | | dictText = dict.getText(); |
| | | break; |
| | | } |
| | | } |
| | | result.add(dictText); |
| | | } |
| | | return String.join(",", result); |
| | | } |
| | | |
| | | /** |
| | | * ç¿»è¯åå
¸ææ¬ |
| | | * @param code |
| | | * @param text |
| | | * @param table |
| | | * @param key |
| | | * @return |
| | | */ |
| | | @Deprecated |
| | | private String translateDictValue(String code, String text, String table, String key) { |
| | | if(oConvertUtils.isEmpty(key)) { |
| | | return null; |
| | | } |
| | | StringBuffer textValue=new StringBuffer(); |
| | | String[] keys = key.split(","); |
| | | for (String k : keys) { |
| | | String tmpValue = null; |
| | | log.debug(" åå
¸ key : "+ k); |
| | | if (k.trim().length() == 0) { |
| | | continue; //è·³è¿å¾ªç¯ |
| | | } |
| | | //update-begin--Author:scott -- Date:20210531 ----forï¼ !56 ä¼åå¾®æå¡åºç¨ä¸åå¨è¡¨å段éè¦åå
¸ç¿»è¯æ¶å è½½ç¼æ
¢é®é¢----- |
| | | if (!StringUtils.isEmpty(table)){ |
| | | log.debug("--DictAspect------dicTable="+ table+" ,dicText= "+text+" ,dicCode="+code); |
| | | String keyString = String.format("sys:cache:dictTable::SimpleKey [%s,%s,%s,%s]",table,text,code,k.trim()); |
| | | if (redisTemplate.hasKey(keyString)){ |
| | | try { |
| | | tmpValue = oConvertUtils.getString(redisTemplate.opsForValue().get(keyString)); |
| | | } catch (Exception e) { |
| | | log.warn(e.getMessage()); |
| | | } |
| | | }else { |
| | | tmpValue= commonApi.translateDictFromTable(table,text,code,k.trim()); |
| | | } |
| | | }else { |
| | | String keyString = String.format("sys:cache:dict::%s:%s",code,k.trim()); |
| | | if (redisTemplate.hasKey(keyString)){ |
| | | try { |
| | | tmpValue = oConvertUtils.getString(redisTemplate.opsForValue().get(keyString)); |
| | | } catch (Exception e) { |
| | | log.warn(e.getMessage()); |
| | | } |
| | | }else { |
| | | tmpValue = commonApi.translateDict(code, k.trim()); |
| | | } |
| | | } |
| | | //update-end--Author:scott -- Date:20210531 ----forï¼ !56 ä¼åå¾®æå¡åºç¨ä¸åå¨è¡¨å段éè¦åå
¸ç¿»è¯æ¶å è½½ç¼æ
¢é®é¢----- |
| | | |
| | | if (tmpValue != null) { |
| | | if (!"".equals(textValue.toString())) { |
| | | textValue.append(","); |
| | | } |
| | | textValue.append(tmpValue); |
| | | } |
| | | |
| | | } |
| | | return textValue.toString(); |
| | | } |
| | | |
| | | /** |
| | | * æ£æµè¿åç»æé䏿¯å¦å
å«Dict注解 |
| | | * @param records |
| | | * @return |
| | | */ |
| | | private Boolean checkHasDict(List<Object> records){ |
| | | if(oConvertUtils.isNotEmpty(records) && records.size()>0){ |
| | | for (Field field : oConvertUtils.getAllFields(records.get(0))) { |
| | | if (oConvertUtils.isNotEmpty(field.getAnnotation(Dict.class))) { |
| | | return true; |
| | | } |
| | | } |
| | | } |
| | | return false; |
| | | } |
| | | |
| | | } |