后台与前台交互时,由于后台存放的原始信息可能就是一些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";@Autowiredprivate 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<String, Class> allPropertyType = dynamicBean.getAllPropertyType(row);Map<String, Object> 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<String, Class> allProperty; //对象的<属性名, 属性名对应的类型>/*** 给对象属性赋值** @param property* @param value*/public void setValue(String property, Object value) {beanMap.put(property, value);}private void setValue(Object object, Map<String, Class> property) {for (String propertyName : property.keySet()) {if (allProperty.containsKey(propertyName)) {Object propertyValue = ReflectUtils.getFieldValue(object, propertyName);this.setValue(propertyName, propertyValue);}}}private void setValue(Map<String, Object> propertyValue) {for (Map.Entry<String, Object> 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<String, Class> getAllPropertyType(Object object) throws ClassNotFoundException {Map<String, Class> 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<String, Class> 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<String, Object> getAllPropertyValue(Object object) {Map<String, Object> 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<String, Object> 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"));}}
}
在实体类中加注解