注解类
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface AuditLog {
boolean skip() default false;
}
Aop运用
/**
* Aspect for logging execution of service and repository Spring components.
* <p>
* By default, it only runs with the "dev" profile.
*/
@Aspect
public class LoggingAspect {
private final Logger log = LoggerFactory.getLogger(LoggingAspect.class);
@Inject
private LoggingService loggingService;
private final Environment env;
@Value("${app.auditLogFlag.printGet}")
private boolean logFlag;
ObjectMapper mapper = new ObjectMapper();
public LoggingAspect(Environment env) {
this.env = env;
}
/**
* Pointcut that matches all repositories, services and Web REST endpoints.
*/
@Pointcut("within(com.qingxing.ManagerComplex.api.web.*.*Resource)")
public void loggingPointcut() {
// Method is empty as this is just a Pointcut, the implementations are in the advices.
}
/**
* Advice that logs methods throwing exceptions.
*/
@AfterThrowing(pointcut = "loggingPointcut()", throwing = "e")
public void logAfterThrowing(JoinPoint joinPoint, Throwable e) {
if (env.acceptsProfiles(Constants.SPRING_PROFILE_DEVELOPMENT)) {
log.error("Exception in {}.{}() with cause = \'{}\' and exception = \'{}\'",
joinPoint.getSignature().getDeclaringTypeName(), joinPoint.getSignature().getName(),
e.getCause() != null ? e.getCause() : "NULL", e.getMessage(), e);
} else {
log.error("Exception in {}.{}() with cause = {}",
joinPoint.getSignature().getDeclaringTypeName(), joinPoint.getSignature().getName(),
e.getCause() != null ? e.getCause() : "NULL");
}
}
/**
* Advice that logs when a method is entered and exited.
*/
@Around("loggingPointcut()")
public Object logAround(ProceedingJoinPoint joinPoint) throws Throwable {
ServletRequestAttributes attributes =
(ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = attributes.getRequest();
// 获取ip
String ip = LogUtil.getIpAddress(request);
// 获取请求头与操作路径
String path = request.getHeader("Page-Name");
if (!StringUtils.isBlank(path)) {
try {
path = URLDecoder.decode(path, "UTF-8");
} catch (UnsupportedEncodingException e1) {
e1.printStackTrace();
log.error("解码错误" + e1.getMessage());
}
}
// 获取当前用户名
String username = UserUtil.getUser().getUsername();
String area = LogUtil.sqlArea(UserUtil.getUser().getArea());
// 通过反射获取方法
String classType = joinPoint.getTarget().getClass().getName();
Class<?> clazz = Class.forName(classType);
String clazzName = clazz.getName();
Signature signature = joinPoint.getSignature();
MethodSignature methodSignature = (MethodSignature) signature;
Method targetMethod = methodSignature.getMethod();
Method realMethod = joinPoint.getTarget().getClass()
.getDeclaredMethod(joinPoint.getSignature().getName(), targetMethod.getParameterTypes());
String methodName = joinPoint.getSignature().getName(); // 获取方法名称
Object[] args = joinPoint.getArgs();
Map<String, Object> nameAndArgs = getFieldsName(this.getClass(), clazzName, methodName, args); // 获取参数名称和值
try {
if (!realMethod.isAnnotationPresent(ApiOperation.class)) {
return 1;
}
// 将map转换为json
String json = mapper.writeValueAsString(nameAndArgs);
// 获取操作内容
ApiOperation apiOperation = realMethod.getAnnotation(ApiOperation.class);
String apiOperationString = apiOperation.value();
boolean isGet = realMethod.isAnnotationPresent(GetMapping.class);
// 判断是否存在 AuditLog 注解
if (realMethod.isAnnotationPresent(AuditLog.class)) {
AuditLog auditLog = realMethod.getAnnotation(AuditLog.class);
boolean skipFlag = auditLog.skip();
joinDatabase(skipFlag, area, username, ip, path, apiOperationString, json);
} else {
// 判断是否 get 请求,以及是否强制打印
joinDatabase(!isGet || !logFlag, area, username, ip, path, apiOperationString, json);
}
} catch (Exception e) {
log.error(e.getMessage());
}
return doNext(joinPoint);
}
private Object doNext(ProceedingJoinPoint joinPoint) throws Throwable {
try {
Object result = joinPoint.proceed();
if (log.isDebugEnabled()) {
log.debug("Exit: {}.{}() with result = {}", joinPoint.getSignature().getDeclaringTypeName(),
joinPoint.getSignature().getName(), result);
}
return result;
} catch (IllegalArgumentException e) {
log.error("Illegal argument: {} in {}.{}()", Arrays.toString(joinPoint.getArgs()),
joinPoint.getSignature().getDeclaringTypeName(), joinPoint.getSignature().getName());
throw e;
}
}
/**
* 记录插入数据库
*/
private void joinDatabase(boolean flag, String area, String username, String ip, String path,
String apiOperationString, String json) {
if (flag) {
loggingService.addLogging(area, username, ip, path, apiOperationString, json);
log.debug("插入数据库成功 " + " 区域:" + area + " 用户名:" + username + " ip地址: " + ip + " 操作路径: " + path + " ,操作:"
+ apiOperationString + ", 参数为:" + json + ", 操作时间为:" + new Date());
} else {
log.debug(" 区域:" + area + " 用户名:" + username + " ip地址: " + ip + " 操作路径: " + path + " ,操作:" + apiOperationString
+ ", 参数为:" + json + ", 操作时间为:" + new Date());
}
}
//全部参数转换为map
private Map<String, Object> getFieldsName(Class cls, String clazzName, String methodName,
Object[] args) throws NotFoundException {
if (args == null || args.length <= 0) return null;
Map<String, Object> map = new HashMap<>();
ClassPool pool = ClassPool.getDefault();
// ClassClassPath classPath = new ClassClassPath(this.getClass());
ClassClassPath classPath = new ClassClassPath(cls);
pool.insertClassPath(classPath);
CtClass cc = pool.get(clazzName);
CtMethod cm = cc.getDeclaredMethod(methodName);
org.apache.ibatis.javassist.bytecode.MethodInfo methodInfo = cm.getMethodInfo();
CodeAttribute codeAttribute = methodInfo.getCodeAttribute();
LocalVariableAttribute attr =
(LocalVariableAttribute) codeAttribute.getAttribute(LocalVariableAttribute.tag);
if (attr != null) {
// String[] paramNames = new String[cm.getParameterTypes().length];
int pos = Modifier.isStatic(cm.getModifiers()) ? 0 : 1;
for (int i = 0; i < cm.getParameterTypes().length; i++) {
if (args[i] == null) {
map.put(attr.variableName(i + pos), "");
continue;
}
String argsStr = args[i].toString();
try {
if (argsStr.getBytes("UTF-8").length < 3000) {
map.put(attr.variableName(i + pos), args[i]);// paramNames即参数名
} else {
String[] msg = StringCutUtil.cutByteByUTF8(args[i].toString(), 512);
map.put(attr.variableName(i + pos), msg[0]);
log.debug("超级长的参数{},时间是{}", args[i], new Date());
}
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
}
// Map<>
return map;
}
}