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);
   }
}

  

 

 

posted @ 2024-09-23 16:59  漂渡  阅读(11)  评论(0编辑  收藏  举报