Ver código fonte

ControllerAspect format logger...

deason 4 anos atrás
pai
commit
9e4a404132

+ 257 - 0
examcloud-commons/src/main/java/cn/com/qmth/examcloud/commons/util/JsonMapper.java

@@ -0,0 +1,257 @@
+package cn.com.qmth.examcloud.commons.util;
+
+import com.fasterxml.jackson.annotation.JsonInclude.Include;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.*;
+import com.fasterxml.jackson.databind.util.JSONPObject;
+import org.apache.commons.lang3.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.IOException;
+import java.text.SimpleDateFormat;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 简单封装Jackson,实现JSON 与 Java Object互相转换的Mapper
+ * 封装不同的输出风格, 使用不同的builder函数创建实例
+ */
+@SuppressWarnings("unchecked")
+public class JsonMapper {
+
+    private static Logger log = LoggerFactory.getLogger(JsonMapper.class);
+
+    private ObjectMapper mapper;
+
+    /**
+     * 默认构造JsonMapper
+     */
+    public JsonMapper() {
+        this(null);
+    }
+
+    /**
+     * 创建只输出初始值被改变的属性到Json字符串的Mapper, 最节约的存储方式
+     */
+    public static JsonMapper nonDefaultMapper() {
+        return new JsonMapper(Include.NON_DEFAULT);
+    }
+
+    /**
+     * 创建只输出非Null且非Empty的属性到Json字符串的Mapper
+     */
+    public static JsonMapper nonEmptyMapper() {
+        return new JsonMapper(Include.NON_EMPTY);
+    }
+
+    /**
+     * 创建只输出非Null的属性到Json字符串的Mapper
+     */
+    public static JsonMapper nonNullMapper() {
+        return new JsonMapper(Include.NON_NULL);
+    }
+
+    /**
+     * 构造JsonMapper
+     */
+    public JsonMapper(Include include) {
+        mapper = new ObjectMapper();
+
+        //设置输出时包含属性的风格
+        if (include != null) {
+            mapper.setSerializationInclusion(include);
+        }
+
+        //设置输入时忽略在JSON字符串中存在但Java对象实际没有的属性
+        mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
+        //忽略无法转换的对象
+        mapper.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS);
+
+        //设置默认日期格式
+        mapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
+    }
+
+    /**
+     * Object可以是POJO,也可以是Collection或数组
+     * 如果对象为Null, 返回"null"
+     * 如果集合为空集合, 返回"[]"
+     */
+    public String toJson(Object object) {
+        if (object == null) {
+            return null;
+        }
+
+        try {
+            return mapper.writeValueAsString(object);
+        } catch (IOException e) {
+            log.error("toJson error!" + e.getMessage(), e);
+            return null;
+        }
+    }
+
+    /**
+     * 反序列化POJO或简单Collection如List<String>
+     * 如果JSON字符串为Null或"null"字符串, 返回Null
+     * 如果JSON字符串为"[]", 返回空集合
+     * 如需反序列化复杂Collection如List<MyBean>, 请使用parseJson(String, JavaType)
+     */
+    public <T> T parseJson(String jsonStr, Class<T> clazz) {
+        if (StringUtils.isEmpty(jsonStr)) {
+            return null;
+        }
+
+        try {
+            return mapper.readValue(jsonStr, clazz);
+        } catch (IOException e) {
+            log.error("parseJson error!" + e.getMessage(), e);
+            return null;
+        }
+    }
+
+    /**
+     * 反序列化复杂Collection如List<Bean>, 先使用createCollectionType()或constructMapType()构造类型, 然后调用本函数
+     */
+    public <T> T parseJson(String jsonStr, JavaType javaType) {
+        if (StringUtils.isEmpty(jsonStr)) {
+            return null;
+        }
+
+        try {
+            return (T) mapper.readValue(jsonStr, javaType);
+        } catch (IOException e) {
+            log.error("parseJson error!" + e.getMessage(), e);
+            return null;
+        }
+    }
+
+    /**
+     * 反序列化复杂的对象,如Page<Bean>
+     */
+    public <T> T parseJson(String jsonStr, TypeReference javaType) {
+        if (StringUtils.isEmpty(jsonStr)) {
+            return null;
+        }
+
+        try {
+            return (T) mapper.readValue(jsonStr, javaType);
+        } catch (IOException e) {
+            log.error("parseJson error!" + e.getMessage(), e);
+            return null;
+        }
+    }
+
+    /**
+     * Json to List
+     */
+    public <T> List<T> toList(String jsonStr, Class<T> bean) {
+        if (StringUtils.isEmpty(jsonStr)) {
+            return null;
+        }
+
+        try {
+            JavaType javaType = constructCollectionType(List.class, bean);
+            return mapper.readValue(jsonStr, javaType);
+        } catch (IOException e) {
+            log.error("parseJson error!" + e.getMessage(), e);
+            return null;
+        }
+    }
+
+    /**
+     * Json to HashMap
+     */
+    public <T> Map<String, T> toHashMap(String jsonStr, Class<T> bean) {
+        if (StringUtils.isEmpty(jsonStr)) {
+            return null;
+        }
+
+        try {
+            JavaType javaType = constructMapType(HashMap.class, String.class, bean);
+            return mapper.readValue(jsonStr, javaType);
+        } catch (IOException e) {
+            log.error("parseJson error!" + e.getMessage(), e);
+            return null;
+        }
+    }
+
+    /**
+     * 构造Collection类型
+     */
+    public JavaType constructCollectionType(Class<? extends Collection> collectionClass, Class<?> elementClass) {
+        return mapper.getTypeFactory().constructCollectionType(collectionClass, elementClass);
+    }
+
+    /**
+     * 构造Map类型
+     */
+    public JavaType constructMapType(Class<? extends Map> mapClass, Class<?> keyClass, Class<?> valueClass) {
+        return mapper.getTypeFactory().constructMapType(mapClass, keyClass, valueClass);
+    }
+
+    /**
+     * 当JSON里只含有Bean的部分属性時,更新一個已存在Bean,只覆盖該部分的属性
+     */
+    public void update(String jsonStr, Object object) {
+        if (jsonStr == null) {
+            return;
+        }
+
+        try {
+            mapper.readerForUpdating(object).readValue(jsonStr);
+        } catch (JsonProcessingException e) {
+            log.error("updateJson error!" + e.getMessage(), e);
+        } catch (IOException e) {
+            log.error("updateJson error!" + e.getMessage(), e);
+        }
+    }
+
+    /**
+     * 輸出JSONP格式数据
+     */
+    public String toJsonP(String functionName, Object object) {
+        if (object == null) {
+            return null;
+        }
+
+        return toJson(new JSONPObject(functionName, object));
+    }
+
+    /**
+     * 設定是否使用Enum的toString函数來读写Enum
+     * 为False時使用Enum的name()函数來读写Enum, 默认为False
+     * 注意本函数一定要在Mapper創建後, 所有的读写動作之前調用
+     */
+    public void enableEnumUseToString() {
+        mapper.enable(SerializationFeature.WRITE_ENUMS_USING_TO_STRING);
+        mapper.enable(DeserializationFeature.READ_ENUMS_USING_TO_STRING);
+    }
+
+    /**
+     * 取出Mapper做进一步的设置或使用其他序列化API
+     */
+    public ObjectMapper getMapper() {
+        return mapper;
+    }
+
+    /***
+     * 把Json字符串转换成Node对象
+     */
+    public JsonNode getNode(String jsonStr) {
+        if (jsonStr == null) {
+            return null;
+        }
+
+        try {
+            //mapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_CONTROL_CHARS, true);
+            return mapper.readTree(jsonStr);
+        } catch (IOException e) {
+            log.error(e.getMessage(), e);
+            return null;
+        }
+    }
+
+}

