基于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 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 list;
}
四:注解解析器(核心代码)
/**
* 填充相应体
*/
@Component
@ControllerAdvice()
public class FillResponseBodyAdvice implements ResponseBodyAdvice {@Autowired
RedissonClient redissonClient;
@Autowired
JdbcTemplate jdbcTemplate;
private static String GET_CODE_METHOD_NAME = "getCode";
private static String GET_MSG_METHOD_NAME = "getMsg";
@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) {
if (((ResponseResult>) body).getCode() == 200) {//仅仅对相应为200结果处理
Object data = https://www.it610.com/article/((ResponseResult>) body).getData();
Class> aClass = data.getClass();
if (data instanceof List) {
//集合对象设置属性
setForListBeanArr((List) data);
} else {
//判断是否为自定义java对象
if (aClass.getSuperclass() instanceof Object) {
setForJavaBeanArr(data, aClass);
}
}
}
return body;
}/**
* 为集合对象设置属性
*
* @param list
*/
void setForListBeanArr(List
实现了从数据库(mysql)自动查询,并把结果缓冲到数据库。
五:需要思考的技术点
1.为什么注解要用到枚举和泛型class
2.注解解析器,为什么用ResponseBodyAdvice这里解析?不在Filter,Interceptors?
3.对于对象里面嵌套对象,或对象里面嵌套集合,怎么解决注入?递归
结束语
【基于SpringBoot实现自动装配返回属性】欢迎大家使用,如果遇到问题可一起探讨,如果帮助了你可点赞子支持一下。
推荐阅读
- vue使用echarts实现地图的方法详解
- Java数据结构之平衡二叉树的原理与实现
- Java实现简单班级管理系统
- C语言猜凶手及类似题目的实现示例
- 新建springboot项目时|新建springboot项目时,entityManagerFactory报错的解决
- 解决springboot没有启动标识|解决springboot没有启动标识,启动类也没有启动标识的问题
- 3D 沙盒游戏之避障踩坑和实现之旅
- 基于Spring|基于Spring Cache实现Caffeine+Redis二级缓存
- C语言实现数独游戏
- C/C++开源库|日志系统模块基础、C语言实现一个日志模块、zlog日志模块基础