目录

  • 前言
  • 源码
  • 思维导图

前言

一般来说,项目开发会用自定义注解去实现日志监控等操作
在实际项目中,前后台数据交互时,每次都需要根据一个code值去进行查询数据库进行中间操作进行获取text值
本博文用自定义注解结合aop实现数据字典的自动翻译

源码

首先附上数据库表结构:

数据字典表(dict)

数据字典类型中间表(dict_type)

用户表(user)

注解类(Dict)

package com.xiaoyang.annotation;import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;/*** @author xiaoyang* @create  2020-11-27 10:36* 数据字典的数字转汉字的自定义注解*/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Dict {/*** 数据dataSource** @return*/String dictDataSource();/*** 返回put到json中的文本key* @return*/String dictText() default "";
}

Controller:

package com.xiaoyang.controller;import com.xiaoyang.model.User;
import com.xiaoyang.service.UserService;
import com.xiaoyang.util.PageBean;
import com.xiaoyang.util.PageUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;import javax.servlet.http.HttpServletRequest;
import java.util.List;/*** @author xiaoyang* @create  2020-11-27 16:47*/
@Controller
@RequestMapping("/user")
public class UserController {@Autowiredprivate UserService userService;@ResponseBody@RequestMapping("/QueryPager")public PageUtils QueryPager(HttpServletRequest req) {User user=new User();user.setName("a");PageBean pageBean = new PageBean();pageBean.setRequest(req);List<User> users = this.userService.QueryPager(user, pageBean);PageUtils pageUtils = new PageUtils(users, pageBean.getTotal());return pageUtils;}
}

aop切面类:

package com.xiaoyang;import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.xiaoyang.annotation.Dict;
import com.xiaoyang.service.DictService;
import com.xiaoyang.util.ObjConvertUtils;
import com.xiaoyang.util.PageUtils;
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.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;import java.lang.reflect.Field;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;/**@author xiaoyang@create  2020-11-27 16:52*/
@Aspect
@Component
@Slf4j
public class DictAspect {//这是操作数据字典那张表的 service@Autowiredprivate DictService dictService;//翻译后拼接的内容private static String DICT_TEXT_SUFFIX = "_dictText";// 定义切点Pointcut 拦截所有对服务器的请求@Pointcut("execution( * com.xiaoyang..controller.*.*(..))")public void excudeService() {}/*** 这是触发 excudeService 的时候会执行的** @param pjp* @return* @throws Throwable*/@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();//开始解析(翻译字段内部的值凡是打了 @Dict 这玩意的都会被翻译)this.parseDictText(result);//解析结束时间long end = System.currentTimeMillis();log.debug("解析注入JSON数据  耗时" + (end - start) + "ms");return result;}/*** 本方法针对返回对象为Result 的IPage的分页列表数据进行动态字典注入* 字典注入实现 通过对实体类添加注解@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 void parseDictText(Object result) {if (result instanceof PageUtils) {List<JSONObject> items = new ArrayList<>();PageUtils pageUtils = (PageUtils) result;//循环查找出来的数据for (Object record : pageUtils.getData()) {ObjectMapper mapper = new ObjectMapper();String json = "{}";try {//解决@JsonFormat注解解析不了的问题详见SysAnnouncement类的@JsonFormatjson = mapper.writeValueAsString(record);} catch (JsonProcessingException e) {log.error("json解析失败" + e.getMessage(), e);}JSONObject item = JSONObject.parseObject(json);//update-begin--Author:scott -- Date:20190603 ----for:解决继承实体字段无法翻译问题------//for (Field field : record.getClass().getDeclaredFields()) {for (Field field : ObjConvertUtils.getAllFields(record)) {//update-end--Author:scott  -- Date:20190603 ----for:解决继承实体字段无法翻译问题------if (field.getAnnotation(Dict.class) != null) {String code = field.getAnnotation(Dict.class).dictDataSource();String text = field.getAnnotation(Dict.class).dictText();//获取当前带翻译的值String key = String.valueOf(item.get(field.getName()));//翻译字典值对应的txtString textValue = translateDictValue(code, key);//  CommonConstant.DICT_TEXT_SUFFIX的值为,是默认值:// public static final String DICT_TEXT_SUFFIX = "_dictText";log.debug(" 字典Val : " + textValue);log.debug(" __翻译字典字段__ " + field.getName() + DICT_TEXT_SUFFIX + ": " + textValue);//如果给了文本名if (!StringUtils.isEmpty(text)) {item.put(text, textValue);} else {//走默认策略item.put(field.getName() + 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()))));}}items.add(item);}pageUtils.setData(items);}}/*** 翻译字典文本** @param code* @param key* @return*/private String translateDictValue(String code, String key) {//如果key为空直接返回就好了if (ObjConvertUtils.isEmpty(key)) {return null;}StringBuffer textValue = new StringBuffer();//分割 key 值System.out.println(code+":::::"+key);String[] keys = key.split(",");//循环 keys 中的所有值for (String k : keys) {String tmpValue = null;log.debug(" 字典 key : " + k);if (k.trim().length() == 0) {continue; //跳过循环}tmpValue = dictService.selectByDatasourceCode(code,k.trim());if (tmpValue != null) {if (!"".equals(textValue.toString())) {textValue.append(",");}textValue.append(tmpValue);}}//返回翻译的值return textValue.toString();}}

工具类(反射类):

package com.xiaoyang.util;import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;/*** @author xiaoyang* @create  2020-11-29 8:32*/
public class ObjConvertUtils {/*** 获取类的所有属性,包括父类** @param object* @return*/public static Field[] getAllFields(Object object) {Class<?> clazz = object.getClass();List<Field> fieldList = new ArrayList<>();while (clazz != null) {fieldList.addAll(new ArrayList<>(Arrays.asList(clazz.getDeclaredFields())));clazz = clazz.getSuperclass();}Field[] fields = new Field[fieldList.size()];fieldList.toArray(fields);return fields;}public static boolean isEmpty(Object object) {if (object == null) {return (true);}if ("".equals(object)) {return (true);}if ("null".equals(object)) {return (true);}return (false);}}

User的实体类中使用注解(可传两个参数,这里使用注解后会在切面类进行获取注解的内容进行数据库查询,例如这里userlevel属性注解传入的是user_level,那么controller层查询出结果集合后,在切面类进行字典表对应字段的查询):

结果:

思维导图

自定义注解运用aop的思想去进行数据字典的转译从根本上来说就是为了简化我们的代码,实现后不需要每次都调用方法去查询(需结合缓存)
最后附上流程图供理解:

over…

Aop+自定义注解实现数据字典翻译相关推荐