+ 239 - 212
examcloud-web/src/main/java/cn/com/qmth/examcloud/web/support/ControllerAspect.java

@@ -1,31 +1,29 @@
 package cn.com.qmth.examcloud.web.support;
 
-import java.util.Collection;
-import java.util.Map;
-
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import org.aspectj.lang.ProceedingJoinPoint;
-import org.aspectj.lang.annotation.Around;
-import org.aspectj.lang.annotation.Aspect;
-import org.aspectj.lang.annotation.Pointcut;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.http.HttpStatus;
-import org.springframework.http.ResponseEntity;
-import org.springframework.stereotype.Component;
-
 import cn.com.qmth.examcloud.api.commons.exchange.BaseResponse;
 import cn.com.qmth.examcloud.api.commons.exchange.JsonSerializable;
 import cn.com.qmth.examcloud.commons.logging.ExamCloudLog;
 import cn.com.qmth.examcloud.commons.logging.ExamCloudLogFactory;
-import cn.com.qmth.examcloud.commons.util.JsonUtil;
+import cn.com.qmth.examcloud.commons.util.JsonMapper;
 import cn.com.qmth.examcloud.commons.util.ObjectUtil;
-import cn.com.qmth.examcloud.commons.util.StringUtil;
 import cn.com.qmth.examcloud.commons.util.ThreadLocalUtil;
 import cn.com.qmth.examcloud.web.config.LogProperties;
 import cn.com.qmth.examcloud.web.enums.HttpServletRequestAttribute;
 import cn.com.qmth.examcloud.web.redis.RedisClient;
