java springboot架构 自定义注解保存项目业务日志,使用线程池保存到数据库
目录
1:pom.xml依赖
<!-- SpringBoot 拦截器 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
2:注解类样例
package com.hgfr.gfs.logconfig.controller;
import java.lang.annotation.*;
/**
* 自定义操作日志记录注解
*/
@Target({ElementType.PARAMETER, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface BusinessLog {
/**
* 操作人名称
*/
public String OperationName() default "";
}
3:枚举类
package com.hgfr.gfs.logconfig.controller;
public enum BusinessType {
ADD("新增"),
UPDATE("修改"),
OTHER("其他"),
EXPORT_IN("导入"),
EXPORT_OUT("导出"),
DELETE("删除");
private String value;
BusinessType(String s) {
this.value =s;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}
4:具体处理方法类
package com.hgfr.gfs.logconfig.controller;
import com.hgfr.gfs.log.entity.GsOperateLog;
import com.hgfr.gfs.log.service.IGsOperateLogService;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.CodeSignature;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.TimerTask;
/**
* 注解解析
*/
@Aspect
@Component
@Slf4j
public class MyLogAspect {
//注解设置到类
@Pointcut("@annotation(com.hgfr.gfs.logconfig.controller.BusinessLog)")
public void logPointCut() {
}
@Autowired
IGsOperateLogService iGsOperateLogService;
/**
* 处理完请求前执行
*
* @param joinPoint 切点
*/
@Before(value = "logPointCut()")
public void before(JoinPoint joinPoint) {
log.info("before");
}
/**
* 处理完请求后执行
*
* @param joinPoint 切点
*/
@AfterReturning(pointcut = "logPointCut()", returning = "jsonResult")
public void doAfterReturning(JoinPoint joinPoint, Object jsonResult) {
log.info("doAfterReturning");
handleLog(joinPoint, null, jsonResult);
}
/**
* 拦截异常操作
*
* @param joinPoint 切点
* @param e 异常
*/
@AfterThrowing(value = "logPointCut()", throwing = "e")
public void doAfterThrowing(JoinPoint joinPoint, Exception e) {
log.info("doAfterThrowing");
handleLog(joinPoint, e, null);
}
protected void handleLog(final JoinPoint joinPoint, final Exception e, Object jsonResult) {
try {
// 获得注解
BusinessLog controllerLog = getAnnotationLog(joinPoint);
if (Objects.isNull(controllerLog)) {
return;
}
// 数据库日志
GsOperateLog sysOperationLog = new GsOperateLog();
// 处理设置注解上的参数
getControllerMethodDescription(joinPoint, controllerLog, sysOperationLog);
// 保存数据库
// iGsOperateLogService.save(sysOperationLog);
ThreadPoolFactory.threadPoolExecutor.execute(saveTest(sysOperationLog));
} catch (Exception exp) {
// 记录本地异常日志
log.error("==前置通知异常==");
log.error("异常信息:{}", exp.getMessage());
exp.printStackTrace();
}
}
public TimerTask saveTest(GsOperateLog sysOperationLog) {
return new TimerTask() {
@Override
public void run() {
// 耗时操作
try {
// 保存数据库
iGsOperateLogService.save(sysOperationLog);
} catch (Exception e) {
log.error("SleepingTest:" + e.toString());
}
}
};
}
/**
* 获取注解中对方法的描述信息 用于Controller层注解
*
* @param businessLog 日志
* @param sysOperationLog 操作日志
* @throws Exception
*/
public void getControllerMethodDescription(JoinPoint joinPoint, BusinessLog businessLog, GsOperateLog sysOperationLog) throws Exception {
sysOperationLog.setOperateType(businessLog.OperationType().getValue());
sysOperationLog.setRequestType(businessLog.OperationDetail());
String methodName = businessLog.MethodName();
sysOperationLog.setUserName(methodName);
}
/**
* 是否存在注解,如果存在就获取
*/
private BusinessLog getAnnotationLog(JoinPoint joinPoint) throws Exception {
Signature signature = joinPoint.getSignature();
MethodSignature methodSignature = (MethodSignature) signature;
Method method = methodSignature.getMethod();
if (method != null) {
return method.getAnnotation(BusinessLog.class);
}
return null;
}
/**
* 获取参数Map集合
* @param joinPoint
* @return
*/
Map<String, Object> getNameAndValue(JoinPoint joinPoint) {
Map<String, Object> param = new HashMap<>();
Object[] paramValues = joinPoint.getArgs();
String[] paramNames = ((CodeSignature) joinPoint.getSignature()).getParameterNames();
for (int i = 0; i < paramNames.length; i++) {
param.put(paramNames[i], paramValues[i]);
}
return param;
}
/**
* 处理完请求中执行
* @param point 切点
*/
@Around("logPointCut()")
public Object around(ProceedingJoinPoint point) {
log.info("around");
//获取方法名称
Signature methodName = point.getSignature();
//日志输出
log.info(methodName + "进来了");
Long l1 = System.currentTimeMillis();
Object obj = null;
try {
obj = point.proceed(point.getArgs());
} catch (Throwable e) {
e.printStackTrace();
}
log.info(methodName + "bye" + "t耗時 " + (System.currentTimeMillis() - l1));
//记录一个耗时时间,将证明日志通知
return obj;
}
}
5:线程池类
package com.hgfr.gfs.logconfig.controller;
import lombok.extern.slf4j.Slf4j;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
@Slf4j
public class ThreadPoolFactory {
/**
* 线程池信息: 核心线程数量5,最大数量10,队列大小20,超出核心线程数量的线程存活时间:30秒, 指定拒绝策略的
*/
public static final ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(5, 10, 30, TimeUnit.SECONDS,
new LinkedBlockingQueue<Runnable>(20), new RejectedExecutionHandler() {
@Override
public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
log.error("有任务被拒绝执行了");
}
});
}
本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
THE END
二维码