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. 使用…...
React 第五十五节 Router 中 useAsyncError的使用详解
前言 useAsyncError 是 React Router v6.4 引入的一个钩子,用于处理异步操作(如数据加载)中的错误。下面我将详细解释其用途并提供代码示例。 一、useAsyncError 用途 处理异步错误:捕获在 loader 或 action 中发生的异步错误替…...
PHP和Node.js哪个更爽?
先说结论,rust完胜。 php:laravel,swoole,webman,最开始在苏宁的时候写了几年php,当时觉得php真的是世界上最好的语言,因为当初活在舒适圈里,不愿意跳出来,就好比当初活在…...
DockerHub与私有镜像仓库在容器化中的应用与管理
哈喽,大家好,我是左手python! Docker Hub的应用与管理 Docker Hub的基本概念与使用方法 Docker Hub是Docker官方提供的一个公共镜像仓库,用户可以在其中找到各种操作系统、软件和应用的镜像。开发者可以通过Docker Hub轻松获取所…...
Linux简单的操作
ls ls 查看当前目录 ll 查看详细内容 ls -a 查看所有的内容 ls --help 查看方法文档 pwd pwd 查看当前路径 cd cd 转路径 cd .. 转上一级路径 cd 名 转换路径 …...
Java多线程实现之Callable接口深度解析
Java多线程实现之Callable接口深度解析 一、Callable接口概述1.1 接口定义1.2 与Runnable接口的对比1.3 Future接口与FutureTask类 二、Callable接口的基本使用方法2.1 传统方式实现Callable接口2.2 使用Lambda表达式简化Callable实现2.3 使用FutureTask类执行Callable任务 三、…...
Java 加密常用的各种算法及其选择
在数字化时代,数据安全至关重要,Java 作为广泛应用的编程语言,提供了丰富的加密算法来保障数据的保密性、完整性和真实性。了解这些常用加密算法及其适用场景,有助于开发者在不同的业务需求中做出正确的选择。 一、对称加密算法…...
微服务商城-商品微服务
数据表 CREATE TABLE product (id bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 商品id,cateid smallint(6) UNSIGNED NOT NULL DEFAULT 0 COMMENT 类别Id,name varchar(100) NOT NULL DEFAULT COMMENT 商品名称,subtitle varchar(200) NOT NULL DEFAULT COMMENT 商…...
C# 类和继承(抽象类)
抽象类 抽象类是指设计为被继承的类。抽象类只能被用作其他类的基类。 不能创建抽象类的实例。抽象类使用abstract修饰符声明。 抽象类可以包含抽象成员或普通的非抽象成员。抽象类的成员可以是抽象成员和普通带 实现的成员的任意组合。抽象类自己可以派生自另一个抽象类。例…...
动态 Web 开发技术入门篇
一、HTTP 协议核心 1.1 HTTP 基础 协议全称 :HyperText Transfer Protocol(超文本传输协议) 默认端口 :HTTP 使用 80 端口,HTTPS 使用 443 端口。 请求方法 : GET :用于获取资源,…...
Python 实现 Web 静态服务器(HTTP 协议)
目录 一、在本地启动 HTTP 服务器1. Windows 下安装 node.js1)下载安装包2)配置环境变量3)安装镜像4)node.js 的常用命令 2. 安装 http-server 服务3. 使用 http-server 开启服务1)使用 http-server2)详解 …...
