爆款云主机2核4G限时秒杀,88元/年起!
查看详情

活动

天翼云最新优惠活动,涵盖免费试用,产品折扣等,助您降本增效!
热门活动
  • 618智算钜惠季 爆款云主机2核4G限时秒杀,88元/年起!
  • 免费体验DeepSeek,上天翼云息壤 NEW 新老用户均可免费体验2500万Tokens,限时两周
  • 云上钜惠 HOT 爆款云主机全场特惠,更有万元锦鲤券等你来领!
  • 算力套餐 HOT 让算力触手可及
  • 天翼云脑AOne NEW 连接、保护、办公,All-in-One!
  • 中小企业应用上云专场 产品组合下单即享折上9折起,助力企业快速上云
  • 息壤高校钜惠活动 NEW 天翼云息壤杯高校AI大赛,数款产品享受线上订购超值特惠
  • 天翼云电脑专场 HOT 移动办公新选择,爆款4核8G畅享1年3.5折起,快来抢购!
  • 天翼云奖励推广计划 加入成为云推官,推荐新用户注册下单得现金奖励
免费活动
  • 免费试用中心 HOT 多款云产品免费试用,快来开启云上之旅
  • 天翼云用户体验官 NEW 您的洞察,重塑科技边界

智算服务

打造统一的产品能力,实现算网调度、训练推理、技术架构、资源管理一体化智算服务
智算云(DeepSeek专区)
科研助手
  • 算力商城
  • 应用商城
  • 开发机
  • 并行计算
算力互联调度平台
  • 应用市场
  • 算力市场
  • 算力调度推荐
一站式智算服务平台
  • 模型广场
  • 体验中心
  • 服务接入
智算一体机
  • 智算一体机
大模型
  • DeepSeek-R1-昇腾版(671B)
  • DeepSeek-R1-英伟达版(671B)
  • DeepSeek-V3-昇腾版(671B)
  • DeepSeek-R1-Distill-Llama-70B
  • DeepSeek-R1-Distill-Qwen-32B
  • Qwen2-72B-Instruct
  • StableDiffusion-V2.1
  • TeleChat-12B

应用商城

天翼云精选行业优秀合作伙伴及千余款商品,提供一站式云上应用服务
进入甄选商城进入云市场创新解决方案
办公协同
  • WPS云文档
  • 安全邮箱
  • EMM手机管家
  • 智能商业平台
财务管理
  • 工资条
  • 税务风控云
企业应用
  • 翼信息化运维服务
  • 翼视频云归档解决方案
工业能源
  • 智慧工厂_生产流程管理解决方案
  • 智慧工地
建站工具
  • SSL证书
  • 新域名服务
网络工具
  • 翼云加速
灾备迁移
  • 云管家2.0
  • 翼备份
资源管理
  • 全栈混合云敏捷版(软件)
  • 全栈混合云敏捷版(一体机)
行业应用
  • 翼电子教室
  • 翼智慧显示一体化解决方案

合作伙伴

天翼云携手合作伙伴,共创云上生态,合作共赢
天翼云生态合作中心
  • 天翼云生态合作中心
天翼云渠道合作伙伴
  • 天翼云代理渠道合作伙伴
天翼云服务合作伙伴
  • 天翼云集成商交付能力认证
天翼云应用合作伙伴
  • 天翼云云市场合作伙伴
  • 天翼云甄选商城合作伙伴
天翼云技术合作伙伴
  • 天翼云OpenAPI中心
  • 天翼云EasyCoding平台
天翼云培训认证
  • 天翼云学堂
  • 天翼云市场商学院
天翼云合作计划
  • 云汇计划
天翼云东升计划
  • 适配中心
  • 东升计划
  • 适配互认证

开发者

开发者相关功能入口汇聚
技术社区
  • 专栏文章
  • 互动问答
  • 技术视频
资源与工具
  • OpenAPI中心
开放能力
  • EasyCoding敏捷开发平台
培训与认证
  • 天翼云学堂
  • 天翼云认证
