package com.usky.aspect; import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.serializer.PropertyFilter; import com.usky.annotion.AutoLog; import com.usky.constant.CommonConstant; import com.usky.entity.sys.SysLogDTO; import com.usky.service.log.LogService; import com.usky.utils.IPUtils; import com.usky.utils.SpringContextUtils; import org.aspectj.lang.JoinPoint; 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.springframework.core.LocalVariableTableParameterNameDiscoverer; import org.springframework.stereotype.Component; import org.springframework.validation.BindingResult; import org.springframework.web.multipart.MultipartFile; import javax.annotation.Resource; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import java.lang.reflect.Method; import java.sql.Timestamp; /** * @author laowo * @version v1.0 * @date 2020/11/10 14:41 * @description 系统日志切面类 **/ @Aspect @Component public class AutoLogAspect { @Resource private LogService logService; @Pointcut("@annotation(com.usky.annotion.AutoLog)") 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; //保存日志 saveSysLog(point, time, result); return result; } private void saveSysLog(ProceedingJoinPoint joinPoint, long time, Object obj) { MethodSignature signature = (MethodSignature) joinPoint.getSignature(); Method method = signature.getMethod(); SysLogDTO dto = new SysLogDTO(); AutoLog syslog = method.getAnnotation(AutoLog.class); if(syslog != null){ //update-begin-author:taoyan date: String content = syslog.value(); //注解上的描述,操作日志内容 dto.setLogType(syslog.logType()); dto.setLogContent(content); } //请求的方法名 String className = joinPoint.getTarget().getClass().getName(); String methodName = signature.getName(); dto.setMethod(className + "." + methodName + "()"); //设置操作类型 if (dto.getLogType() == CommonConstant.LOG_TYPE_2) { dto.setOperateType(getOperateType(methodName, syslog.operateType())); } //获取request HttpServletRequest request = SpringContextUtils.getHttpServletRequest(); //请求的参数 dto.setRequestType(request.getMethod()); dto.setRequestParam(getReqestParams(request,joinPoint)); //设置IP地址 dto.setIp(IPUtils.getIpAddr(request)); //获取登录用户信息 TODO 添加用户数据后启用 // LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal(); // if(sysUser!=null){ // dto.setUserid(sysUser.getUsername()); // dto.setUsername(sysUser.getRealname()); // } //耗时 dto.setCostTime(time); dto.setCreateTime(new Timestamp(System.currentTimeMillis())); //保存系统日志 logService.addLog(dto); } /** * 获取操作类型 */ private int getOperateType(String methodName,int operateType) { if (operateType > 0) { return operateType; } if (methodName.startsWith("list")) { return CommonConstant.OPERATE_TYPE_1; } if (methodName.startsWith("add")) { return CommonConstant.OPERATE_TYPE_2; } if (methodName.startsWith("edit")) { return CommonConstant.OPERATE_TYPE_3; } if (methodName.startsWith("delete")) { return CommonConstant.OPERATE_TYPE_4; } if (methodName.startsWith("import")) { return CommonConstant.OPERATE_TYPE_5; } if (methodName.startsWith("export")) { return CommonConstant.OPERATE_TYPE_6; } return CommonConstant.OPERATE_TYPE_1; } /** * 请求参数获取 * @param request * @param joinPoint * @return */ private String getReqestParams(HttpServletRequest request, JoinPoint joinPoint) { String httpMethod = request.getMethod(); String params = ""; if ("POST".equals(httpMethod) || "PUT".equals(httpMethod) || "PATCH".equals(httpMethod)) { Object[] paramsArray = joinPoint.getArgs(); // java.lang.IllegalStateException: It is illegal to call this method if the current request is not in asynchronous mode (i.e. isAsyncStarted() returns false) // https://my.oschina.net/mengzhang6/blog/2395893 Object[] arguments = new Object[paramsArray.length]; for (int i = 0; i < paramsArray.length; i++) { if (paramsArray[i] instanceof BindingResult || paramsArray[i] instanceof ServletRequest || paramsArray[i] instanceof ServletResponse || paramsArray[i] instanceof MultipartFile) { //ServletRequest不能序列化,从入参里排除,否则报异常:java.lang.IllegalStateException: It is illegal to call this method if the current request is not in asynchronous mode (i.e. isAsyncStarted() returns false) //ServletResponse不能序列化 从入参里排除,否则报异常:java.lang.IllegalStateException: getOutputStream() has already been called for this response continue; } arguments[i] = paramsArray[i]; } //update-begin-author:taoyan date:20200724 for:日志数据太长的直接过滤掉 PropertyFilter profilter = new PropertyFilter() { @Override public boolean apply(Object o, String name, Object value) { if(value!=null && value.toString().length()>500){ return false; } return true; } }; params = JSONObject.toJSONString(arguments, profilter); //update-end-author:taoyan date:20200724 for:日志数据太长的直接过滤掉 } else { MethodSignature signature = (MethodSignature) joinPoint.getSignature(); Method method = signature.getMethod(); // 请求的方法参数值 Object[] args = joinPoint.getArgs(); // 请求的方法参数名称 LocalVariableTableParameterNameDiscoverer u = new LocalVariableTableParameterNameDiscoverer(); String[] paramNames = u.getParameterNames(method); if (args != null && paramNames != null) { for (int i = 0; i < args.length; i++) { params += " " + paramNames[i] + ": " + args[i]; } } } return params; } }