后台与前台交互时,由于后台存放的原始信息可能就是一些id或code,要经过相应的转换才能很好地在前台展示。
比如: select id, user_id from user
直接返回给前台时,前台可能要根据你这个user_id作为参数,再请求一次后台,获取对应的人员信息实体,以作人员信息展示。
这样多了一次IO,同时还要根据不同的场景写很多的重复代码。比如第一次IO时就连接查出对应的返回实体,或者本来不需要后续又需要这些实体就又要补上代码。
这些重复性的工作抽像出通用的代码解决,我的做法是这样:
1、首先我的人员信息是有缓存的
2、自定义一个注解@BaseId(第一个类文件)
3、写一个AOP(第二个类文件)
这个AOP在@Controller方法返回前,校验返回的实体是固定的泛型且泛型参数对应的实体类中存在被@BaseId注解的变量,就基于这个变量生成一个人员信息实体,加进这个返回实体中返回给前台。下面且看代码:
一、注解类
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface BaseId {
}
二、AOP类
/**
* 对GetMapping接口的返回做条件性增强,
* 1、返回的类型为TableDataInfo的。里面的rows对应的实体类如果有@BaseId的,增加对应的StaffMain字段返回
*
* @author wack
* @version 1.0
* @since 2023/8/3
*/
@Aspect
@Slf4j
@Component
public class GetResponseAspect {
private static final String STAFF_MAIN = "xxx.xxx.basis.model.staff.StaffMain";
@Autowired
private IStaffService staffService;
@AfterReturning(pointcut = "@annotation(getMapping)", returning = "jsonResult")
public void beforeReturnIng(JoinPoint joinPoint, Object jsonResult, GetMapping getMapping) throws ClassNotFoundException {
if (jsonResult instanceof TableDataInfo) {
List rows = ((TableDataInfo) jsonResult).getRows();
List newRows = new ArrayList();
if (CollectionUtils.isNotEmpty(rows) && rows.get(0) != null) {
Class> returnModel = rows.get(0).getClass();
Field[] declaredFields = returnModel.getDeclaredFields();
if (Arrays.stream(declaredFields).filter(obj -> obj.getAnnotation(BaseId.class) != null).findAny().isPresent()) {
for (Object row : rows) {
// 找到注解为baseId的字段,生成一个新的StaffMain 字段来承载对应的人员信息
DynamicObject dynamicBean = new DynamicObject();
Map allPropertyType = dynamicBean.getAllPropertyType(row);
Map allPropertyValue = dynamicBean.getAllPropertyValue(row);
for (Field declaredField : declaredFields) {
if (declaredField.getAnnotation(BaseId.class) != null) {
String fieldValue = ReflectUtils.getFieldValue(row, declaredField.getName());
allPropertyType.put(declaredField.getName() + "Staff", Class.forName(STAFF_MAIN));
allPropertyValue.put(declaredField.getName() + "Staff", staffService.getStaffCacheInfo(fieldValue));
}
}
dynamicBean.addProperty(allPropertyType, allPropertyValue);
row = dynamicBean.getObject();
newRows.add(row);
}
if (CollectionUtils.isNotEmpty(newRows)) ((TableDataInfo) jsonResult).setRows(newRows);
}
}
}
}
class DynamicObject {
private Object object; //对象
private BeanMap beanMap; //对象的属性
private BeanGenerator beanGenerator; //对象生成器
private Map allProperty; //对象的<属性名, 属性名对应的类型>
/**
* 给对象属性赋值
*
* @param property
* @param value
*/
public void setValue(String property, Object value) {
beanMap.put(property, value);
}
private void setValue(Object object, Map property) {
for (String propertyName : property.keySet()) {
if (allProperty.containsKey(propertyName)) {
Object propertyValue = ReflectUtils.getFieldValue(object, propertyName);
this.setValue(propertyName, propertyValue);
}
}
}
private void setValue(Map propertyValue) {
for (Map.Entry entry : propertyValue.entrySet()) {
this.setValue(entry.getKey(), entry.getValue());
}
}
/**
* 通过属性名获取属性值
*
* @param property
* @return
*/
public Object getValue(String property) {
return beanMap.get(property);
}
/**
* 获取该bean的实体
*
* @return
*/
public Object getObject() {
return this.object;
}
private Object generateObject(Map propertyMap) {
if (null == beanGenerator) {
beanGenerator = new BeanGenerator();
}
Set keySet = propertyMap.keySet();
for (Iterator i = keySet.iterator(); i.hasNext(); ) {
String key = (String) i.next();
beanGenerator.addProperty(key, (Class) propertyMap.get(key));
}
return beanGenerator.create();
}
/**
* 添加属性名与属性值
*
* @param propertyType
* @param propertyValue
*/
public void addProperty(Map propertyType, Map propertyValue) {
if (null == propertyType) {
throw new RuntimeException("动态添加属性失败!");
}
Object oldObject = object;
object = generateObject(propertyType);
beanMap = BeanMap.create(object);
if (null != oldObject) {
setValue(oldObject, allProperty);
}
setValue(propertyValue);
if (null == allProperty) {
allProperty = propertyType;
} else {
allProperty.putAll(propertyType);
}
}
/**
* 获取对象中的所有属性名与属性值
*
* @param object
* @return
* @throws ClassNotFoundException
*/
public Map getAllPropertyType(Object object) throws ClassNotFoundException {
Map map = new HashMap<>();
Field[] fields = object.getClass().getDeclaredFields();
for (int index = 0; index < fields.length; index++) {
Field field = fields[index];
String propertyName = field.getName();
String typeName = field.getGenericType().getTypeName();
if ("long".equals(typeName)) {
typeName = "java.lang.Long";
}
if ("int".equals(typeName)) {
typeName = "java.lang.Integer";
}
if ("float".equals(typeName)) {
typeName = "java.lang.Float";
}
if ("double".equals(typeName)) {
typeName = "java.lang.Double";
}
if ("boolean".equals(typeName)) {
typeName = "java.lang.Boolean";
}
if ("char".equals(typeName)) {
typeName = "java.lang.Character";
}
if (typeName.indexOf("List") > -1) {
typeName = "java.util.List";
}
Class> propertyType = Class.forName(typeName);
map.put(propertyName, propertyType);
}
defaultEndType(map);
return map;
}
private void defaultEndType(Map map) {
map.put("createId", String.class);
map.put("modifyId", String.class);
map.put("createDate", Date.class);
map.put("modifyDate", Date.class);
}
/**
* 获取对象中的所有属性名与属性值
*
* @param object
* @return
*/
public Map getAllPropertyValue(Object object) {
Map map = new HashMap<>();
Field[] fields = object.getClass().getDeclaredFields();
for (int index = 0; index < fields.length; index++) {
Field field = fields[index];
String propertyName = field.getName();
Object propertyValue = ReflectUtils.getFieldValue(object, propertyName);
map.put(propertyName, propertyValue);
}
defaultEndValue(object,map);
return map;
}
private void defaultEndValue(Object object,Map map) {
map.put("createId", ReflectUtils.getFieldValue(object, "createId"));
map.put("modifyId", ReflectUtils.getFieldValue(object, "modifyId"));
map.put("createDate", ReflectUtils.getFieldValue(object, "createDate"));
map.put("modifyDate", ReflectUtils.getFieldValue(object, "modifyDate"));
}
}
}
在实体类中加注解