  1. AOP+自定义注解实现字典翻译

    目录 需求: 结果展示 : 代码实现 : 需求: 一般情况下数据库表中字段对应的是字典值,但在查询或导出时需要展示字典名,若每次字典转换时都需要关联字典表查询,而且导出时还需要在做一次数据转换,这样处 ...

  2. JPOM - AOP+自定义注解实现操作日志记录

    文章目录 地址 版本 源码解析-AOP+自定义注解实现操作日志记录 地址 Gitee: https://gitee.com/dromara/Jpom 官网: https://jpom.io/ 一款简而 ...

  3. spring AOP自定义注解方式实现日志管理

    转:spring AOP自定义注解方式实现日志管理 今天继续实现AOP,到这里我个人认为是最灵活,可扩展的方式了,就拿日志管理来说,用Spring AOP 自定义注解形式实现日志管理.废话不多说,直接 ...

  4. springboot+aop+自定义注解,打造通用的全局异常处理和参数校验切面(通用版)

    springboot+aop+自定义注解,打造通用的全局异常处理和参数校验切面(通用版) 参考文章: (1)springboot+aop+自定义注解,打造通用的全局异常处理和参数校验切面(通用版) ( ...

  5. Java AOP自定义注解

    一.背景 在之前文章:Java注解详解中,主要介绍了注解的含义.作用.以及常用的各类注解.今天主要介绍在Springboot中如何实现一个自定义注解,通过自定义注解去实现一些定制化的需求. 二.了解元 ...

  6. spring aop 自定义注解配合swagger注解保存操作日志到mysql数据库含(源码)

    spring aop 自定义注解保存操作日志到mysql数据库 一.思路 二.自定义注解 三.编写操作日志 四.编写操作日志切面\增强 五.使用 六.`注意` 一.思路 利用spring aop 对方 ...

  7. Spring AOP自定义注解并获取注解的参数

    环境 springboot:1.5 Intellij IDEA:2021.1 序言 最近有个需求,要做方法层面的权限控制.以前在公司使用的是spring security,然后使用注解 如下: @Pr ...

  8. AOP+自定义注解 实现service统一的异常信息处理

    返回信息枚举 TipsMsg: public enum TipsMsg {DEFAULT_SUCCESS("0","操作成功"),DEFAULT_FAILED( ...

  9. aop注解配置切点 spring_springboot aop 自定义注解方式实现一套完善的日志记录

    一:功能简介 本文主要记录如何使用aop切面的方式来实现日志记录功能. 主要记录的信息有: 操作人,方法名,参数,运行时间,操作类型(增删改查),详细描述,返回值. 二:项目结构图 如果想学习Java ...

最新文章

  1. 三分钟破解无线网——无线网络安全攻防
  2. 【c++版数据结构】之循环单链表的实现(带头结点以及尾节点)
  3. unix高级环境编程-基础知识
  4. 阿里云消息队列Kafka商业化:支持消息无缝迁移到云上
  5. android webview调js方法,Android中WebView与H5的交互,Native与JS方法互调
  6. Node聊天程序实例04:chat_ui.js
  7. C语言入门学习(入门级C语言)
  8. 计算机毕业设计 SSM+Vue教师考核系统 教师绩效考核系统 学校教师考核系统 教师绩效考核管理系统Java Vue MySQL数据库 远程调试 代码讲解
  9. matlab 不显示图中的x,y轴
  10. Moore-Penrose广义逆矩阵
  11. echarts饼图默认中间显示总数
  12. 微信授权登录的多帐号问题
  13. 第三十八章 短语动词
  14. 【详细】小程序发微博功能实现
  15. pandas将dataframe的所有数据列的名称转化为大写形式(all column labels in dataframe to uppercase)
  16. [C++]小根堆 插入/删除/初始化
  17. Ubuntu安装eigen
  18. swift基础学习笔记
  19. 微信小程序怎么新建页面
  20. 智慧指间丨水污染预警溯源平台,实现“污水零直排”长效监管

热门文章

  1. [Toddler's Bottle]-collision
  2. 原生JS实现slice方法
  3. SubQuery总结
  4. 用Phaser来制作一个html5游戏——flappy bird (一)
  5. ITSS信息技术服务标准是什么?
  6. 网易云音乐Java面试题:Mybatis事务+SpringBean+Java锁+Redis
  7. System.NullReferenceException HResult=0x80004003 Message=未将对象引用设置到对象的实例。
  8. 详细前端面试题HTML篇
  9. html总结常见问题
  10. html图片3d球体,HTML5 三维透视球体运动