写一篇关于通过AOP实现记录系统日志的文章,便于日后查阅。
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
- Service注解
- @return:
- @author: cjy
- @date: 2020/9/11 16:50
*/
@Documented
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface ControllerMonitor {
String value() default “”;
}
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Maps;
import com.xlcloud.business.vip.mapper.log.SystemLogMapper;
import com.xlcloud.business.vip.model.log.SystemLog;
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.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
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.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
/**
-
系统操作日志 aop
-
@author cjy
-
@create 2020-09-11 16:52
*/
@Aspect
@Component
public class SystemLogAspect {
private SimpleDateFormat dateFormat = new SimpleDateFormat(“yyyy-mm-dd HH:mm:ss”);private final Logger logger = LoggerFactory.getLogger(this.getClass());
@Autowired
private SystemLogMapper systemLogMapper;@Pointcut("@annotation(com.xlcloud.business.vip.aop.log.ControllerMonitor)")
public void systemLog() {
}@Around(value = “systemLog()”)
public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = attributes.getRequest();
//1、记录执行时间
long startTime = System.currentTimeMillis();
Object result = joinPoint.proceed(joinPoint.getArgs());
long endTime = System.currentTimeMillis();
long totalTime = endTime - startTime;
//2、有无日志监控注解,有则输出
String methodName = joinPoint.getTarget().getClass().getName() + “.” + joinPoint.getSignature().getName() + “()”;
MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
Method targetMethod = methodSignature.getMethod();
Map<String, Object> map = toMap(request);
if (targetMethod.isAnnotationPresent(ControllerMonitor.class)) {
logger.info(“Method: {}, Start: {}, End: {}, Total: {}ms”, methodName, dateFormat.format(startTime), dateFormat.format(endTime), totalTime);
}
String operateName = map.get(“operateName”) != null ? String.valueOf(map.get(“operateName”)) : null;
//3、入系统日志表
SystemLog systemLog = new SystemLog();
systemLog.setClientIp(IpUtil.getClientIp(request));
systemLog.setReqUri(request.getRequestURI());
systemLog.setMethod(joinPoint.getTarget().getClass().getName() + “.” + joinPoint.getSignature().getName() + “()”);
// systemLog.setParam(JSONObject.toJSONString(joinPoint.getArgs()));
systemLog.setParam(JSONObject.toJSONString(map));
systemLog.setOperator(operateName);
systemLog.setStartTime(String.valueOf(startTime));
systemLog.setEndTime(String.valueOf(endTime));
systemLog.setTotalTime(totalTime == 0 ? null : String.valueOf(totalTime));
systemLog.setReturnData(JSONObject.toJSONString(result));
systemLog.setCreateUser(operateName);
systemLog.setUpdateUser(operateName);
systemLog.setCreateTime(new Date());
systemLog.setUpdateTime(new Date());
systemLog.setIsDelete(0);
systemLogMapper.insert(systemLog);
return result;
}private Map<String, Object> toMap(HttpServletRequest request) {
HashMap map = Maps.newHashMap();
Enumeration paramNames = request.getParameterNames();
while (paramNames.hasMoreElements()) {
String paramName = (String) paramNames.nextElement();
String[] paramValues = request.getParameterValues(paramName);
if (paramValues.length == 1) {
String paramValue = paramValues[0];
if (paramValue.length() != 0) {
map.put(paramName, paramValue);
}
}
}
return map;
}
}
import javax.servlet.http.HttpServletRequest;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.UnknownHostException;
import java.util.Enumeration;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
-
IP工具类
-
@author cjy
-
@create 2020-09-12 10:30
*/
public class IpUtil {/**
- 检查IP是否合法
- @param ip
- @return
*/
public static boolean ipValid(String ip) {
String regex0 = “(2[0-4]\d)” + “|(25[0-5])”;
String regex1 = “1\d{2}”;
String regex2 = “[1-9]\d”;
String regex3 = “\d”;
String regex = “(” + regex0 + “)|(” + regex1 + “)|(” + regex2 + “)|(” + regex3 + “)”;
regex = “(” + regex + “).(” + regex + “).(” + regex + “).(” + regex + “)”;
Pattern p = Pattern.compile(regex);
Matcher m = p.matcher(ip);
return m.matches();
}
/**
- 获取本地ip 适合windows与linux
- @return
*/
public static String getLocalIP() {
String localIP = “127.0.0.1”;
try {
Enumeration netInterfaces = NetworkInterface.getNetworkInterfaces();
while (netInterfaces.hasMoreElements()) {
NetworkInterface ni = (NetworkInterface) netInterfaces.nextElement();
InetAddress ip = ni.getInetAddresses().nextElement();
if (!ip.isLoopbackAddress() && ip.getHostAddress().indexOf("😊 == -1) {
localIP = ip.getHostAddress();
break;
}
}
} catch (Exception e) {
try {
localIP = InetAddress.getLocalHost().getHostAddress();
} catch (UnknownHostException e1) {
e1.printStackTrace();
}
}
return localIP;
}
/**
- 获取客户机的ip地址
- @param request
- @return
*/
public static String getClientIp(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();
}
if (ip == null || ip.length() == 0 || “unknown”.equalsIgnoreCase(ip)) {
ip = request.getHeader(“http_client_ip”);
}
if (ip == null || ip.length() == 0 || “unknown”.equalsIgnoreCase(ip)) {
ip = request.getHeader(“HTTP_X_FORWARDED_FOR”);
}
// 如果是多级代理,那么取第一个ip为客户ip
if (ip != null && ip.indexOf(",") != -1) {
ip = ip.substring(ip.lastIndexOf(",") + 1, ip.length()).trim();
}
return ip;
}
/**
- 把ip转化为整数
- @param ip
- @return
*/
public static long translateIP2Int(String ip){
String[] intArr = ip.split("\.");
int[] ipInt = new int[intArr.length];
for (int i = 0; i <intArr.length ; i++) {
ipInt[i] = new Integer(intArr[i]).intValue();
}
return ipInt[0] * 256 * 256 * 256 + + ipInt[1] * 256 * 256 + ipInt[2] * 256 + ipInt[3];
}
public static void main(String[] args) {
System.out.println(getLocalIP());
}
}
日志表结构设计
字段名 注释 类型 长度 是否必填 是否主键
id 自增ID int 11 是 是
client_ip 客户端ip varchar 100 否 否
req_uri 请求映射路径 varchar 100 否 否
method 方法名 varchar 200 否 否
param 参数 text 0 否 否
operator 操作人姓名 varchar 100 否 否
start_time 接口请求时间 varchar 50 否 否
end_time 接口返回时间 varchar 50 否 否
total_time 总消耗时间 varchar 50 否 否
return_data 接口返回数据 text 0 否 否
gmt_create 创建时间 datatime 0 是 否
gmt_create_user 创建人 varchar 50 是 否
gmt_modified 修改时间 datatime 0 是 否
gmt_modified_user 修改人 varchar 50 是 否
is_delete 是否删除(0:否 1:是) tinyint 2 是 否