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

285 lines
12 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package com.greenorange.promotion.aop;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.greenorange.promotion.annotation.SysLog;
import com.greenorange.promotion.model.dto.fileInfo.UploadFileRequest;
import com.greenorange.promotion.model.entity.SysOperLog;
import com.greenorange.promotion.service.log.SysOperLogService;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
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.IOException;
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
@Slf4j
public class OperateLogAspect {
@Resource
private SysOperLogService sysOperLogService;
// 为了记录方法的执行时间
ThreadLocal<Long> startTime = new ThreadLocal<>();
@Before("@annotation(sysLog)")
public void beforeMethod(JoinPoint joinPoint, SysLog sysLog){
startTime.set(System.currentTimeMillis());
}
/**
* 正常返回通知,拦截用户操作日志,连接点正常执行完成后执行, 如果连接点抛出异常,则不会执行
* @param joinPoint 切入点
* @param result 返回结果
*/
@AfterReturning(value = "@annotation(sysLog)", returning = "result")
public void saveOperateLog(JoinPoint joinPoint, SysLog sysLog, Object result) {
// 获取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();
sysOperLog.setTitle(sysLog.title());//设置模块名称
sysOperLog.setContent(sysLog.content());//设置日志内容
// 将入参转换成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 + "()";
// 获取操作
SysLog sysLog = method.getAnnotation(SysLog.class);
if (sysLog != null) {
sysOperLog.setTitle(sysLog.title());//设置模块名称
sysOperLog.setContent(sysLog.content());//设置日志内容
}
// 将入参转换成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();
log.warn("JSON参数解析出现异常");
}
}
}
}
return params.trim();
}
//字符串截取
public String substring(String str, int start, int end) {
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获取的参数数组
*/
public Map<String, String> convertMap(Map<String, String[]> paramMap) {
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 country = jsonResponse.getString("country"); // 国家
// String region = jsonResponse.getString("regionName"); // 省
// String city = jsonResponse.getString("city"); // 城市
//
// return country + "-" + region + "-" + city; // 返回位置
// } catch (Exception e) {
// e.printStackTrace();
// }
return "未知";
}
}