魔乐社区
  • 魔乐社区

支持与服务

为您提供全方位支持与服务,全流程技术保障,助您轻松上云,安全无忧
文档与工具
  • 文档中心
  • 新手上云
  • 自助服务
  • OpenAPI中心
定价
  • 价格计算器
  • 定价策略
基础服务
  • 售前咨询
  • 在线支持
  • 在线支持
  • 工单服务
  • 建议与反馈
  • 用户体验官
  • 服务保障
  • 客户公告
  • 会员中心
增值服务
  • 红心服务
  • 首保服务
  • 客户支持计划
  • 专家技术服务
  • 备案管家

了解天翼云

天翼云秉承央企使命,致力于成为数字经济主力军,投身科技强国伟大事业,为用户提供安全、普惠云服务
品牌介绍
  • 关于天翼云
  • 智算云
  • 天翼云4.0
  • 新闻资讯
  • 天翼云APP
基础设施
  • 全球基础设施
  • 信任中心
最佳实践
  • 精选案例
  • 超级探访
  • 云杂志
  • 分析师和白皮书
  • 天翼云·创新直播间
市场活动
  • 2025智能云生态大会
  • 2024智算云生态大会
  • 2023云生态大会
  • 2022云生态大会
  • 天翼云中国行
天翼云
  • 活动
  • 智算服务
  • 产品
  • 解决方案
  • 应用商城
  • 合作伙伴
  • 开发者
  • 支持与服务
  • 了解天翼云
      • 文档
      • 控制中心
      • 备案
      • 管理中心

      基于SpringBoot实现自动装配返回属性

      首页 知识中心 软件开发 文章详情页

      基于SpringBoot实现自动装配返回属性

      2024-09-25 10:14:09 阅读次数:426

      mysql,SpringBoot

      一:需求背景

      	在业务开发中经常会有这个一个场景,A(业务表)表中会记录数据的创建人,通常我们会用userId字段记录该数据的创建者,但数据的使用方会要求展示该数据的创建者姓名,故我们会关联用户表拿该用户的姓名。还有一些枚举值的含义也要展示给前端。导致原本一个单表的sql就要写成多表的关联sql,以及枚举含义的转换很是恶心。
      

      例如:业务对象BusinessEntity.java

      public class BusinessEntity {
      
          /**
           * 创建者id
           */
          private Long createUserId;
          /**
           * 创建者名称 (需要关联用户表)
           */
          private String userName;
      
          /**
           * 数据状态(0:有效,1失效)
           */
          private String status;
      
          /**
           * 数据状态含义(需要解析0或1的含义给前端)
           */
          private String statusName;
          /**
           * 数据集合
           */
          private List<BusinessEntity> list;
      }
      

      二:设计思路

      ​ 就像@JsonFormat注解,可以指定返回日期格式。我们是不是可以也自定义一个注解,通过这个注解,我们可以自动的把需要联表的数据userName自动填充,需要解析的数据数据statusName如何通过枚举解析。

      ​ 故定义枚举@AutowiredAttribute如下

      /**
       * 自动装配属性
       */
      @Target({METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE})
      @Retention(RUNTIME)
      @Documented
      public @interface AutowiredAttribute {
      
          /**
           * 当为默认值时,表明该属性为javaBean,且该javaBean需要自动注入属性
           * 否则为指向的某一个属性
           *
           * @return
           */
          String param() default "";
      
          /**
           * 默认为BaseEnum.class,
           * 当为默认时注入数据的来源时redis缓存,
           * 否则为枚举类型
           *
           * @return
           */
          Class<? extends BaseEnum> enumClass() default BaseEnum.class;
      
          /**
           * 数据源
           *
           * @return
           */
          DataSourceEnum dataSource() default DataSourceEnum.EMPTY;
      
      }
      
      

      定义公共枚举继承继承接口BaseEnum

      public interface BaseEnum {
      
          String getCode();
      
          String getMsg();
      }
      

      定义数据源枚举如下dataSource

      public enum DataSourceEnum implements BaseEnum {
      
          SYSTEM_DICT("sys:dict:", "系统字典值", "sys_dict_value", "name"),
          USER_NAME("user:name:", "用户的id与姓名的映射", "sys_user", "user_name"),
          USER_ROLE("user:role:", "角色id于角色名称映射", "sys_role", "name"),
          DEPT_NAME("dept:name:", "部门的id与部门名称的映射", "sys_dept", "name"),
          EMPTY("00", "默认", "", "");
      
          DataSourceEnum(String code, String msg, String tableName, String tableColumn) {
              this.code = code;
              this.msg = msg;
              this.tableName = tableName;
              this.tableColumn = tableColumn;
          }
      
          private String code;
          private String msg;
      
          /**
           * 表明
           */
          private String tableName;
          /**
           * 表的列
           */
          private String tableColumn;
      
          @Override
          public String getCode() {
              return code;
          }
      
          @Override
          public String getMsg() {
              return msg;
          }
      
          public String getTableName() {
              return tableName;
          }
      
          public String getTableColumn() {
              return tableColumn;
          }
      }
      
      

      三:使用方法

      对比原对象:通过新增注解,就避免的关联查询和数据解析

      public class BusinessEntity {
      
          /**
           * 创建者id
           */
          private Long createUserId;
          /**
           * 创建者名称 (需要关联用户表)
           */
          @AutowiredAttribute(param = "createUserId", dataSource = DataSourceEnum.USER_NAME)
          private String userName;
      
          /**
           * 数据状态(0:有效,1失效)
           */
          private String status;
      
          /**
           * 数据状态含义(需要解析0或1的含义给前端)
           */
          @AutowiredAttribute(param = "status", enumClass = StatusEnum.class)
          private String statusName;
          /**
           * 数据集合
           */
          @AutowiredAttribute
          private List<BusinessEntity> list;
      }
      
      

      四:注解解析器(核心代码)

      @Component
      @ControllerAdvice()
      public class FillResponseBodyAdvice implements ResponseBodyAdvice {
          private static final Logger log = LoggerFactory.getLogger(FillResponseBodyAdvice.class);
          @Autowired
          RedissonClient redissonClient;
      
          @Autowired
          JdbcTemplate jdbcTemplate;
      
          private static String GET_CODE_METHOD_NAME = "getCode";
          private static String GET_MSG_METHOD_NAME = "getMsg";
          String pageName = Page.class.getName();//分页对象名
          String baseEntityName = BaseEntity.class.getName();//自定义基础对象
      
          @Override
          public boolean supports(MethodParameter returnType, Class converterType) {
              if (ResponseResult.class.getName().equals(returnType.getMethod().getReturnType().getName())) {
                  return true;
              }
              return false;
          }
      
          @Override
          public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
              try {
                  if (((ResponseResult<?>) body).getCode() == 200 && Objects.nonNull(body)) {//仅仅对相应为200结果处理
                      Object data = ((ResponseResult<?>) body).getData();
                      Class<?> aClass = data.getClass();
                      //根路径从
                      String valueClassName = data.getClass().getName();
                      if (valueClassName.equals(pageName)) {
                          //分页对象
                          List records = ((Page<?>) data).getRecords();
                          setForListBeanArr(records);
                      } else if (data instanceof List) {
                          //集合对象设置属性
                          setForListBeanArr((List) data);
                      } else {
                          //判断是否为自定义java对象
                          if (aClass.getSuperclass() instanceof Object || valueClassName.equals(baseEntityName)) {
                              setForJavaBeanArr(data, aClass);
                          }
                      }
                  }
              } catch (Exception e) {
                  ("autowired attribute fail msg = {}", e.getMessage());
              }
              return body;
          }
      
          /**
           * 为集合对象设置属性
           *
           * @param list
           */
          void setForListBeanArr(List<Object> list) {
              for (Object object : list) {
                  Class<?> aClass = object.getClass();
                  setForJavaBeanArr(object, aClass);
              }
          }
      
          /**
           * 为自定义javaBean对象设置值
           */
          private void setForJavaBeanArr(Object data, Class<?> aClass) {
              Field[] declaredFields = aClass.getDeclaredFields();
              for (Field field : declaredFields) {
                  AutowiredAttribute annotation = field.getAnnotation(AutowiredAttribute.class);
                  if (annotation == null) {
                      continue;
                  }
                  //通过枚举注入
                  String param = annotation.param();
                  try {
                      field.setAccessible(true);
                      if (param.equals("")) {//注解表明该对象时javaBean对象
                          //获取该javaBean对象
                          Object data2 = field.get(data);
                          if (data2 == null) {
                              continue;
                          }
                          //属性是list对象
                          if (data2 instanceof List) {
                              setForListBeanArr((List) data2);
                          } else if (data2.getClass().getSuperclass() instanceof Object || data2.getClass().getName().equals(baseEntityName)) {
                              setForJavaBeanArr(data2, data2.getClass());
                          }
      
                      } else {
                          //反射获取值
                          Field field1 = aClass.getDeclaredField(param);
                          field1.setAccessible(true);
                          Object o = field1.get(data);
                          if (annotation.enumClass().getName().equals(BaseEnum.class.getName())) {
                              //通过redis注入
                              injectByEnum(o, field, data);
                          } else {
                              //通过枚举注入
                              injectByRedis(o, field, data);
                          }
                      }
                  } catch (IllegalAccessException e) {
                      e.printStackTrace();
                  } catch (NoSuchFieldException e) {
                      e.printStackTrace();
                  }
              }
          }
      
          private void injectByEnum(Object param, Field field, Object data) throws IllegalAccessException {
              AutowiredAttribute annotationAutowiredAttribute = field.getAnnotation(AutowiredAttribute.class);
              DataSourceEnum dataSourceEnum = annotationAutowiredAttribute.dataSource();
      
              if (dataSourceEnum.equals(DataSourceEnum.EMPTY)) {
                  //不规范的
              } else {
                  Object bucketValue = redissonClient.getBucket(dataSourceEnum.getCode() + param).get();
                  if (Objects.isNull(bucketValue)) {
                      bucketValue = getDictAndSetRedis(dataSourceEnum, param);
                  }
                  field.set(data, bucketValue);
              }
          }
      
          private void injectByRedis(Object param, Field field, Object data) throws IllegalAccessException {
              AutowiredAttribute annotation = field.getAnnotation(AutowiredAttribute.class);
              Class<? extends BaseEnum> aClass = annotation.enumClass();
              try {
                  // 获取所有常量
                  Object[] objects = aClass.getEnumConstants();
                  //获取指定方法
                  Method getMsg = aClass.getMethod(GET_MSG_METHOD_NAME);
                  //获取指定方法
                  Method getCode = aClass.getMethod(GET_CODE_METHOD_NAME);
                  for (Object obj : objects) {
                      if (getCode.invoke(obj).equals(param.toString())) {
                          field.set(data, getMsg.invoke(obj));
                          System.out.println(getMsg.invoke(obj));
                      }
                  }
              } catch (Exception e) {
                  System.out.println(e.getMessage());
              }
          }
      
          //
          Object getDictAndSetRedis(DataSourceEnum dataSourceEnum, Object value) {
              String sql = String.format("select %s from %s where id = %s", dataSourceEnum.getTableColumn(), dataSourceEnum.getTableName(), value);
              ("autowired attribute from sql = {}", sql);
              String dataValue = jdbcTemplate.queryForObject(sql, String.class);
              RBucket<Object> bucket = redissonClient.getBucket(dataSourceEnum.getCode() + value);
              bucket.set(dataValue);
              bucket.expire(30, TimeUnit.MINUTES);
              return dataValue;
          }
      }
      

      实现了从数据库(mysql)自动查询,并把结果缓冲到数据库。

      五:需要思考的技术点

      1.为什么注解要用到枚举和泛型class

      2.注解解析器,为什么用ResponseBodyAdvice这里解析?不在Filter,Interceptors?

      3.对于对象里面嵌套对象,或对象里面嵌套集合,怎么解决注入?递归

      版权声明:本文内容来自第三方投稿或授权转载,原文地址:https://www.cnblogs.com/jinliang374003909/p/16051843.html,作者:爱我-中华,版权归原作者所有。本网站转在其作品的目的在于传递更多信息,不拥有版权,亦不承担相应法律责任。如因作品内容、版权等问题需要同本网站联系,请发邮件至ctyunbbs@chinatelecom.cn沟通。

      上一篇:Linux:ansible-playbook配置文件(剧本)(进阶)

      下一篇:Python编程:Flask扩展Flask-Migrate迁移数据库

      相关文章

      2025-05-13 09:49:27

      mysql一些小知识点

      mysql 使用的是三值逻辑:TRUE FALSE UNKNOWN。

      2025-05-13 09:49:27
      left , mod , mysql , null , select , user
      2025-05-08 09:04:49

      MySQL-备份+日志:介质故障与数据库恢复

      MySQL-备份+日志:介质故障与数据库恢复

      2025-05-08 09:04:49
      mysql , MySQL , 备份 , 恢复 , 数据库 , 文件 , 日志
      2025-05-08 09:03:29

      windows下mybatis插入mysql数据中文乱码问题解决

      windows下mybatis插入mysql数据中文乱码问题解决

      2025-05-08 09:03:29
      amp , ini , jdbc , mysql , 乱码
      2025-05-07 09:09:52

      基础—SQL—DCL(数据控制语言)之用户管理

      基础—SQL—DCL(数据控制语言)之用户管理

      2025-05-07 09:09:52
      mysql , 创建 , 数据库 , 权限 , 用户 , 访问
      2025-05-07 09:09:52

      基础—SQL—DCL(数据控制语言)小结

      基础—SQL—DCL(数据控制语言)小结

      2025-05-07 09:09:52
      mysql , SQL , 数据库 , 权限 , 用户 , 管理 , 语句
      2025-05-07 09:08:08

      基于servlet+jsp+mysql实现的java web校园车辆管理系统

      本项目是一套基于servlet+jsp+mysql实现的java web校园车辆管理系统,主要针对计算机相关专业的正在做毕设的学生与需要项目实战练习的Java学习者。

      2025-05-07 09:08:08
      mysql , 信息 , 信息管理 , 添加 , 源码
      2025-05-07 09:07:56

      基于JavaFX和mysql实现的驾考习题管理系统

      本项目是一套基于JavaFX和mysql实现的驾考习题管理系统,主要针对计算机相关专业的正在做bishe的学生和需要项目实战练习的Java学习者。

      2025-05-07 09:07:56
      mysql , 数据库 , 项目
      2025-04-22 09:27:28

      SpringBoot 自定义TaskExecutor线程池执行异步操作

      SpringBoot 自定义TaskExecutor线程池执行异步操作

      2025-04-22 09:27:28
      SpringBoot , 异步 , 线程 , 自定义
      2025-04-11 07:15:54

      java使用JDBC方式操作mysql数据库示例

      java使用JDBC方式操作mysql数据库示例

      2025-04-11 07:15:54
      java , JDBC , mysql , 数据库 , 示例
      2025-04-11 07:12:29

      基于主流SpringBoot进行JavaWeb开发的学习路线

      基于主流SpringBoot进行JavaWeb开发的学习路线

      2025-04-11 07:12:29
      Java , SpringBoot , Vue , Web , 学习 , 开发 , 接口
      查看更多
      推荐标签

      作者介绍

      天翼云小翼
      天翼云用户

      文章

      33561

      阅读量

      5235063

      查看更多

      最新文章

      基础—SQL—DCL(数据控制语言)小结

      2025-05-07 09:09:52

      基础—SQL—DCL(数据控制语言)之用户管理

      2025-05-07 09:09:52

      基于servlet+jsp+mysql实现的java web校园车辆管理系统

      2025-05-07 09:08:08

      基于JavaFX和mysql实现的驾考习题管理系统

      2025-05-07 09:07:56

      SpringBoot 自定义TaskExecutor线程池执行异步操作

      2025-04-22 09:27:28

      基于主流SpringBoot进行JavaWeb开发的学习路线

      2025-04-11 07:12:29

      查看更多

      热门文章

      MySQL 5.7 JSON函数学习

      2023-04-27 08:00:00

      mysql列存储引擎-字符串属性列-列压缩测试

      2023-04-23 09:34:23

      SpringBoot 单元测试(三十六)

      2024-09-25 10:14:09

      Ajax提交数据SpringBoot后台报错“HttpMessageNotReadableException: JSON parse error: Cannot construct instance“

      2023-06-13 08:29:06

      AOP 中 获取常见的各种参数方法合集

      2023-05-15 10:01:00

      Python编程:利用上下文管理器管理MySQL的链接对象

      2023-02-21 03:02:11

      查看更多

      热门标签

      java Java python 编程开发 代码 开发语言 算法 线程 Python html 数组 C++ 元素 javascript c++
      查看更多

      相关产品

      弹性云主机

      随时自助获取、弹性伸缩的云服务器资源

      天翼云电脑(公众版)

      便捷、安全、高效的云电脑服务

      对象存储

      高品质、低成本的云上存储服务

      云硬盘

      为云上计算资源提供持久性块存储

      查看更多

      随机文章

      Mysql 5.7大量数据修改表结构解决办法(插入一千万条数据测试)

      如何自定义一个starter步骤详解

      185.Spring Boot使用FastJson解析JSON数据:中文乱码

      杀掉链接mysql库线程的方法

      手把手搭建SpringBoot电子商城网站【附源码】(毕设)

      mysql/stonedb-多线程聚合的数据访问问题

      • 7*24小时售后
      • 无忧退款
      • 免费备案
      • 专家服务
      售前咨询热线
      400-810-9889转1
      关注天翼云
      • 旗舰店
      • 天翼云APP
      • 天翼云微信公众号
      服务与支持
      • 备案中心
      • 售前咨询
      • 智能客服
      • 自助服务
      • 工单管理
      • 客户公告
      • 涉诈举报
      账户管理
      • 管理中心
      • 订单管理
      • 余额管理
      • 发票管理
      • 充值汇款
      • 续费管理
      快速入口
      • 天翼云旗舰店
      • 文档中心
      • 最新活动
      • 免费试用
      • 信任中心
      • 天翼云学堂
      云网生态
      • 甄选商城
      • 渠道合作
      • 云市场合作
      了解天翼云
      • 关于天翼云
      • 天翼云APP
      • 服务案例
      • 新闻资讯
      • 联系我们
      热门产品
      • 云电脑
      • 弹性云主机
      • 云电脑政企版
      • 天翼云手机
      • 云数据库
      • 对象存储
      • 云硬盘
      • Web应用防火墙
      • 服务器安全卫士
      • CDN加速
      热门推荐
      • 云服务备份
      • 边缘安全加速平台
      • 全站加速
      • 安全加速
      • 云服务器
      • 云主机
      • 智能边缘云
      • 应用编排服务
      • 微服务引擎
      • 共享流量包
      更多推荐
      • web应用防火墙
      • 密钥管理
      • 等保咨询
      • 安全专区
      • 应用运维管理
      • 云日志服务
      • 文档数据库服务
      • 云搜索服务
      • 数据湖探索
      • 数据仓库服务
      友情链接
      • 中国电信集团
      • 189邮箱
      • 天翼企业云盘
      • 天翼云盘
      ©2025 天翼云科技有限公司版权所有 增值电信业务经营许可证A2.B1.B2-20090001
      公司地址:北京市东城区青龙胡同甲1号、3号2幢2层205-32室
      • 用户协议
      • 隐私政策
      • 个人信息保护
      • 法律声明
      备案 京公网安备11010802043424号 京ICP备 2021034386号