diff --git a/demo-log-aop/pom.xml b/demo-log-aop/pom.xml index 7113002aa..a01664fbf 100644 --- a/demo-log-aop/pom.xml +++ b/demo-log-aop/pom.xml @@ -23,6 +23,12 @@ + + + com.google.guava + guava + + org.springframework.boot spring-boot-starter-web diff --git a/demo-log-aop/src/main/java/com/xkcoding/log/aop/aspectj/AopLog.java b/demo-log-aop/src/main/java/com/xkcoding/log/aop/aspectj/AopLog.java index 487a35a57..d39c093de 100644 --- a/demo-log-aop/src/main/java/com/xkcoding/log/aop/aspectj/AopLog.java +++ b/demo-log-aop/src/main/java/com/xkcoding/log/aop/aspectj/AopLog.java @@ -1,16 +1,28 @@ package com.xkcoding.log.aop.aspectj; +import cn.hutool.core.util.ArrayUtil; import cn.hutool.json.JSONUtil; +import com.google.common.collect.Maps; import eu.bitwalker.useragentutils.UserAgent; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.aspectj.lang.JoinPoint; import org.aspectj.lang.ProceedingJoinPoint; -import org.aspectj.lang.annotation.*; +import org.aspectj.lang.Signature; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Pointcut; +import org.aspectj.lang.reflect.MethodSignature; import org.springframework.stereotype.Component; import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.ServletRequestAttributes; import javax.servlet.http.HttpServletRequest; +import java.net.InetAddress; +import java.net.UnknownHostException; +import java.util.Collections; import java.util.Map; import java.util.Objects; @@ -20,14 +32,13 @@ *

