spring aop给返回值添加额外字段
1、默认情况下直接修改返回值为新对象时无法达到预期结果、但可通过序列化方式达到给原对象增加字段的目的
import cn.hutool.core.util.ReflectUtil; import com.alibaba.fastjson.JSON; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.fasterxml.jackson.databind.node.ObjectNode; import lombok.extern.slf4j.Slf4j; import cn.as.foundation.web.api.BusinessCode; import cn.as.foundation.web.exception.BusinessException; import cn.as.geekbidder.core.annotation.Dict; import cn.as.geekbidder.core.util.JacksonTool; import cn.as.maple.platform.api.model.User; import cn.as.maple.platform.api.service.UserService; import cn.as.maple.process.api.model.FlowTask; import java.lang.reflect.Field; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.stream.Collectors; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.AfterReturning; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Pointcut; import org.flowable.engine.TaskService; import org.flowable.identitylink.api.IdentityLink; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.springframework.util.CollectionUtils; @Aspect @Component @Slf4j public class AddCurrentUser { @Autowired private TaskService taskService; @Autowired private UserService userService; /** * Pointcut */ @Pointcut("execution(* cn.togeek.maple.process.controller.FlowTaskController.*(..))") public void joinPoint() {} private void addOtherInfo(Object result) { if (result instanceof IPage) { List<ObjectNode> items = new ArrayList<>(); List<?> records = ((IPage<?>) result).getRecords(); if(CollectionUtils.isEmpty(records)) { return; } for (Object record : records) { ObjectNode item = doAdd(record); items.add(item); } ((IPage<ObjectNode>) result).setRecords(items); } } public ObjectNode doAdd(Object record) { //解决@JsonFormat注解解析不了的问题 String json = JacksonTool.object2String(record); ObjectNode item = JacksonTool.string2Object(json, ObjectNode.class); if(Objects.isNull(item)) { throw new BusinessException(BusinessCode.SYSTEM_ERROR.getCode(), "返回值解析失败"); } String taskId = (String) ReflectUtil.getFieldValue(record, "taskId"); List<IdentityLink> idList = this.taskService.getIdentityLinksForTask(taskId); List<User> collect = idList.stream().map(e -> { List<User> users; if(e.getUserId() != null) { users = userService.getUsersByIds(Collections.singletonList(e.getUserId())); } else { users = userService.getUserByRole(e.getGroupId()); } return users; }).flatMap(Collection::stream).collect(Collectors.toList()); String users = collect.stream().map(User::getName).collect(Collectors.joining(",")); item.put("currentUser", users); return item; } @AfterReturning(value = "joinPoint()", returning = "methodResult") public void afterRt(JoinPoint jp, Object methodResult) { addOtherInfo(methodResult); } }
2、工具类
import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.JavaType; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializationFeature; import com.fasterxml.jackson.databind.module.SimpleModule; import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer; import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer; import com.fasterxml.jackson.datatype.jsr310.deser.LocalTimeDeserializer; import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer; import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer; import com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer; import com.google.common.collect.Maps; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import java.io.IOException; import java.text.SimpleDateFormat; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.LocalTime; import java.time.format.DateTimeFormatter; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; /** * json 工具类 * @author ludangxin * @date 2021/4/1 */ @Slf4j public class JacksonTool { private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper(); private static final String STANDARD_PATTERN = "yyyy-MM-dd HH:mm:ss"; private static final String DATE_PATTERN = "yyyy-MM-dd"; private static final String TIME_PATTERN = "HH:mm:ss"; static { //设置java.util.Date时间类的序列化以及反序列化的格式 OBJECT_MAPPER.setDateFormat(new SimpleDateFormat(STANDARD_PATTERN)); // 初始化JavaTimeModule JavaTimeModule javaTimeModule = new JavaTimeModule(); //处理LocalDateTime DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(STANDARD_PATTERN); javaTimeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(dateTimeFormatter)); javaTimeModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(dateTimeFormatter)); //处理LocalDate DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern(DATE_PATTERN); javaTimeModule.addSerializer(LocalDate.class, new LocalDateSerializer(dateFormatter)); javaTimeModule.addDeserializer(LocalDate.class, new LocalDateDeserializer(dateFormatter)); //处理LocalTime DateTimeFormatter timeFormatter = DateTimeFormatter.ofPattern(TIME_PATTERN); javaTimeModule.addSerializer(LocalTime.class, new LocalTimeSerializer(timeFormatter)); javaTimeModule.addDeserializer(LocalTime.class, new LocalTimeDeserializer(timeFormatter)); //处理Long SimpleModule simpleModule = new SimpleModule(); simpleModule.addSerializer(Long.class, ToStringSerializer.instance); OBJECT_MAPPER.registerModule(simpleModule); //注册时间模块, 支持支持jsr310, 即新的时间类(java.time包下的时间类) OBJECT_MAPPER.registerModule(javaTimeModule); // 包含所有字段 OBJECT_MAPPER.setSerializationInclusion(JsonInclude.Include.ALWAYS); // 在序列化一个空对象时时不抛出异常 OBJECT_MAPPER.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS); // 忽略反序列化时在json字符串中存在, 但在java对象中不存在的属性 OBJECT_MAPPER.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES); } public static <T> String object2String(T object) { if(object == null) { return null; } try { return object instanceof String ? (String) object:OBJECT_MAPPER.writeValueAsString(object); } catch(IOException e) { log.warn("Parse object to string error", e); return null; } } public static <T> String object2StringPretty(T object) { if(object == null) { return null; } try { return object instanceof String ? (String) object:OBJECT_MAPPER.writerWithDefaultPrettyPrinter() .writeValueAsString(object); } catch(IOException e) { log.warn("Parse object to string error", e); return null; } } public static <T> T string2Object(String str, Class<T> clazz) { if(StringUtils.isEmpty(str) || clazz == null) { return null; } try { return clazz.equals(String.class) ? (T) str : OBJECT_MAPPER.readValue(str, clazz); } catch(Exception e) { log.warn("Parse String to object error!", e); return null; } } public static <T> T string2Object(String str, TypeReference<T> typeReference) { if(StringUtils.isEmpty(str) || typeReference == null) { return null; } try { return typeReference.getType().equals(String.class) ? (T)str : OBJECT_MAPPER.readValue(str, typeReference); } catch(Exception e) { log.warn("Parse String to object error!", e); return null; } } public static <T> T string2Object(String str, Class<?> collectionClass, Class<?>... elementClass) { JavaType javaType = OBJECT_MAPPER.getTypeFactory().constructParametricType(collectionClass, elementClass); try { return OBJECT_MAPPER.readValue(str, javaType); } catch(Exception e) { log.warn("Parse String to object error!", e); return null; } } /** * 把对象转换为有序map,在序列化时确保对象的顺序和属性编排时一致 */ public static Map<String, Object> objectToLinkedHashMap(Object obj) { if(null == obj) { return Maps.newHashMap(); } return objectToLikedMap(obj); } public static LinkedHashMap<String, Object> objectToLikedMap(Object data) { try { return string2Object(object2String(data), LinkedHashMap.class); } catch(Exception e) { return Maps.newLinkedHashMap(); } } /** * json字符串转成list * * @param jsonString * @param cls * @return */ public static <T> List<T> jsonToList(String jsonString, Class<T> cls) { try { return OBJECT_MAPPER.readValue(jsonString, getCollectionType(List.class, cls)); } catch (JsonProcessingException e) { String className = cls.getSimpleName(); log.error(" parse json [{}] to class [{}] error:{}", jsonString, className, e); } return null; } /** * 获取泛型的Collection Type * * @param collectionClass 泛型的Collection * @param elementClasses 实体bean * @return JavaType Java类型 */ private static JavaType getCollectionType(Class<?> collectionClass, Class<?>... elementClasses) { return OBJECT_MAPPER.getTypeFactory().constructParametricType(collectionClass, elementClasses); } }