在系统中涉及到的方法有很多,有的时候我们需要监控,系统中哪些方法执行效率低,耗时长,这样有助于我们得知系统中存在哪些隐患;
得知隐患后,我们可以针对这些隐患做性能的优化
本篇博客的内容,是基于spring的aop以及自定义注解完成的;
当浏览器输入
执行登录
控制台输出
登录系统控制台产生的所有日志输出
16:24:28 [http-nio-80-exec-9] INFO c.j.b.common.aspect.WebLogAspect - 请求地址 : http://localhost/login 16:24:28 [http-nio-80-exec-9] INFO c.j.b.common.aspect.WebLogAspect - HTTP METHOD : POST 16:24:28 [http-nio-80-exec-9] INFO c.j.b.common.aspect.WebLogAspect - CLASS_METHOD : com.javaxl.bootdo.system.controller.LoginController.ajaxLogin 16:24:28 [http-nio-80-exec-9] INFO c.j.b.common.aspect.WebLogAspect - 参数 : [admin, 111111, 1969, org.apache.shiro.web.servlet.ShiroHttpServletRequest@78f55dd6] 16:24:28 [http-nio-80-exec-9] INFO c.j.b.common.aspect.WebLogAspect - 耗时 : 2345 16:24:28 [http-nio-80-exec-9] DEBUG c.j.b.common.aspect.WebLogAspect - 返回值 : {msg=请输入正确的验证码, code=500} 16:24:28 [SimpleAsyncTaskExecutor-3] DEBUG c.j.bootdo.common.dao.LogDao.save - ==> Preparing: insert into sys_log ( `user_id`, `username`, `operation`, `time`, `method`, `params`, `ip`, `gmt_create` ) values ( ?, ?, ?, ?, ?, ?, ?, ? ) 16:24:28 [SimpleAsyncTaskExecutor-3] DEBUG c.j.bootdo.common.dao.LogDao.save - ==> Parameters: 1(Long), admin(String), 登录(String), 2345(Integer), com.javaxl.bootdo.system.controller.LoginController.ajaxLogin()(String), null, 127.0.0.1(String), 2019-06-24 16:24:28.03(Timestamp) 16:24:28 [SimpleAsyncTaskExecutor-3] DEBUG c.j.bootdo.common.dao.LogDao.save - <== Updates: 1 16:24:47 [http-nio-80-exec-6] INFO c.j.b.common.aspect.WebLogAspect - 请求地址 : http://localhost/login 16:24:47 [http-nio-80-exec-6] INFO c.j.b.common.aspect.WebLogAspect - HTTP METHOD : POST 16:24:47 [http-nio-80-exec-6] INFO c.j.b.common.aspect.WebLogAspect - CLASS_METHOD : com.javaxl.bootdo.system.controller.LoginController.ajaxLogin 16:24:47 [http-nio-80-exec-6] INFO c.j.b.common.aspect.WebLogAspect - 参数 : [admin, 111111, 9054, org.apache.shiro.web.servlet.ShiroHttpServletRequest@3f83b3f0] 16:24:47 [http-nio-80-exec-6] DEBUG c.j.bootdo.system.dao.UserDao.list - ==> Preparing: select `user_id`,`username`,`name`,`password`,`dept_id`,`email`,`mobile`,`status`,`user_id_create`,`gmt_create`,`gmt_modified`,`sex`,`birth`,`pic_id`,`live_address`,`hobby`,`province`,`city`,`district` from sys_user WHERE username = ? order by user_id desc 16:24:47 [http-nio-80-exec-6] DEBUG c.j.bootdo.system.dao.UserDao.list - ==> Parameters: admin(String) 16:24:47 [http-nio-80-exec-6] DEBUG c.j.bootdo.system.dao.UserDao.list - <== Total: 1 16:24:47 [http-nio-80-exec-6] DEBUG c.j.b.s.dao.UserRoleDao.listRoleSign - ==> Preparing: select distinct r.role_sign from sys_role r left join sys_user_role ur on r.role_id = ur.role_id where ur.user_id=? 16:24:47 [http-nio-80-exec-6] DEBUG c.j.b.s.dao.UserRoleDao.listRoleSign - ==> Parameters: 1(Long) 16:24:47 [http-nio-80-exec-6] DEBUG c.j.b.s.dao.UserRoleDao.listRoleSign - <== Total: 3 16:24:47 [http-nio-80-exec-6] INFO c.j.b.common.aspect.WebLogAspect - 耗时 : 2534 16:24:47 [http-nio-80-exec-6] DEBUG c.j.b.common.aspect.WebLogAspect - 返回值 : {msg=操作成功, code=0} 16:24:47 [SimpleAsyncTaskExecutor-4] DEBUG c.j.bootdo.common.dao.LogDao.save - ==> Preparing: insert into sys_log ( `user_id`, `username`, `operation`, `time`, `method`, `params`, `ip`, `gmt_create` ) values ( ?, ?, ?, ?, ?, ?, ?, ? ) 16:24:47 [SimpleAsyncTaskExecutor-4] DEBUG c.j.bootdo.common.dao.LogDao.save - ==> Parameters: 1(Long), admin(String), 登录(String), 2534(Integer), com.javaxl.bootdo.system.controller.LoginController.ajaxLogin()(String), null, 127.0.0.1(String), 2019-06-24 16:24:47.954(Timestamp) 16:24:47 [SimpleAsyncTaskExecutor-4] DEBUG c.j.bootdo.common.dao.LogDao.save - <== Updates: 1 16:24:50 [http-nio-80-exec-2] INFO c.j.b.common.aspect.WebLogAspect - 请求地址 : http://localhost/index 16:24:50 [http-nio-80-exec-2] INFO c.j.b.common.aspect.WebLogAspect - HTTP METHOD : GET 16:24:50 [http-nio-80-exec-2] INFO c.j.b.common.aspect.WebLogAspect - CLASS_METHOD : com.javaxl.bootdo.system.controller.LoginController.index 16:24:50 [http-nio-80-exec-2] INFO c.j.b.common.aspect.WebLogAspect - 参数 : [{}] 16:24:50 [http-nio-80-exec-2] DEBUG c.j.b.s.dao.MenuDao.listMenuByUserId - ==> Preparing: select distinct m.menu_id , parent_id, name, url, perms,`type`,icon,order_num,gmt_create, gmt_modified from sys_menu m left join sys_role_menu rm on m.menu_id = rm.menu_id left join sys_user_role ur on rm.role_id =ur.role_id where ur.user_id = ? and m.type in(0,1) order by m.order_num 16:24:50 [http-nio-80-exec-2] DEBUG c.j.b.s.dao.MenuDao.listMenuByUserId - ==> Parameters: 1(Long) 16:24:50 [http-nio-80-exec-2] DEBUG c.j.b.s.dao.MenuDao.listMenuByUserId - <== Total: 30 16:24:50 [http-nio-80-exec-2] DEBUG c.j.bootdo.common.dao.FileDao.get - ==> Preparing: select `id`,`type`,`url`,`create_date` from sys_file where id = ? 16:24:50 [http-nio-80-exec-2] DEBUG c.j.bootdo.common.dao.FileDao.get - ==> Parameters: 138(Long) 16:24:50 [http-nio-80-exec-2] DEBUG c.j.bootdo.common.dao.FileDao.get - <== Total: 1 16:24:50 [http-nio-80-exec-2] INFO c.j.b.common.aspect.WebLogAspect - 耗时 : 2040 16:24:50 [http-nio-80-exec-2] DEBUG c.j.b.common.aspect.WebLogAspect - 返回值 : index_v1 16:24:50 [SimpleAsyncTaskExecutor-5] DEBUG c.j.bootdo.common.dao.LogDao.save - ==> Preparing: insert into sys_log ( `user_id`, `username`, `operation`, `time`, `method`, `params`, `ip`, `gmt_create` ) values ( ?, ?, ?, ?, ?, ?, ?, ? ) 16:24:50 [SimpleAsyncTaskExecutor-5] DEBUG c.j.bootdo.common.dao.LogDao.save - ==> Parameters: 1(Long), admin(String), 请求访问主页(String), 2040(Integer), com.javaxl.bootdo.system.controller.LoginController.index()(String), null, 127.0.0.1(String), 2019-06-24 16:24:50.033(Timestamp) 16:24:50 [SimpleAsyncTaskExecutor-5] DEBUG c.j.bootdo.common.dao.LogDao.save - <== Updates: 1 16:24:51 [http-nio-80-exec-1] INFO c.j.b.common.aspect.WebLogAspect - 请求地址 : http://localhost/main 16:24:51 [http-nio-80-exec-1] INFO c.j.b.common.aspect.WebLogAspect - HTTP METHOD : GET 16:24:51 [http-nio-80-exec-1] INFO c.j.b.common.aspect.WebLogAspect - CLASS_METHOD : com.javaxl.bootdo.system.controller.LoginController.main 16:24:51 [http-nio-80-exec-1] INFO c.j.b.common.aspect.WebLogAspect - 参数 : [] 16:24:51 [http-nio-80-exec-1] INFO c.j.b.common.aspect.WebLogAspect - 耗时 : 1111 16:24:51 [http-nio-80-exec-1] DEBUG c.j.b.common.aspect.WebLogAspect - 返回值 : main 16:24:51 [http-nio-80-exec-10] INFO c.j.b.common.aspect.WebLogAspect - 请求地址 : http://localhost/oa/notify/message 16:24:51 [http-nio-80-exec-10] INFO c.j.b.common.aspect.WebLogAspect - HTTP METHOD : GET 16:24:51 [http-nio-80-exec-10] INFO c.j.b.common.aspect.WebLogAspect - CLASS_METHOD : com.javaxl.bootdo.oa.controller.NotifyController.message 16:24:51 [http-nio-80-exec-10] INFO c.j.b.common.aspect.WebLogAspect - 参数 : [] 16:24:52 [http-nio-80-exec-5] INFO c.j.b.common.aspect.WebLogAspect - 请求地址 : http://localhost/main 16:24:52 [http-nio-80-exec-5] INFO c.j.b.common.aspect.WebLogAspect - HTTP METHOD : GET 16:24:52 [http-nio-80-exec-5] INFO c.j.b.common.aspect.WebLogAspect - CLASS_METHOD : com.javaxl.bootdo.system.controller.LoginController.main 16:24:52 [http-nio-80-exec-5] INFO c.j.b.common.aspect.WebLogAspect - 参数 : [] 16:24:52 [http-nio-80-exec-5] INFO c.j.b.common.aspect.WebLogAspect - 耗时 : 1413 16:24:52 [http-nio-80-exec-5] DEBUG c.j.b.common.aspect.WebLogAspect - 返回值 : main 16:24:52 [http-nio-80-exec-10] DEBUG c.j.bootdo.oa.dao.NotifyDao.listDTO - ==> Preparing: select DISTINCT n.id ,`type`,`title`,`content`,`files`,r.is_read,`status`,`create_by`,`create_date`,`update_by`,`update_date`,`remarks`,`del_flag` from oa_notify_record r right JOIN oa_notify n on r.notify_id = n.id WHERE r.is_read = ? and r.user_id = ? order by is_read ASC, update_date DESC limit ?, ? 16:24:52 [http-nio-80-exec-10] DEBUG c.j.bootdo.oa.dao.NotifyDao.listDTO - ==> Parameters: 0(String), 1(Long), 0(Integer), 3(Integer) 16:24:52 [http-nio-80-exec-10] DEBUG c.j.bootdo.oa.dao.NotifyDao.listDTO - <== Total: 0 16:24:52 [http-nio-80-exec-10] DEBUG c.j.bootdo.oa.dao.NotifyDao.countDTO - ==> Preparing: select count(*) from oa_notify_record r right JOIN oa_notify n on r.notify_id = n.id where r.user_id =? and r.is_read = ? 16:24:52 [http-nio-80-exec-10] DEBUG c.j.bootdo.oa.dao.NotifyDao.countDTO - ==> Parameters: 1(Long), 0(String) 16:24:52 [http-nio-80-exec-10] DEBUG c.j.bootdo.oa.dao.NotifyDao.countDTO - <== Total: 1 16:24:52 [http-nio-80-exec-10] INFO c.j.b.common.aspect.WebLogAspect - 耗时 : 1433 16:24:52 [http-nio-80-exec-10] DEBUG c.j.b.common.aspect.WebLogAspect - 返回值 : com.javaxl.bootdo.common.utils.PageUtils@34bd65e2
系统日志监控界面
Log
@Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface Log { String value() default ""; }
这个注解类的作用在于可以动态获取调用的方法所携带的参数
参考文章
https://blog.csdn.net/Merci_sen/article/details/80886206
WebLogAspect
package com.javaxl.bootdo.common.aspect; import com.javaxl.bootdo.common.utils.HttpContextUtils; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.*; import org.aspectj.lang.reflect.MethodSignature; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Component; import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.ServletRequestAttributes; import sun.net.util.IPAddressUtil; import javax.servlet.http.HttpServletRequest; import java.lang.reflect.Method; import java.util.Arrays; @Aspect @Component public class WebLogAspect { private static final Logger logger = LoggerFactory.getLogger(WebLogAspect.class); @Pointcut("execution( * com.javaxl.bootdo..controller.*.*(..))")//两个..代表所有子目录,最后括号里的两个..代表所有参数 public void logPointCut() { } @Before("logPointCut()") public void doBefore(JoinPoint joinPoint) throws Throwable { // 接收到请求,记录请求内容 ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); HttpServletRequest request = attributes.getRequest(); // 记录下请求内容 logger.info("请求地址 : " + request.getRequestURL().toString()); logger.info("HTTP METHOD : " + request.getMethod()); // 获取真实的ip地址 //logger.info("IP : " + IPAddressUtil.getClientIpAddress(request)); logger.info("CLASS_METHOD : " + joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName()); logger.info("参数 : " + Arrays.toString(joinPoint.getArgs())); // loggger.info("参数 : " + joinPoint.getArgs()); } @AfterReturning(returning = "ret", pointcut = "logPointCut()")// returning的值和doAfterReturning的参数名一致 public void doAfterReturning(Object ret) throws Throwable { // 处理完请求,返回内容(返回值太复杂时,打印的是物理存储空间的地址) logger.debug("返回值 : " + ret); } @Around("logPointCut()") public Object doAround(ProceedingJoinPoint pjp) throws Throwable { long startTime = System.currentTimeMillis(); Object ob = pjp.proceed();// ob 为方法的返回值 logger.info("耗时 : " + (System.currentTimeMillis() - startTime)); return ob; } }
LogAspect
package com.javaxl.bootdo.common.aspect; import java.lang.reflect.Method; import java.util.Date; import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; import javax.servlet.http.HttpServletRequest; import com.javaxl.bootdo.common.service.LogService; import com.javaxl.bootdo.system.domain.UserToken; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Pointcut; import org.aspectj.lang.reflect.MethodSignature; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Component; import com.javaxl.bootdo.common.annotation.Log; import com.javaxl.bootdo.common.dao.LogDao; import com.javaxl.bootdo.common.domain.LogDO; import com.javaxl.bootdo.common.utils.HttpContextUtils; import com.javaxl.bootdo.common.utils.IPUtils; import com.javaxl.bootdo.common.utils.JSONUtils; import com.javaxl.bootdo.common.utils.ShiroUtils; import com.javaxl.bootdo.system.domain.UserDO; @Aspect @Component public class LogAspect { private static final Logger logger = LoggerFactory.getLogger(LogAspect.class); @Autowired LogService logService; @Pointcut("@annotation(com.javaxl.bootdo.common.annotation.Log)") 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; //异步保存日志 saveLog(point, time); return result; } void saveLog(ProceedingJoinPoint joinPoint, long time) throws InterruptedException { MethodSignature signature = (MethodSignature) joinPoint.getSignature(); Method method = signature.getMethod(); LogDO sysLog = new LogDO(); Log syslog = method.getAnnotation(Log.class); if (syslog != null) { // 注解上的描述 sysLog.setOperation(syslog.value()); } // 请求的方法名 String className = joinPoint.getTarget().getClass().getName(); String methodName = signature.getName(); sysLog.setMethod(className + "." + methodName + "()"); // 请求的参数 Object[] args = joinPoint.getArgs(); try { String params = JSONUtils.beanToJson(args[0]).substring(0, 4999); sysLog.setParams(params); } catch (Exception e) { } // 获取request HttpServletRequest request = HttpContextUtils.getHttpServletRequest(); // 设置IP地址 sysLog.setIp(IPUtils.getIpAddr(request)); // 用户名 UserDO currUser = ShiroUtils.getUser(); if (null == currUser) { if (null != sysLog.getParams()) { sysLog.setUserId(-1L); sysLog.setUsername(sysLog.getParams()); } else { sysLog.setUserId(-1L); sysLog.setUsername("获取用户信息为空"); } } else { sysLog.setUserId(ShiroUtils.getUserId()); sysLog.setUsername(ShiroUtils. getUser().getUsername()); } sysLog.setTime((int) time); // 系统当前时间 Date date = new Date(); sysLog.setGmtCreate(date); // 保存系统日志 logService.save(sysLog); } }
over.......
备案号:湘ICP备19000029号
Copyright © 2018-2019 javaxl晓码阁 版权所有