qingcheng-houduan/src/main/java/com/greenorange/promotion/aop/OperateLogAspect.java

280 lines
11 KiB
Java
Raw Normal View History

2025-05-03 02:20:50 +00:00
package com.greenorange.promotion.aop;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
2025-05-03 07:03:36 +00:00
import com.greenorange.promotion.annotation.SysLog;
2025-05-03 02:20:50 +00:00
import com.greenorange.promotion.model.entity.SysOperLog;
import com.greenorange.promotion.service.log.SysOperLogService;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.lang.reflect.Method;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
/**
* 切面处理类记录操作日志到数据库
*/
@Aspect
@Component
2025-05-03 07:03:36 +00:00
public class OperateLogAspect {
2025-05-03 02:20:50 +00:00
@Resource
private SysOperLogService sysOperLogService;
// 为了记录方法的执行时间
ThreadLocal<Long> startTime = new ThreadLocal<>();
2025-05-03 07:03:36 +00:00
@Before("@annotation(sysLog)")
public void beforeMethod(JoinPoint joinPoint, SysLog sysLog){
2025-05-03 02:20:50 +00:00
startTime.set(System.currentTimeMillis());
}
/**
* 正常返回通知拦截用户操作日志连接点正常执行完成后执行 如果连接点抛出异常则不会执行
* @param joinPoint 切入点
* @param result 返回结果
*/
2025-05-03 07:03:36 +00:00
@AfterReturning(value = "@annotation(sysLog)", returning = "result")
public void saveOperateLog(JoinPoint joinPoint, SysLog sysLog, Object result) {
2025-05-03 02:20:50 +00:00
// 获取RequestAttributes
RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
// 从获取RequestAttributes中获取HttpServletRequest的信息
HttpServletRequest request = (HttpServletRequest) requestAttributes.resolveReference(RequestAttributes.REFERENCE_REQUEST);
try {
// 从切面织入点处通过反射机制获取织入点处的方法
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
// 获取切入点所在的方法
Method method = signature.getMethod();
// 获取操作
SysOperLog sysOperLog = new SysOperLog();
2025-05-03 07:03:36 +00:00
sysOperLog.setTitle(sysLog.title());//设置模块名称
sysOperLog.setContent(sysLog.content());//设置日志内容
2025-05-03 02:20:50 +00:00
// 将入参转换成json
String params = argsArrayToString(joinPoint.getArgs());
// 获取请求的类名
String className = joinPoint.getTarget().getClass().getName();
// 获取请求的方法名
String methodName = method.getName();
methodName = className + "." + methodName + "()";
sysOperLog.setMethod(methodName); //设置请求方法
sysOperLog.setRequestMethod(request.getMethod());//设置请求方式
sysOperLog.setRequestParam(params); // 请求参数
sysOperLog.setResponseResult(JSON.toJSONString(result)); // 返回结果
// 从request中取出账号
String userAccount = (String) request.getAttribute("userAccount");
sysOperLog.setOperName(userAccount); // 获取用户名真实环境中肯定有工具类获取当前登录者的账号或ID的或者从token中解析而来
String ip = getIp(request);
sysOperLog.setIp(ip); // IP地址
String ipLocation = getIpLocation(ip);
sysOperLog.setIpLocation(ipLocation); // IP归属地真是环境中可以调用第三方API根据IP地址查询归属地
sysOperLog.setRequestUrl(request.getRequestURI()); // 请求URI
sysOperLog.setOperTime(new Date()); // 时间
sysOperLog.setStatus(0);//操作状态0正常 1异常
Long takeTime = System.currentTimeMillis() - startTime.get();//记录方法执行耗时时间(单位:毫秒)
sysOperLog.setTakeTime(takeTime);
//插入数据库
sysOperLogService.save(sysOperLog);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 设置操作异常切入点记录异常日志 扫描所有controller包下操作
* 异常返回通知用于拦截异常日志信息 连接点抛出异常后执行
*/
@AfterThrowing(pointcut = "execution(* com.greenorange.promotion.controller..*.*(..))", throwing = "e")
public void saveExceptionLog(JoinPoint joinPoint, Throwable e) {
// 获取RequestAttributes
RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
// 从获取RequestAttributes中获取HttpServletRequest的信息
HttpServletRequest request = (HttpServletRequest) requestAttributes.resolveReference(RequestAttributes.REFERENCE_REQUEST);
SysOperLog sysOperLog = new SysOperLog();
try {
// 从切面织入点处通过反射机制获取织入点处的方法
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
// 获取切入点所在的方法
Method method = signature.getMethod();
// 获取请求的类名
String className = joinPoint.getTarget().getClass().getName();
// 获取请求的方法名
String methodName = method.getName();
methodName = className + "." + methodName + "()";
// 获取操作
2025-05-03 07:03:36 +00:00
SysLog sysLog = method.getAnnotation(SysLog.class);
if (sysLog != null) {
sysOperLog.setTitle(sysLog.title());//设置模块名称
sysOperLog.setContent(sysLog.content());//设置日志内容
2025-05-03 02:20:50 +00:00
}
// 将入参转换成json
String params = argsArrayToString(joinPoint.getArgs());
sysOperLog.setMethod(methodName); //设置请求方法
sysOperLog.setRequestMethod(request.getMethod());//设置请求方式
sysOperLog.setRequestParam(params); // 请求参数
// 从request中取出账号
String userAccount = (String) request.getAttribute("userAccount");
sysOperLog.setOperName(userAccount); // 获取用户名真实环境中肯定有工具类获取当前登录者的账号或ID的或者从token中解析而来
String ip = getIp(request);
sysOperLog.setIp(ip); // IP地址
String ipLocation = getIpLocation(ip);
sysOperLog.setIpLocation(ipLocation); // IP归属地真是环境中可以调用第三方API根据IP地址查询归属地
sysOperLog.setRequestUrl(request.getRequestURI()); // 请求URI
sysOperLog.setOperTime(new Date()); // 时间
sysOperLog.setStatus(1);//操作状态0正常 1异常
sysOperLog.setErrorMsg(stackTraceToString(e.getClass().getName(), e.getMessage(), e.getStackTrace()));//记录异常信息
//插入数据库
sysOperLogService.save(sysOperLog);
} catch (Exception e2) {
e2.printStackTrace();
}
}
/**
* 转换异常信息为字符串
*/
public String stackTraceToString(String exceptionName, String exceptionMessage, StackTraceElement[] elements) {
StringBuffer strbuff = new StringBuffer();
for (StackTraceElement stet : elements) {
strbuff.append(stet + "\n");
}
String message = exceptionName + ":" + exceptionMessage + "\n\t" + strbuff.toString();
message = substring(message,0 ,2000);
return message;
}
/**
* 参数拼装
*/
private String argsArrayToString(Object[] paramsArray)
{
String params = "";
if (paramsArray != null && paramsArray.length > 0) {
for (Object o : paramsArray) {
if (o != null) {
try {
Object jsonObj = JSON.toJSON(o);
params += jsonObj.toString() + " ";
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
return params.trim();
}
//字符串截取
2025-05-03 07:03:36 +00:00
public String substring(String str, int start, int end) {
2025-05-03 02:20:50 +00:00
if (str == null) {
return null;
} else {
if (end < 0) {
end += str.length();
}
if (start < 0) {
start += str.length();
}
if (end > str.length()) {
end = str.length();
}
if (start > end) {
return "";
} else {
if (start < 0) {
start = 0;
}
if (end < 0) {
end = 0;
}
return str.substring(start, end);
}
}
}
/**
* 转换request 请求参数
* @param paramMap request获取的参数数组
*/
2025-05-03 07:03:36 +00:00
public Map<String, String> convertMap(Map<String, String[]> paramMap) {
2025-05-03 02:20:50 +00:00
Map<String, String> returnMap = new HashMap<>();
for (String key : paramMap.keySet()) {
returnMap.put(key, paramMap.get(key)[0]);
}
return returnMap;
}
//根据HttpServletRequest获取访问者的IP地址
public 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.getHeader("HTTP_CLIENT_IP");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("HTTP_X_FORWARDED_FOR");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getRemoteAddr();
}
return ip;
}
public String getIpLocation(String ip) {
try {
// 发送请求到ip-api服务
String url = "http://ip-api.com/json/" + ip + "?lang=zh-CN"; // 获取中文结果
URL obj = new URL(url);
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("GET");
BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
response.append(inputLine);
}
in.close();
// 解析JSON返回结果
JSONObject jsonResponse = JSONObject.parseObject(response.toString());
String region = jsonResponse.getString("regionName"); // 省
String city = jsonResponse.getString("city"); // 城市
String country = jsonResponse.getString("country"); // 国家
return city + ", " + region + ", " + country; // 返回位置
} catch (Exception e) {
e.printStackTrace();
}
return "未知";
}
}