希望的效果為
需求
用戶點(diǎn)擊了某個(gè)界面,請求了后臺(tái)某個(gè)接口。接口請求到后臺(tái)后,記錄請求的數(shù)據(jù)到數(shù)據(jù)庫中。
實(shí)現(xiàn)方式
1、自定義一個(gè)注解,被加注解的方法,請求的數(shù)據(jù)被保存下來
2、定義一個(gè)aop 去攔截被注解的方法
3、寫一個(gè)線程池、執(zhí)行攔截后的邏輯。也就是保存到數(shù)據(jù)庫中
效果圖
這里寫圖片描述
查看到剛剛請求用戶列表界面的執(zhí)行情況
這里寫圖片描述
實(shí)現(xiàn)步驟
1、自定義注解
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface SLog {
String value() default "";
}
定義一個(gè)aop攔截注解
@Aspect
@Component
public class SLogAspect {
/**
* 保存日志到數(shù)據(jù)庫的線程池
*/
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();
// 執(zhí)行方法
Object result = point.proceed();
// 執(zhí)行時(shí)長(毫秒)
long time = System.currentTimeMillis() - beginTime;
// 獲取request
HttpServletRequest request = ServletUtils.getHttpServletRequest();
//獲取請求的ip
String ip = IPUtils.getIpAddr(request);
SaveLogTask saveLogTask = new SaveLogTask(point, time, ip);
//保存日志到數(shù)據(jù)庫
executor.execute(saveLogTask);
return result;
}
}
線程池執(zhí)行保存數(shù)據(jù)到數(shù)據(jù)庫
/**
*
* @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);
}
/**
* 保存日志 到數(shù)據(jù)庫
*
* @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 + "()");
// 請求的參數(shù)
Object[] args = joinPoint.getArgs();
try {
String params = JSON.toJSONString(args[0]);
slifeLog.setParams(params);
} catch (Exception e) {
}
// 設(shè)置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);
// 保存系統(tǒng)日志
slifeLogDao.insert(slifeLog);
}
}
給需要的方法加注解
@SLog("獲取用戶列表數(shù)據(jù)")
@ApiOperation(value = "獲取用戶列表數(shù)據(jù)", notes = "獲取用戶列表:使用約定的DataTable")
@PostMapping(value = "/list")
@ResponseBody
public DataTable<SysUser> list(@RequestBody DataTable dt, ServletRequest request) {
return sysUserService.pageSearch(dt);
}
@SLog("獲取用戶列表數(shù)據(jù)")
簡單的一個(gè) 記錄請求的日志 實(shí)現(xiàn)。
說明
這里把保存到數(shù)據(jù)庫的邏輯寫到了一個(gè)線程池中,主要是不希望記錄日志的邏輯影響了用戶請求數(shù)據(jù)接口的邏輯,和性能。
點(diǎn)擊獲取阿里云優(yōu)惠券
我的官網(wǎng)

我的博客
我的官網(wǎng)http://guan2ye.com
我的CSDN地址http://blog.csdn.net/chenjianandiyi
我的簡書地址http://www.lxweimin.com/u/9b5d1921ce34
我的githubhttps://github.com/javanan
我的碼云地址https://gitee.com/jamen/
阿里云優(yōu)惠券https://promotion.aliyun.com/ntms/act/ambassador/sharetouser.html?userCode=vf2b5zld&utm_source=vf2b5zld