Jeecgboot 字典值自动转化:DictAspect类方法改造,支持IPage、List、Object、Map类自动转化,附有源码
改造的是DictAspect类:
原来使用的 parseDictText(Object result)方法,针对返回对象为Result 的IPage的分页列表数据进行动态字典注入,当单个对象查询,列表查询,或者多个数据放到Map中时,就不会自动转化,在web端进行展示的时候就需要连表查询或者手动查询字典值,不方便使用。
于是我改造了parseDictText()方法,不仅针对返回对象为Result时的分页列表,还支持列表、对象以及Map类型的结果。实在Result对象执行setResult()方式时进行自动注入转换。
原方法
代码:
private Object parseDictText(Object result) {//if (result instanceof Result) {if (true) {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类的@JsonFormatjson = 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();//update-begin---author:chenrui ---date:20231221 for:[issues/#5643]解决分布式下表字典跨库无法查询问题------------String dataSource = field.getAnnotation(Dict.class).ds();//update-end---author:chenrui ---date:20231221 for:[issues/#5643]解决分布式下表字典跨库无法查询问题------------List<String> dataList;String dictCode = code;if (!StringUtils.isEmpty(table)) {//update-begin---author:chenrui ---date:20231221 for:[issues/#5643]解决分布式下表字典跨库无法查询问题------------dictCode = String.format("%s,%s,%s,%s", table, text, code, dataSource);//update-end---author:chenrui ---date:20231221 for:[issues/#5643]解决分布式下表字典跨库无法查询问题------------}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();//update-begin---author:chenrui ---date:20231221 for:[issues/#5643]解决分布式下表字典跨库无法查询问题------------// 自定义的字典表数据源String dataSource = field.getAnnotation(Dict.class).ds();//update-end---author:chenrui ---date:20231221 for:[issues/#5643]解决分布式下表字典跨库无法查询问题------------String fieldDictCode = code;if (!StringUtils.isEmpty(table)) {//update-begin---author:chenrui ---date:20231221 for:[issues/#5643]解决分布式下表字典跨库无法查询问题------------fieldDictCode = String.format("%s,%s,%s,%s", table, text, code, dataSource);//update-end---author:chenrui ---date:20231221 for:[issues/#5643]解决分布式下表字典跨库无法查询问题------------}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;}
改造
判断传递参数的类型,是IPage、List、Map、Object,如果是IPage、List、Map,则把对象中的数据拿出来再挨个转换,改造为新的结果数据返回。
private Object parseDictText(Object result) {if (result instanceof Result) {List<Object> list = new LinkedList<>();if (((Result) result).getResult() instanceof IPage) {//分页list = ((IPage) ((Result) result).getResult()).getRecords();} else if (((Result) result).getResult() instanceof List) {//List集合list = (List<Object>) ((Result) result).getResult();} else if (((Result) result).getResult() instanceof Map) {//mapMap<Object, Object> map = (Map<Object, Object>) ((Result) result).getResult();Map<Object, Object> itemMap = new HashMap<>();for (Map.Entry entry : map.entrySet()) {//System.out.println(entry.getKey() + " " + entry.getValue());Map mapRe = new HashMap();if (entry.getValue() instanceof List) {//列表List<Object> listItems = new ArrayList<>();for (Object record : (List) entry.getValue()) {if (checkIsJsonStr(record)) {//字典翻译record = this.dictEscape(record);}listItems.add(record);}itemMap.put(entry.getKey(), listItems);} else if (entry.getValue() instanceof Object) {//单对象Object record = entry.getValue();//判断能否转换成JSON,因为有些结果集返回的是String类型,导致翻译异常,因此判断是否可以转换jsonif (checkIsJsonStr(record)) {//字典翻译record = this.dictEscape(record);}itemMap.put(entry.getKey(), record);}}((Result) result).setResult(itemMap);} else {//单对象Object record = ((Result) result).getResult();//判断能否转换成JSON,因为有些结果集返回的是String类型,导致翻译异常,因此判断是否可以转换jsonif (checkIsJsonStr(record)) {//字典翻译record = this.dictEscape(record);}((Result) result).setResult(record);}//列表解析if (list != null && list.size() > 0) {List<Object> items = new ArrayList<>();for (Object record : list) {if (checkIsJsonStr(record)) {//字典翻译record = this.dictEscape(record);}items.add(record);}if (((Result) result).getResult() instanceof IPage) {((IPage) ((Result) result).getResult()).setRecords(items);} else if (((Result) result).getResult() instanceof List) {((Result) result).setResult(items);}}}return result;}
字典翻译方法:
/*** 字典翻译** @param record* @return*/private JSONObject dictEscape(Object record) {ObjectMapper mapper = new ObjectMapper();String json = "{}";JSONObject item = null;try {//解决@JsonFormat注解解析不了的问题详见SysAnnouncement类的@JsonFormatjson = mapper.writeValueAsString(record);//对象序列化为JSON字符串} catch (JsonProcessingException e) {log.error("json解析失败" + e.getMessage(), e);}try {item = JSONObject.parseObject(json);//update-begin--Author:scott -- Date:20190603 ----for:解决继承实体字段无法翻译问题------for (Field field : oConvertUtils.getAllFields(record)) {//update-end--Author:scott -- Date:20190603 ----for:解决继承实体字段无法翻译问题------if (field.getAnnotation(Dict.class) != null) {String code = field.getAnnotation(Dict.class).dicCode();String text = field.getAnnotation(Dict.class).dicText();String table = field.getAnnotation(Dict.class).dictTable();String key = String.valueOf(item.get(field.getName()));//翻译字典值对应的txtString textValue = key;//非中文时翻译if (!checkCountName(key)) {textValue = translateDictValue(code, text, table, key);}log.debug(" 字典Val : " + textValue);log.debug(" __翻译字典字段__ " + field.getName() + CommonConstant.DICT_TEXT_SUFFIX + ": " + textValue);item.put(field.getName() + CommonConstant.DICT_TEXT_SUFFIX, textValue);}//date类型默认转换string格式化日期if (field.getType().getName().equals("java.util.Date") && 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()))));}}} catch (Exception e) {log.info("字典翻译异常:" + e.getMessage(), e);}return item;}
检测是否是中文:
/*** 检测是否是中文** @param countName* @return*/public static boolean checkCountName(String countName) {Pattern p = Pattern.compile("[\u4e00-\u9fa5]");Matcher m = p.matcher(countName);if (m.find()) {return true;}return false;}
检测是否可转换为JSON字符串
/*** 检测是否可转换为JSON字符串** @param record* @return*/public static boolean checkIsJsonStr(Object record) {boolean jsonFlag = false;try {String json = new ObjectMapper().writeValueAsString(record);if (json.startsWith("{")) {jsonFlag = true;}} catch (JsonProcessingException e) {e.printStackTrace();}return jsonFlag;}
相关文章:
Jeecgboot 字典值自动转化:DictAspect类方法改造,支持IPage、List、Object、Map类自动转化,附有源码
改造的是DictAspect类: 原来使用的 parseDictText(Object result)方法,针对返回对象为Result 的IPage的分页列表数据进行动态字典注入,当单个对象查询,列表查询,或者多个数据放到Map中时,就不会自动转化&am…...
DVWA DOM Based Cross Site Scripting (DOM型 XSS)
DVWA DOM Based Cross Site Scripting (DOM型 XSS) 文章目录 DVWA DOM Based Cross Site Scripting (DOM型 XSS)XSS跨站原理DOM型 LowMediumHighImpossible XSS跨站原理 当应用程序发送给浏览器的页面中包含用户提交的数据,但没有经过适当验证或转义时,就…...
LinkedList集合及迭代器的源码分析
一.介绍: 二.LinkedList集合特有的API: 三.迭代器的源码分析: package com.itheima.a03myarraylist;import java.util.ArrayList; import java.util.Iterator;public class A01_ArrayListDemo1 {public static void main(String[] args) {ArrayList<String> listnew Arr…...
Go调度器
线程数过多,意味着操作系统会不断地切换线程,频繁的上下文切换就成了性能瓶颈.Go提供一种机制 可以在线程中自己实现调度,上下文切换更轻量,从而达到线程数少,而并发数并不少的效果,而线程中调度的就是Goroutine 调度器主要概念: 1.G:即Go协程,每个go关键字都会创建一个协程…...
当node节点kubectl 命令无法连接到 Kubernetes API 服务器
1.问题 当node节点当node节点kubectl 命令无法连接到 Kubernetes API 服务器 [rootnode1 ~]# kubectl get nodes The connection to the server localhost:8080 was refused - did you specify the right host or port?2. 确认 kubeconfig 文件 确保节点上有有效的 kubeco…...
直接通过类CURL方式,与GRPC方法交互的命令行工具
大家好,今天给大家分享的是一个命令行工具grpcurl,它能够直接与 gRPC 服务进行交互。 项目介绍 您可以把grpcurl想象成是 curl 的 gRPC 版本,但是功能更加强大。 由于 gRPC 服务之间的通信使用的是 Protocol Buffers (Protobuf) 格式的二进…...
Hive3:数据的加载与导出
一、加载数据 在创建表之后,表中没有数据,我们不可能insert存入数据。 而是,通过数据加载,将HDFS中的数据关联到Hive表中。 建表 CREATE TABLE myhive.test_load(dt string comment 时间(时分秒), user_…...
React事件绑定的方式有哪些?区别?
React 中事件绑定的方式主要有以下几种: 直接在 JSX 中绑定事件: <button onClick{handleClick}>Click me</button> 这是最常见和推荐的方式。事件名(如 onClick)作为 JSX 的属性,值为一个函数,…...
ibis:极具潜力的Python数据分析新框架
今天要给大家介绍的Python框架叫做ibis,没错,跟著名连锁酒店宜必思同名,其作者是创造了pandas、Arrow等著名框架的Wes McKinney。 ibis的核心理念是用同一套数据框操作API,统一操纵各种主流的数据运算框架,使得用户可以…...
SQL Zoo 8+.NSS Tutorial
以下数据来自SQL Zoo 1.at Edinburgh Napier University,studying (8) Computer Science,Show the the percentage who STRONGLY AGREE.(在爱丁堡纳皮尔大学,学习“计算机科学”,显示STRONGLY AGREE的百分比࿰…...
conda pack迁移环境
文章目录 下载conda pack打包已有环境还原环境 因为有的服务器没有网络,如果想要安装自己的虚拟环境,就需要在有网络的服务器安装好环境后迁移到没有网络的服务器。conda-pack是一个命令行工具,用于打包 conda 环境,pip inatall和…...
UML建模案例分析-活动图商业建模
概述 活动图主要用来描述如何完成工作以及做什么工作。可以用活动图来描述操作、类或 用例,但是它们只能显示工作流。可以用活动图来进行商业建模,在模型中,工作、工 人、组织、对象被显示。 案例 在商业建模时,下列方面是模型要…...
C++标准模板(STL)- 低层内存管理 - 解分配函数 (operator delete, operator delete[])
低层内存管理 new 表达式是创建拥有动态存储期对象或对象数组的仅有方式,即它们拥有不受制于创建所它们在的作用域的生存期。 new 表达式通过调用分配函数获得存储。 delete 表达式销毁最终导出对象或通过 new 表达式创造的数组,然后调用解分配函数。默认…...
LeetCode 热题 HOT 100 (025/100)【宇宙最简单版】
【二叉树】No. 0124 二叉树中的最大路径和 【困难】👉力扣对应题目指路 希望对你有帮助呀!!💜💜 如有更好理解的思路,欢迎大家留言补充 ~ 一起加油叭 💦 欢迎关注、订阅专栏 【力扣详解】谢谢你…...
【mysql 第三篇章】一条 update语句是怎么持久化到磁盘上的?
首先看一下这个 SQL 语句你会不会写? 下面是说明执行这个 SQL 语句,数据库底层做了什么操作。 update users set namexxx where id10;在引擎要执行更新语句的时候,比如更新 id10 这行数据时,他会先查看数据在缓冲池中是否存在,如…...
深入探索大模型:从基础到实践,开启AI之旅
摘要: 在人工智能领域,大模型技术正成为推动创新和进步的关键力量。对于初学者而言,掌握大模型的基本概念、理论和技术是至关重要的。 本文将为你提供一个全面的学习路线,帮助你从基础知识出发,逐步深入到大模型的实践…...
题解:力扣1567 - 返回乘积为正数的最长子数组
问题描述 给定一个整数数组 nums,找出乘积为正数的最长子数组的长度。这里的子数组定义为连续元素的序列,乘积为正数指子数组中正数的个数必须大于负数的个数。 解题思路 为了解决这个问题,我们可以使用两个数组 f 和 g 分别表示以当前位置…...
009 | 上证50ETF基金数据分析及预测
项目背景 中国股市的发展历程坎坷,从最初的茫然到现在的逐步成熟,股市已经成为中国经济发展的重要标志之一。然而,当前中国股市仍存在投机行为过度和定价机制不完善等问题。为更好地理解和预测股市走势,本项目聚焦于上证50ETF基金的历史数据分析和未来走势预测。 项目目标…...
Wakanda: 1靶场复现【附代码】(权限提升)
靶机下载地址: wakanda: 1 ~ VulnHubwakanda: 1, made by xMagass. Download & walkthrough links are available.https://www.vulnhub.com/entry/wakanda-1,251/#download 1. 主机发现端口扫描目录扫描敏感信息获取 1.1. 主机发现 nmap -sn 192.168.7.0/24…...
内核函数调试
要进入 bind 函数的内部进行调试,实际上是不能直接在用户空间代码中进入内核内部的 bind 实现,因为 bind 是一个系统调用,它由内核处理。尽管如此,你可以通过以下几种方法来间接调试 bind 函数并理解它的行为: 1. 使用…...
Midjourney锐化效果失效真相(2024官方未公开的渲染管线瓶颈解析)
更多请点击: https://intelliparadigm.com 第一章:Midjourney锐化效果失效真相(2024官方未公开的渲染管线瓶颈解析) 自2024年V6.2版本起,大量用户反馈 --stylize 与 --sharp 参数组合下图像边缘锐化效果显著弱化&am…...
别再死记硬背了!用5个生活化比喻彻底搞懂Linux进程的fork、exec和wait
别再死记硬背了!用5个生活化比喻彻底搞懂Linux进程的fork、exec和wait想象你正在厨房准备一顿大餐。菜谱上写着"切菜"、"炒菜"、"装盘"等步骤,但突然发现需要同时处理多道菜品——这时候,你会本能地让家人分工…...
CPU架构启发的智能仓储布局优化实践
1. 仓库布局优化的核心挑战与创新机遇在物流仓储领域,拣货环节通常占据运营成本的55%-65%,而其中约50%的时间消耗在无效行走路径上。传统矩形仓库布局虽然易于规划和施工,但其正交的通道设计导致拣货员需要频繁进行90度转向,这种&…...
Arcmap实操:如何用‘渔网’给你的地图做一次‘CT扫描’——以韶关市路网密度可视化为例
Arcmap实操:如何用‘渔网’给你的地图做一次‘CT扫描’——以韶关市路网密度可视化为例 想象一下,医生通过CT扫描将人体内部结构分层呈现,而GIS中的"渔网"工具同样能对城市路网进行"切片式"分析。这种空间离散化技术&…...
HarmonyOS 6学习:解决图片放大后无法移动至边缘的matrix4矩阵变换技巧
从"卡在中间"到"自由拖拽":一次完整的图片缩放平移边界问题攻关在HarmonyOS 6应用开发中,我最近遇到了一个看似简单却让人头疼的图片查看器问题:用户双指放大图片后,想要拖动查看边缘细节,却发现图…...
1688运营培训/询盘成本从500元降到63.9!1688运营培训还原1688真实玩法
1688运营培训/询盘成本从500元降到63.9!1688运营培训还原1688真实玩法500块钱一个询盘,你敢信?做1688运营培训这么多年,这个数字我都觉得离谱。前阵子遇到一个老板,一上来就开始吐槽1688,说1688就是个垃圾平…...
Android Root检测绕过:从逆向分析到Frida分层Hook实战
1. 这不是“绕过root检测”,而是理解检测逻辑后的精准干预在安卓逆向工程的实际工作中,“过root检测”这个说法本身就容易引发误解——它听起来像某种黑箱魔法,仿佛只要套用某个脚本、加载某个插件,就能让App对设备状态“视而不见…...
League Akari:如何通过LCU API实现英雄联盟游戏流程的智能化管理?
League Akari:如何通过LCU API实现英雄联盟游戏流程的智能化管理? 【免费下载链接】League-Toolkit An all-in-one toolkit for LeagueClient. Gathering power 🚀. 项目地址: https://gitcode.com/gh_mirrors/le/League-Toolkit Leag…...
理想二极管控制器:用MOSFET实现毫伏级压降的电源管理方案
1. 理想二极管控制器:告别传统二极管的压降损耗 在电源设计、电池保护、太阳能板并联这些领域里,二极管是个再常见不过的元件。我们用它来防反接、做整流、实现“或”逻辑供电,几乎不假思索。但如果你设计过一个需要处理大电流、低电压的系统…...
绝了!原来毕业论文还能这样写?2026降AIGC工具推荐合集
还在为查重率爆红、AI痕迹太明显、格式乱成一团而发愁?2026 年的 AI 论文工具早已不只是写文章那么简单,从选题构思到降AIGC率、去AI痕迹、查重优化,全流程智能辅助,帮你把论文写作变得简单高效,告别熬夜改稿的焦虑&am…...
