希望的效果为
需求
用户点击了某个界面,请求了后台某个接口。接口请求到后台后,记录请求的数据到数据库中。
实现方式
1、自定义一个注解,被加注解的方法,请求的数据被保存下来
2、定义一个aop 去拦截被注解的方法
3、写一个线程池、执行拦截后的逻辑。也就是保存到数据库中
效果图
查看到刚刚请求用户列表界面的执行情况
实现步骤
1、自定义注解
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface SLog {
String value() default "";
}
定义一个aop拦截注解
@Aspect
@Component
public class SLogAspect {
/**
* 保存日志到数据库的线程池
*/
ThreadFactory threadFactory = new ThreadFactoryBuilder().setNameFormat("SLogAspect-Thread-%d").build();
ExecutorService executor = new ThreadPoolExecutor(5,200,0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>(1024),
threadFactory,
new ThreadPoolExecutor.AbortPolicy());
@Pointcut("@annotation(com.slife.annotation.SLog)")
public void logPointCut() {
}
@Around("logPointCut()")
public Object around(ProceedingJoinPoint point) throws Throwable {
long beginTime = System.currentTimeMillis();
// 执行方法
Object result = point.proceed();
// 执行时长(毫秒)
long time = System.currentTimeMillis() - beginTime;
// 获取request
HttpServletRequest request = ServletUtils.getHttpServletRequest();
//获取请求的ip
String ip = IPUtils.getIpAddr(request);
SaveLogTask saveLogTask = new SaveLogTask(point, time, ip);
//保存日志到数据库
executor.execute(saveLogTask);
return result;
}
}
线程池执行保存数据到数据库
/**
*
* @author chen
* @date 2017/9/19
* <p>
* Email 122741482@qq.com
* <p>
* Describe:
*/
public class SaveLogTask implements Runnable {
private SlifeLogDao slifeLogDao = ApplicationContextRegister.getBean(SlifeLogDao.class);
private ProceedingJoinPoint joinPoint;
private long time;
private String ip;
public SaveLogTask(ProceedingJoinPoint point, long time, String ip) {
this.joinPoint = point;
this.time = time;
this.ip = ip;
}
@Override
public void run() {
saveLog(joinPoint, time, ip);
}
/**
* 保存日志 到数据库
*
* @param joinPoint
* @param time
*/
private void saveLog(ProceedingJoinPoint joinPoint, long time, String ip) {
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
Method method = signature.getMethod();
SlifeLog slifeLog = new SlifeLog();
SLog sLog = method.getAnnotation(SLog.class);
if (slifeLog != null) {
// 注解上的描述
slifeLog.setMsg(sLog.value());
}
// 请求的方法名
String className = joinPoint.getTarget().getClass().getName();
String methodName = signature.getName();
slifeLog.setSrc(className + "." + methodName + "()");
// 请求的参数
Object[] args = joinPoint.getArgs();
try {
String params = JSON.toJSONString(args[0]);
slifeLog.setParams(params);
} catch (Exception e) {
}
// 设置IP地址
slifeLog.setIp(ip);
// 用户名
ShiroUser currUser = SlifeSysUser.ShiroUser();
if (null == currUser) {
if (null != slifeLog.getParams()) {
slifeLog.setName(slifeLog.getParams());
slifeLog.setLoginName(slifeLog.getParams());
} else {
slifeLog.setName("获取用户信息为空");
slifeLog.setLoginName("获取用户信息为空");
slifeLog.setCreateId(-1L);
}
} else {
slifeLog.setName(currUser.getName());
slifeLog.setLoginName(currUser.getUsername());
}
slifeLog.setUseTime(time);
// 保存系统日志
slifeLogDao.insert(slifeLog);
}
}
给需要的方法加注解
@SLog("获取用户列表数据")
@ApiOperation(value = "获取用户列表数据", notes = "获取用户列表:使用约定的DataTable")
@PostMapping(value = "/list")
@ResponseBody
public DataTable<SysUser> list(@RequestBody DataTable dt, ServletRequest request) {
return sysUserService.pageSearch(dt);
}
@SLog("获取用户列表数据")
简单的一个 记录请求的日志 实现。
说明
这里把保存到数据库的逻辑写到了一个线程池中,主要是不希望记录日志的逻辑影响了用户请求数据接口的逻辑,和性能。
点击获取阿里云优惠券
我的官网
我的官网http://guan2ye.com
我的CSDN地址http://blog.csdn.net/chenjianandiyi
我的简书地址http://www.jianshu.com/u/9b5d1921ce34
我的githubhttps://github.com/javanan
我的码云地址https://gitee.com/jamen/
阿里云优惠券https://promotion.aliyun.com/ntms/act/ambassador/sharetouser.html?userCode=vf2b5zld&utm_source=vf2b5zld