+import org.apache.commons.lang3.ArrayUtils;
+import org.aspectj.lang.ProceedingJoinPoint;
+import org.aspectj.lang.annotation.Around;
+import org.aspectj.lang.annotation.Aspect;
+import org.aspectj.lang.annotation.Pointcut;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.ResponseEntity;
+import org.springframework.stereotype.Component;
+import org.springframework.web.multipart.MultipartFile;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.util.Collection;
+import java.util.Map;
 
 /**
  * spring mvc controller aspect.
@@ -38,198 +36,227 @@ import cn.com.qmth.examcloud.web.redis.RedisClient;
 @Aspect
 public class ControllerAspect {
 
-	private static final ExamCloudLog DEBUG_LOG = ExamCloudLogFactory
-			.getLog(ControllerAspect.class);
-
-	private static final ExamCloudLog INTERFACE_LOG = ExamCloudLogFactory
-			.getLog("INTERFACE_LOGGER");
-
-	@Autowired(required = false)
-	HttpMethodProcessor httpMethodProcessor;
-
-	@Autowired
-	LogProperties logProperties;
-
-	@Autowired(required = false)
-	RedisClient redisClient;
-
-	/**
-	 * 构造函数
-	 *
-	 */
-	public ControllerAspect() {
-		super();
-		DEBUG_LOG.info("Aspect class [ControllerAspect]  is active!");
-	}
-
-	private static String[] excludeFields = new String[]{"password", ".*Password"};
-
-	/**
-	 * handlerMethods
-	 *
-	 * @author WANGWEI
-	 */
-	@Pointcut("@annotation(org.springframework.web.bind.annotation.RequestMapping) "
-			+ "|| @annotation(org.springframework.web.bind.annotation.GetMapping) "
-			+ "|| @annotation(org.springframework.web.bind.annotation.PostMapping)"
-			+ "|| @annotation(org.springframework.web.bind.annotation.DeleteMapping)"
-			+ "|| @annotation(org.springframework.web.bind.annotation.PutMapping)")
-	public void handlerMethods() {
-
-	}
-
-	/**
-	 * 接口处理
-	 *
-	 * @author WANG WEI
-	 *
-	 * @param joinPoint
-	 * @return
-	 */
-	@Around("handlerMethods()")
-	public Object doAroundWebRequests(ProceedingJoinPoint joinPoint) {
-		long startTime = System.currentTimeMillis();
-
-		// 获取request对象
-		HttpServletRequest request = ServletUtil.getRequest();
-
-		String path = request.getServletPath();
-		String method = request.getMethod();
-
-		if (INTERFACE_LOG.isInfoEnabled()) {
-			INTERFACE_LOG
-					.info(StringUtil.join("[HTTP-IN]. path=\"", path, "\", method=[", method, "]"));
-		}
-
-		Object[] args = joinPoint.getArgs();
-
-		if (INTERFACE_LOG.isInfoEnabled()) {
-			if (null != args) {
-				if (1 == args.length && args[0] instanceof JsonSerializable) {
-					INTERFACE_LOG
-							.info("[HTTP-REQ]. request=" + JsonUtil.toJson(args[0], excludeFields));
-				} else if (1 <= args.length) {
-					StringBuilder sb = new StringBuilder();
-					sb.append("[HTTP-REQ]. args: ");
-					for (int i = 0; i < args.length; i++) {
-						Object curArg = args[i];
-						sb.append("args[").append(i).append("]=");
-						if (null == curArg) {
-							sb.append("null");
-						} else if (curArg instanceof JsonSerializable) {
-							sb.append(JsonUtil.toJson(curArg));
-						} else if (ObjectUtil.isBaseDataType(curArg.getClass())) {
-							sb.append(curArg);
-						}
-						sb.append("; ");
-					}
-
-					INTERFACE_LOG.info(sb.toString());
-				}
-			}
-		}
-
-		Object ret = null;
-		try {
-			if (null != httpMethodProcessor) {
-				httpMethodProcessor.beforeMethod(request, args);
-			}
-			// 执行
-			ret = joinPoint.proceed();
-
-			request.setAttribute(HttpServletRequestAttribute.$_EXCEPTION_HAPPENED.name(),
-					new Boolean(false));
-
-		} catch (Throwable e) {
-
-			request.setAttribute(HttpServletRequestAttribute.$_EXCEPTION_HAPPENED.name(),
-					new Boolean(true));
-
-			if (null != httpMethodProcessor) {
-				try {
-					httpMethodProcessor.onException(request, args, e);
-				} catch (Exception ex) {
-					INTERFACE_LOG.error("[AFTER-METHOD].onException()", ex);
-				}
-			}
-			INTERFACE_LOG.error(StringUtil.join("[HTTP-FAIL]. path=\"", path, "\", method=[",
-					method, "] ; cost ", System.currentTimeMillis() - startTime, " ms."));
-			throw new RuntimeException(e);
-		}
-
-		if (null != httpMethodProcessor) {
-			try {
-				httpMethodProcessor.onSuccess(request, args, ret);
-			} catch (Exception ex) {
-				INTERFACE_LOG.error("[AFTER-METHOD].onSuccess()", ex);
-			}
-		}
-
-		if (null != ret && BaseResponse.class.isAssignableFrom(ret.getClass())) {
-			BaseResponse baseResponse = (BaseResponse) ret;
-			baseResponse.setCost(System.currentTimeMillis() - startTime);
-		}
-
-		if (INTERFACE_LOG.isDebugEnabled() && logProperties.isNormalResponseLogEnable()) {
-			boolean jsonSerializable = false;
-			if (null == ret) {
-				INTERFACE_LOG.debug("[HTTP-RESP]. status=" + HttpStatus.OK);
-				INTERFACE_LOG.debug("[HTTP-RESP]. response=void");
-			} else if (ret instanceof ResponseEntity) {
-				ResponseEntity<?> re = (ResponseEntity<?>) ret;
-				Object body = re.getBody();
-				if (null != body) {
-					if (body instanceof JsonSerializable) {
-						jsonSerializable = true;
-					} else if (body instanceof Collection) {
-						jsonSerializable = true;
-					} else if (body instanceof Map) {
-						jsonSerializable = true;
-					} else if (body instanceof String) {
-						jsonSerializable = true;
-					}
-					INTERFACE_LOG.debug("[HTTP-RESP]. status=" + re.getStatusCodeValue());
-					if (jsonSerializable) {
-						String json = JsonUtil.toJson(body);
-						int responseJsonMaxSize = logProperties.getResponseLogJsonMaxSize();
-						if (json.length() > responseJsonMaxSize) {
-							INTERFACE_LOG.debug("[HTTP-RESP]. response= too large");
-						} else {
-							INTERFACE_LOG.debug("[HTTP-RESP]. response=" + json);
-						}
-					}
-				}
-			} else {
-				if (ret instanceof JsonSerializable) {
-					jsonSerializable = true;
-				} else if (ret instanceof Collection) {
-					jsonSerializable = true;
-				} else if (ret instanceof Map) {
-					jsonSerializable = true;
-				} else if (ret instanceof String) {
-					jsonSerializable = true;
-				}
-				INTERFACE_LOG.info("[HTTP-RESP]. status=" + HttpStatus.OK.value());
-				if (jsonSerializable) {
-					String json = JsonUtil.toJson(ret);
-					int responseJsonMaxSize = logProperties.getResponseLogJsonMaxSize();
-					if (json.length() > responseJsonMaxSize) {
-						INTERFACE_LOG.debug("[HTTP-RESP]. response= too large");
-					} else {
-						INTERFACE_LOG.debug("[HTTP-RESP]. response=" + json);
-					}
-				}
-			}
-		}
-
-		HttpServletResponse response = ServletUtil.getResponse();
-		response.setHeader("Trace-Id", ThreadLocalUtil.getTraceId());
-		response.setHeader("cost", String.valueOf(System.currentTimeMillis() - startTime));
-
-		INTERFACE_LOG.info(StringUtil.join("[HTTP-OK]. path=\"", path, "\", method=[", method,
-				"] ; cost ", System.currentTimeMillis() - startTime, " ms."));
-
-		return ret;
-	}
-
-}
+    private static final ExamCloudLog DEBUG_LOG = ExamCloudLogFactory.getLog(ControllerAspect.class);
+
+    private static final ExamCloudLog INTERFACE_LOG = ExamCloudLogFactory.getLog("INTERFACE_LOGGER");
+
+    @Autowired(required = false)
+    HttpMethodProcessor httpMethodProcessor;
+
+    @Autowired
+    LogProperties logProperties;
+
+    @Autowired(required = false)
+    RedisClient redisClient;
+
+    /**
+     * 构造函数
+     */
+    public ControllerAspect() {
+        super();
+        DEBUG_LOG.info("ControllerAspect init...");
+    }
+
+    private static String[] excludeFields = new String[]{"password", ".*Password"};
+
+    /**
+     * handlerMethods
+     *
+     * @author WANGWEI
+     */
+    @Pointcut("@annotation(org.springframework.web.bind.annotation.RequestMapping) "
+            + "|| @annotation(org.springframework.web.bind.annotation.GetMapping) "
+            + "|| @annotation(org.springframework.web.bind.annotation.PostMapping)"
+            + "|| @annotation(org.springframework.web.bind.annotation.DeleteMapping)"
+            + "|| @annotation(org.springframework.web.bind.annotation.PutMapping)")
+    public void handlerMethods() {
+
+    }
+
+    /**
+     * 接口处理
+     *
+     * @param joinPoint
+     * @return
+     * @author WANG WEI
+     */
+    @Around("handlerMethods()")
+    public Object doAroundWebRequests(ProceedingJoinPoint joinPoint) {
+        // 获取request对象
+        HttpServletRequest request = ServletUtil.getRequest();
+        String path = request.getServletPath();
+        try {
+            if ("/".equals(request.getServletPath())) {
+                return joinPoint.proceed();
+            }
+        } catch (Throwable e) {
+            INTERFACE_LOG.error(e.getMessage());
+            throw new RuntimeException(e);
+        }
+
+        long startTime = System.currentTimeMillis();
+        String method = request.getMethod();
+        Object[] args = joinPoint.getArgs();
+
+        if (INTERFACE_LOG.isInfoEnabled()) {
+            StringBuilder params = new StringBuilder();
+
+            if (args != null) {
+                if (args.length == 0) {
+                    Map<String, String[]> paramMaps = request.getParameterMap();
+                    for (Map.Entry<String, String[]> entry : paramMaps.entrySet()) {
+                        String name = entry.getKey();
+                        String[] values = entry.getValue();
+                        params.append("&").append(name).append("=");
+                        if (ArrayUtils.isNotEmpty(values)) {
+                            if (name.toLowerCase().indexOf(excludeFields[0]) >= 0) {
+                                params.append("***");
+                            } else {
+                                params.append(values[0]);
+                            }
+                        }
+                    }
+                } else {
+                    for (int i = 0; i < args.length; i++) {
+                        Object curArg = args[i];
+                        if (curArg == null) {
+                            params.append("null");
+                        } else if (ObjectUtil.isBaseDataType(curArg.getClass())) {
+                            params.append(curArg);
+                        } else {
+                            String content = this.parseContent(curArg);
+                            if (content == null) {
+                                content = "...";
+                            } else {
+                                if (content.length() > logProperties.getResponseLogJsonMaxSize()) {
+                                    content = "content too large...";
+                                }
+                            }
+                            params.append(content);
+                        }
+                        if (i < args.length - 1) {
+                            params.append(" | ");
+                        }
+                    }
+                }
+            }
+
+            INTERFACE_LOG.info(String.format("[ControllerAspect][request][%s] - %s, params = %s", method, path, params.toString()));
+        }
+
+        Object ret;
+        try {
+            if (null != httpMethodProcessor) {
+                httpMethodProcessor.beforeMethod(request, args);
+            }
+
+            // 执行
+            ret = joinPoint.proceed();
+
+            request.setAttribute(HttpServletRequestAttribute.$_EXCEPTION_HAPPENED.name(), new Boolean(false));
+        } catch (Throwable e) {
+            request.setAttribute(HttpServletRequestAttribute.$_EXCEPTION_HAPPENED.name(), new Boolean(true));
+
+            if (null != httpMethodProcessor) {
+                try {
+                    httpMethodProcessor.onException(request, args, e);
+                } catch (Exception ex) {
+                    INTERFACE_LOG.error("[ControllerAspect] processor1 - " + ex.getMessage(), ex);
+                }
+            }
+
+            INTERFACE_LOG.error(String.format("[ControllerAspect][execute fail][%s] - %s, cost %sms, err is %s"
+                    , method, path, System.currentTimeMillis() - startTime, e.getMessage()));
+            throw new RuntimeException(e);
+        }
+
+        if (null != httpMethodProcessor) {
+            try {
+                httpMethodProcessor.onSuccess(request, args, ret);
+            } catch (Exception ex) {
+                INTERFACE_LOG.error("[ControllerAspect] processor2 - " + ex.getMessage(), ex);
+            }
+        }
+
+        if (null != ret && BaseResponse.class.isAssignableFrom(ret.getClass())) {
+            BaseResponse baseResponse = (BaseResponse) ret;
+            baseResponse.setCost(System.currentTimeMillis() - startTime);
+        }
+
+        if (INTERFACE_LOG.isDebugEnabled() && logProperties.isNormalResponseLogEnable()) {
+            if (ret == null) {
+                INTERFACE_LOG.debug("[ControllerAspect] status = 200, responseMsg = void");
+            } else if (ret instanceof ResponseEntity) {
+                ResponseEntity<?> re = (ResponseEntity<?>) ret;
+                Object body = re.getBody();
+
+                String content = null;
+                if (body != null) {
+                    boolean jsonSerializable = false;
+                    if (body instanceof Collection) {
+                        jsonSerializable = true;
+                    } else if (body instanceof Map) {
+                        jsonSerializable = true;
+                    } else if (body instanceof String) {
+                        jsonSerializable = true;
+                    } else if (body instanceof JsonSerializable) {
+                        jsonSerializable = true;
+                    }
+                    if (jsonSerializable) {
+                        content = this.parseContent(body);
+                    }
+                }
+
+                if (content == null) {
+                    content = "...";
+                } else {
+                    if (content.length() > logProperties.getResponseLogJsonMaxSize()) {
+                        content = "content too large...";
+                    }
+                }
+
+                INTERFACE_LOG.debug(String.format("[ControllerAspect] status = %s, responseMsg = %s",
+                        re.getStatusCodeValue(), content));
+            } else {
+                String content;
+                if (ObjectUtil.isBaseDataType(ret.getClass())) {
+                    content = ret.toString();
+                } else {
+                    content = this.parseContent(ret);
+                }
+
+                if (content == null) {
+                    content = "...";
+                } else {
+                    if (content.length() > logProperties.getResponseLogJsonMaxSize()) {
+                        content = "content too large...";
+                    }
+                }
+
+                INTERFACE_LOG.debug(String.format("[ControllerAspect] status = 200, responseMsg = %s", content));
+            }
+        }
+
+        HttpServletResponse response = ServletUtil.getResponse();
+        response.setHeader("Trace-Id", ThreadLocalUtil.getTraceId());
+        response.setHeader("cost", String.valueOf(System.currentTimeMillis() - startTime));
+
+        INTERFACE_LOG.info(String.format("[ControllerAspect][response][%s] - %s, cost %sms", method, path, System.currentTimeMillis() - startTime));
+        return ret;
+    }
+
+    private String parseContent(Object obj) {
+        try {
+            if (obj instanceof MultipartFile) {
+                return ((MultipartFile) obj).getOriginalFilename();
+            }
+
+            return new JsonMapper().toJson(obj);
+        } catch (Exception e) {
+            INTERFACE_LOG.warn("[ControllerAspect] parseContent " + e.getMessage());
+        }
+
+        return null;
+    }
+
+}