未验证 提交 c6598936 编写于 作者: 不合群的混子's avatar 不合群的混子 提交者: GitHub

Merge pull request #170

[FEATURE] 完善日志切面功能
......@@ -30,6 +30,11 @@
</properties>
<dependencies>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
......@@ -86,73 +91,149 @@
* </p>
*
* @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";
/**
* 切入点
*/
@Pointcut("execution(public * com.xkcoding.log.aop.controller.*Controller.*(..))")
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<String, String[]> parameterMap = request.getParameterMap();
log.info("【请求参数】:{},", JSONUtil.toJsonStr(parameterMap));
Long start = System.currentTimeMillis();
request.setAttribute(START_TIME, start);
}
/**
* 环绕操作
*
* @param point 切入点
* @return 原方法返回值
* @throws Throwable 异常信息
*/
@Around("log()")
public Object aroundLog(ProceedingJoinPoint point) throws Throwable {
Object result = point.proceed();
log.info("【返回值】:{}", JSONUtil.toJsonStr(result));
return result;
}
/**
* 后置操作
*/
@AfterReturning("log()")
public void afterReturning() {
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = Objects.requireNonNull(attributes).getRequest();
Long start = (Long) request.getAttribute(START_TIME);
Long end = System.currentTimeMillis();
log.info("【请求耗时】:{}毫秒", end - start);
String header = request.getHeader("User-Agent");
UserAgent userAgent = UserAgent.parseUserAgentString(header);
log.info("【浏览器类型】:{},【操作系统】:{},【原始User-Agent】:{}", userAgent.getBrowser().toString(), userAgent.getOperatingSystem().toString(), header);
}
/**
* 切入点
*/
@Pointcut("execution(public * com.xkcoding.log.aop.controller.*Controller.*(..))")
public void log() {
}
/**
* 环绕操作
*
* @param point 切入点
* @return 原方法返回值
* @throws Throwable 异常信息
*/
@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();
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
*/
private Map<String, Object> getNameAndValue(ProceedingJoinPoint joinPoint) {
final Signature signature = joinPoint.getSignature();
MethodSignature methodSignature = (MethodSignature) signature;
final String[] names = methodSignature.getParameterNames();
final Object[] args = joinPoint.getArgs();
if (ArrayUtil.isEmpty(names) || ArrayUtil.isEmpty(args)) {
return Collections.emptyMap();
}
if (names.length != args.length) {
log.warn("{}方法参数名和参数值数量不一致", methodSignature.getName());
return Collections.emptyMap();
}
Map<String, Object> 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;
}
}
```
......@@ -165,22 +246,36 @@ public class AopLog {
* </p>
*
* @author yangkai.shen
* @author chen qi
* @date Created in 2018-10-01 22:10
*/
@Slf4j
@RestController
public class TestController {
/**
* 测试方法
*
* @param who 测试参数
* @return {@link Dict}
*/
@GetMapping("/test")
public Dict test(String who) {
return Dict.create().set("who", StrUtil.isBlank(who) ? "me" : who);
}
/**
* 测试方法
*
* @param who 测试参数
* @return {@link Dict}
*/
@GetMapping("/test")
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<String, Object> map) {
final String jsonStr = JSONUtil.toJsonStr(map);
log.info(jsonStr);
return Dict.create().set("json", map);
}
}
```
......@@ -23,6 +23,12 @@
</properties>
<dependencies>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
......
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 @@ import java.util.Objects;
* </p>
*
* @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 class AopLog {
}
/**
* 前置操作
*
* @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<String, String[]> parameterMap = request.getParameterMap();
log.info("【请求参数】:{},", JSONUtil.toJsonStr(parameterMap));
Long start = System.currentTimeMillis();
request.setAttribute(START_TIME, start);
}
/**
* 环绕操作
*
......@@ -66,25 +56,123 @@ public class AopLog {
*/
@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<String, Object> 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<String, Object> 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;
}
}
......@@ -2,17 +2,25 @@ package com.xkcoding.log.aop.controller;
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;
/**
* <p>
* 测试 Controller
* </p>
*
* @author yangkai.shen
* @author chen qi
* @date Created in 2018-10-01 22:10
*/
@Slf4j
@RestController
public class TestController {
......@@ -27,4 +35,16 @@ public class TestController {
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<String, Object> map) {
final String jsonStr = JSONUtil.toJsonStr(map);
log.info(jsonStr);
return Dict.create().set("json", map);
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册