springboot AOP记录日志(线程池实现)

mac2025-05-31  76

通过线程池异步实现的目的是,尽量不去抢占主业务的资源,通过异步线程处理切面日志

 1.配置多线程执行器

 

@Configuration @EnableAsync public class ExecutorConfig { @Bean public Executor asyncServiceExecutor() { ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); //配置核心线程数 executor.setCorePoolSize(5); //配置最大线程数 executor.setMaxPoolSize(10); //配置队列大小 executor.setQueueCapacity(400); //配置线程池中的线程的名称前缀 executor.setThreadNamePrefix("thread-"); // rejection-policy:当pool已经达到max size的时候,如何处理新任务 // CALLER_RUNS:不在新线程中执行任务,而是有调用者所在的线程来执行 executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); //执行初始化 executor.initialize(); return executor; } }

2.创建切面类

@Aspect @Component public class ControllerAspect { @Autowired private LogService sysLogService; @Pointcut("execution(* com.neusoft.aaaa.*.controller..*.*(..)) && !execution(* com.bbbb.controller..*.*(..))") public void logPointCut() { } @Around("logPointCut()") public Object around(ProceedingJoinPoint point) throws Throwable { long beginTime = System.currentTimeMillis(); String userName = ""; try{ userName = ShiroUtils.getLoginUser().getUserName();//若是退出操作,执行后就获取不到用户对象了,所以提前获取 }catch (Exception e){ } //获取request HttpServletRequest request = HttpContextUtils.getHttpServletRequest();//return ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); //设置IP地址 String ip = IPUtils.getIpAddr(request); //执行方法 Object result = point.proceed();//result是方法的返回结果 //执行时长(毫秒) long time = System.currentTimeMillis() - beginTime; //保存日志 sysLogService.save(point, time,result,userName,ip,beginTime); return result; } }

其中,获取ip的工具类

public class IPUtils { private static Logger logger = LoggerFactory.getLogger(IPUtils.class); /** * 获取IP地址 * * 使用Nginx等反向代理软件, 则不能通过request.getRemoteAddr()获取IP地址 * 如果使用了多级反向代理的话,X-Forwarded-For的值并不止一个,而是一串IP地址,X-Forwarded-For中第一个非unknown的有效IP字符串,则为真实IP地址 */ public static String getIpAddr(HttpServletRequest request) { String ip = null; try { ip = request.getHeader("x-forwarded-for"); if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) { ip = request.getHeader("Proxy-Client-IP"); } if (StringUtils.isEmpty(ip) || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { ip = request.getHeader("WL-Proxy-Client-IP"); } if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) { ip = request.getHeader("HTTP_CLIENT_IP"); } if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) { ip = request.getHeader("HTTP_X_FORWARDED_FOR"); } if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) { ip = request.getRemoteAddr(); } } catch (Exception e) { logger.error("IPUtils ERROR ", e); } // //使用代理,则获取第一个IP地址 // if(StringUtils.isEmpty(ip) && ip.length() > 15) { // if(ip.indexOf(",") > 0) { // ip = ip.substring(0, ip.indexOf(",")); // } // } return ip; } }

 3.日志处理接口

public interface LogService { void save(ProceedingJoinPoint joinPoint, long time, Object result,String userName,String ip,long begin); }

实现类:@Async("asyncServiceExecutor")是关键

@Service("logService") public class LogServiceImpl implements LogService { private static Logger log = LoggerFactory.getLogger(LogServiceImpl.class); @Resource LogMapper logMapper; @Override @Async("asyncServiceExecutor") public void save(ProceedingJoinPoint joinPoint, long time, Object result, String userName, String ip, long begin) { try { MethodSignature signature = (MethodSignature) joinPoint.getSignature(); Method method = signature.getMethod(); ApiOperation operation = method.getAnnotation(ApiOperation.class); //请求的方法名 String className = joinPoint.getTarget().getClass().getName(); String[] splitClassName = className.split("\\."); String methodName = splitClassName[splitClassName.length-1] + "." + signature.getName(); String operationStr = methodName; if (operation != null) { //注解上的描述 operationStr = operation.value(); } //请求的参数 Object[] args = joinPoint.getArgs(); String[] parameterNames = signature.getParameterNames(); JSONObject paramsJson = new JSONObject(); String params = ""; if (args != null && args.length > 0) { for (int i = 0; i < args.length; i++) { if (!BindingResult.class.isInstance(args[i])) { paramsJson.put(parameterNames[i], args[i]); } } params = paramsJson.toJSONString(); } if (StringUtils.isBlank(userName)) { if (args != null && args.length > 0) { if (UserEntity.class.isInstance(args[0])) { UserEntityuser = (UserEntity) args[0]; userName = user.getUserName(); } } } String startTime = DateUtils.format(DateUtils.getDate(begin, "yyyy-MM-dd HH:mm:ss"), "yyyy-MM-dd HH:mm:ss"); LogEntity sysLog = new LogEntity(userName, operationStr, methodName, params, startTime, time, JSONObject.toJSONString(result), ip); //保存系统日志 logMapper.save(sysLog); } catch (Exception e) { log.error("记录系统日志异常", e); } } }

4.实体类

public class LogEntity implements Serializable { private static final long serialVersionUID = 1L; private String id;//id private String userName;//操作用户名 private String operation;//操作名称 private String method;//执行方法 private String params;//请求参数 private String startTime;//请求时间 private long time;//执行耗时 private String backMessage;//返回参数 private String ip;//访问者ip private String createDate;//时间戳 public LogEntity(){ this.id= UUID.randomUUID().toString(); } public LogEntity(String userName, String operation, String method, String params, String startTime, long time, String backMessage, String ip) { this.id= UUID.randomUUID().toString(); this.userName = userName; this.operation = operation; this.method = method; this.params = params; this.startTime = startTime; this.time = time; this.backMessage = backMessage; this.ip = ip; } public String getId() { return id; } public void setId(String id) { this.id = id; } public String getUserName() { return userName; } public void setUserName(String userName) { this.userName = userName; } public String getOperation() { return operation; } public void setOperation(String operation) { this.operation = operation; } public String getMethod() { return method; } public void setMethod(String method) { this.method = method; } public String getParams() { return params; } public void setParams(String params) { this.params = params; } public String getStartTime() { return startTime; } public void setStartTime(String startTime) { this.startTime = startTime; } public long getTime() { return time; } public void setTime(long time) { this.time = time; } public String getBackMessage() { return backMessage; } public void setBackMessage(String backMessage) { this.backMessage = backMessage; } public String getIp() { return ip; } public void setIp(String ip) { this.ip = ip; } public String getCreateDate() { return createDate; } public void setCreateDate(String createDate) { this.createDate = createDate; } }

至于mapper的插入语句就不粘贴了,自己敲吧!

最新回复(0)