* * @author yangkai.shen + * @author chen qi * @date Created in 2018-10-01 22:05 */ @Aspect @Component @Slf4j public class AopLog { - private static final String START_TIME = "request-start"; - /** * 切入点 */ @@ -36,27 +47,6 @@ public void log() { } - /** - * 前置操作 - * - * @param point 切入点 - */ - @Before("log()") - public void beforeLog(JoinPoint point) { - ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); - - HttpServletRequest request = Objects.requireNonNull(attributes).getRequest(); - - log.info("【请求 URL】:{}", request.getRequestURL()); - log.info("【请求 IP】:{}", request.getRemoteAddr()); - log.info("【请求类名】:{},【请求方法名】:{}", point.getSignature().getDeclaringTypeName(), point.getSignature().getName()); - - Map parameterMap = request.getParameterMap(); - log.info("【请求参数】:{},", JSONUtil.toJsonStr(parameterMap)); - Long start = System.currentTimeMillis(); - request.setAttribute(START_TIME, start); - } - /** * 环绕操作 * @@ -66,25 +56,123 @@ public void beforeLog(JoinPoint point) { */ @Around("log()") public Object aroundLog(ProceedingJoinPoint point) throws Throwable { + + // 开始打印请求日志 + ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); + HttpServletRequest request = Objects.requireNonNull(attributes).getRequest(); + + // 打印请求相关参数 + long startTime = System.currentTimeMillis(); Object result = point.proceed(); - log.info("【返回值】:{}", JSONUtil.toJsonStr(result)); + String header = request.getHeader("User-Agent"); + UserAgent userAgent = UserAgent.parseUserAgentString(header); + + final Log l = Log.builder() + .threadId(Long.toString(Thread.currentThread().getId())) + .threadName(Thread.currentThread().getName()) + .ip(getIp(request)) + .url(request.getRequestURL().toString()) + .classMethod(String.format("%s.%s", point.getSignature().getDeclaringTypeName(), + point.getSignature().getName())) + .httpMethod(request.getMethod()) + .requestParams(getNameAndValue(point)) + .result(result) + .timeCost(System.currentTimeMillis() - startTime) + .userAgent(header) + .browser(userAgent.getBrowser().toString()) + .os(userAgent.getOperatingSystem().toString()).build(); + + log.info("Request Log Info : {}", JSONUtil.toJsonStr(l)); + return result; } /** - * 后置操作 + * 获取方法参数名和参数值 + * @param joinPoint + * @return */ - @AfterReturning("log()") - public void afterReturning() { - ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); - HttpServletRequest request = Objects.requireNonNull(attributes).getRequest(); + private Map getNameAndValue(ProceedingJoinPoint joinPoint) { - Long start = (Long) request.getAttribute(START_TIME); - Long end = System.currentTimeMillis(); - log.info("【请求耗时】:{}毫秒", end - start); + final Signature signature = joinPoint.getSignature(); + MethodSignature methodSignature = (MethodSignature) signature; + final String[] names = methodSignature.getParameterNames(); + final Object[] args = joinPoint.getArgs(); - String header = request.getHeader("User-Agent"); - UserAgent userAgent = UserAgent.parseUserAgentString(header); - log.info("【浏览器类型】:{},【操作系统】:{},【原始User-Agent】:{}", userAgent.getBrowser().toString(), userAgent.getOperatingSystem().toString(), header); + if (ArrayUtil.isEmpty(names) || ArrayUtil.isEmpty(args)) { + return Collections.emptyMap(); + } + if (names.length != args.length) { + log.warn("{}方法参数名和参数值数量不一致", methodSignature.getName()); + return Collections.emptyMap(); + } + Map map = Maps.newHashMap(); + for (int i = 0; i < names.length; i++) { + map.put(names[i], args[i]); + } + return map; + } + + private static final String UNKNOWN = "unknown"; + + /** + * 获取ip地址 + */ + public static String getIp(HttpServletRequest request) { + String ip = request.getHeader("x-forwarded-for"); + if (ip == null || ip.length() == 0 || UNKNOWN.equalsIgnoreCase(ip)) { + ip = request.getHeader("Proxy-Client-IP"); + } + if (ip == null || ip.length() == 0 || UNKNOWN.equalsIgnoreCase(ip)) { + ip = request.getHeader("WL-Proxy-Client-IP"); + } + if (ip == null || ip.length() == 0 || UNKNOWN.equalsIgnoreCase(ip)) { + ip = request.getRemoteAddr(); + } + String comma = ","; + String localhost = "127.0.0.1"; + if (ip.contains(comma)) { + ip = ip.split(",")[0]; + } + if (localhost.equals(ip)) { + // 获取本机真正的ip地址 + try { + ip = InetAddress.getLocalHost().getHostAddress(); + } catch (UnknownHostException e) { + log.error(e.getMessage(), e); + } + } + return ip; + } + + @Data + @Builder + @NoArgsConstructor + @AllArgsConstructor + static class Log { + // 线程id + private String threadId; + // 线程名称 + private String threadName; + // ip + private String ip; + // url + private String url; + // http方法 GET POST PUT DELETE PATCH + private String httpMethod; + // 类方法 + private String classMethod; + // 请求参数 + private Object requestParams; + // 返回参数 + private Object result; + // 接口耗时 + private Long timeCost; + // 操作系统 + private String os; + // 浏览器 + private String browser; + // user-agent + private String userAgent; } } diff --git a/demo-log-aop/src/main/java/com/xkcoding/log/aop/controller/TestController.java b/demo-log-aop/src/main/java/com/xkcoding/log/aop/controller/TestController.java index 0eda8962c..c261d7917 100644 --- a/demo-log-aop/src/main/java/com/xkcoding/log/aop/controller/TestController.java +++ b/demo-log-aop/src/main/java/com/xkcoding/log/aop/controller/TestController.java @@ -2,17 +2,25 @@ import cn.hutool.core.lang.Dict; import cn.hutool.core.util.StrUtil; +import cn.hutool.json.JSONUtil; +import lombok.extern.slf4j.Slf4j; import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RestController; +import java.util.Map; + /** *

* 测试 Controller *

* * @author yangkai.shen + * @author chen qi * @date Created in 2018-10-01 22:10 */ +@Slf4j @RestController public class TestController { @@ -27,4 +35,16 @@ public Dict test(String who) { return Dict.create().set("who", StrUtil.isBlank(who) ? "me" : who); } + /** + * 测试post json方法 + * @param map 请求的json参数 + * @return {@link Dict} + */ + @PostMapping("/testJson") + public Dict testJson(@RequestBody Map map) { + + final String jsonStr = JSONUtil.toJsonStr(map); + log.info(jsonStr); + return Dict.create().set("json", map); + } }