1. 日志系统的难点在于AOP的应用
得把aop到底能拿来干什么整理一下,常用的那些函数,怎么构建切点切面什么的都得整理!!!
2. 日志数据表设计
从这张表的设计上面也就能看出日志系统的基本功能是什么,即:
核心是记录:谁,在什么时候,调用了哪个接口。
字段名 | 注释 | 类型 | 长度 | 是否必填 | 是否主键 |
---|---|---|---|---|---|
client_ip | 客户端ip | varchar | 100 | 否 | 否 |
req_uri | 请求映射路径 | varchar | 100 | 否 | 否 |
method | 方法名 | varchar | 200 | 否 | 否 |
param | 参数 | text | 0 | 否 | 否 |
operator | 操作人姓名 | varchar | 100 | 否 | 否 |
start_time | 接口请求时间 | varchar | 50 | 否 | 否 |
end_time | 接口返回时间 | varchar | 50 | 否 | 否 |
total_time | 总消耗时间 | varchar | 50 | 否 | 否 |
return_data | 接口返回数据 | text | 0 | 否 | 否 |
gmt_create | 创建时间 | datatime | 0 | 是 | 否 |
gmt_create_user | 创建人 | varchar | 50 | 是 | 否 |
gmt_modified | 修改时间 | datatime | 0 | 是 | 否 |
gmt_modified_user | 修改人 | varchar | 50 | 是 | 否 |
is_delete | 是否删除(0:否 1:是) | tinyint | 2 | 是 | 否 |
3. 切面类代码
@Aspect
@Component
public class SystemLogAspect {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
@Autowired
private SystemLogDAO systemLogDAO;
//这个逻辑还是有趣,只要是这个包里面的类都自动建立代理类,所有方法就都给代理了。
@Pointcut("execution(public * com.cy.ops.api.*.controller..*(..))")
public void systemLog() {}
@Around(value = "systemLog()")
public ResponseResult doAround(ProceedingJoinPoint joinPoint) throws Throwable {
ServletRequestAttributes attributes = (ServletRequestAttributes)RequestContextHolder.getRequestAttributes();
HttpServletRequest request = attributes.getRequest();
HttpServletResponse response = attributes.getResponse();
UserInfoBO userInfo = WebSession.getUserInfo(request, response);
if(userInfo == null) {
return new ResponseResult().setSuccess(false).setMessage(ResultCode.RECORD_LOGIN_EXPIRE.getMessage()).setCode(ResultCode.RECORD_LOGIN_EXPIRE.getCOde());
}
// 1、记录执行时间
long startTime = System.currentTimeMillis();
ResponseResult result = (ResponseResult) joinPoint.proceed(joinPoint.getArgs());
long endTime = System.currentTimeMillis();
long totalTime = endTime - startTime;
// 2、有无日志监控注解,有则输出
String methodName = joinPoint.getTarget().getClass().getName() + "." + joinPoint.getSignature().getName() + "()";
MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
Method targetMethod = nethodSignature.getMethod();
//这个注解的意思是如果有这个注解,就log出来
//打这个注解的应该是debug用到的重点,这里可以换一下逻辑,log的时候把参数和输出打印出来
if(targetMethod.isAnnotationPresent(ControllerMonitor.class)) {
logger.info("**********Method: {}, Start: {}, End: {}, Total: {}ms**********", methodName, dateFormat.format(startTime), dateFormat.format(endTime), totalTime);
}
// 3、存入数据库
//不管有没有注解,都要把访问记录存到数据库里面去
//(感觉这才是比较赞的逻辑,只要访问了,那就要存到数据表里面,不过查bug的时候,可以重点查一下输出出来的日志)
SystemLogDO systemLogDO = new SystemLogDO();
if(joinPoint.getArgs().length > 0){
systemLogDO.setPara(JsonToBeanUtil.beanToJSON(joinPoint.getArgs()[0]));
}
systemLogDO.setClientIp(IpUtil.getClientIp(request));
systemLogDO.setMethod(joinPoint.getTarget().getClass().getName() + "." + joinPoint.getSignature().getName() + "()");
systemLogDO.setOperator(userInfo.getUserName());
systemLogDO.setReqUri(request.getRequestURI());
systemLogDO.setReturnData(JsonToBeanUtil.beanToJSON(result));
systemLogDO.setStartTime(String.valueOf(startTime));
systemLogDO.setEndTime(String.valueOf(endTime));
systemLogDO.setTotalTime(String.valueOf(totalTime));
systemLogDO.setGmtCreateUser(userInfo.getUserName());
systemLogDO.setGmtModifiedUser(userInfo.getUserName());
systemLogDO.setIsDelete(0);
systemLogDAO.insert(systemLogDO);
return result;
}
}
网友评论