package com.yanzuoguang.cloud.aop; import com.alibaba.fastjson.JSON; import com.yanzuoguang.util.cache.MemoryCache; import com.yanzuoguang.util.contants.ResultConstants; import com.yanzuoguang.util.exception.ExceptionHelper; import com.yanzuoguang.util.helper.JsonHelper; import com.yanzuoguang.util.helper.StringHelper; import com.yanzuoguang.util.log.Log; import com.yanzuoguang.util.thread.ThreadNext; import com.yanzuoguang.util.vo.LogVo; import com.yanzuoguang.util.vo.ResponseResult; import org.aspectj.lang.ProceedingJoinPoint; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.ApplicationContext; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.util.ArrayList; import java.util.List; import java.util.concurrent.LinkedBlockingQueue; /** * 基本处理拦截类 * * @author 颜佐光 */ public class BaseRequestAspect implements ThreadNext.Next { @Value("${spring.application.name}") protected String applicationName; @Value("${yzg.logCommon:true}") protected boolean logCommon = true; @Value("${yzg.logAll:false}") protected boolean logAll = false; @Value("${yzg.cacheTime:120}") protected int cacheTime = 120; @Value("${yzg.reqSize:5000}") private int reqSize; @Value("${yzg.log.notFilter:^.*login.*$}") private String notFilter; @Value("${yzg.log.filter:^.*log.*$}") private String filter; @Autowired protected ApplicationContext context; protected LogFeign logFeign; /** * 缓存队列 */ protected volatile LinkedBlockingQueue<LogVo> cache = new LinkedBlockingQueue<LogVo>(); public BaseRequestAspect() { ThreadNext.start(this, "save log error"); } /** * 添加日志到缓存中,并不是立即添加,而是通过线程执行,防止对环境造成影响 * * @param logVo */ public void addLog(LogVo logVo) { cache.add(logVo); } /** * 初始化日志Vo * * @param url 请求路径 * @param joinPoint 请求参数 * @param responseResult 返回参数 * @return */ protected LogVo initLogInterVo(String url, ProceedingJoinPoint joinPoint, ResponseResult responseResult) { LogVo logInterVo = new LogVo(); logInterVo.setLogId(StringHelper.getNewID()); //平台名 logInterVo.setLogSources(applicationName); //请求URL logInterVo.setInterUrl(url); Object paraTo = getFirstDataParameter(joinPoint.getArgs()); //请求参数 logInterVo.setContent(JSON.toJSONString(paraTo)); //返回参数 logInterVo.setResult(JSON.toJSONString(responseResult)); logInterVo.setStatus(responseResult != null && responseResult.getCode() == ResultConstants.SUCCESS ? 1 : 0); return logInterVo; } /** * 获取请求的参数 * * @param args * @return */ protected Object getFirstDataParameter(Object[] args) { List<Object> para = getDataParameters(args); Object paraTo = para; if (para.size() == 1) { paraTo = para.get(0); } return paraTo; } /** * 获取数据参数 * * @param args * @return */ protected List<Object> getDataParameters(Object[] args) { List<Object> para = new ArrayList<>(); for (Object item : args) { if (item instanceof HttpServlet || item instanceof HttpServletResponse || item instanceof HttpServletRequest) { continue; } para.add(item); } return para; } /** * 获取JSON,当Json过长时,截断 * * @param paraJson * @return */ private String getMaxString(String paraJson) { if (paraJson != null && paraJson.length() > reqSize) { paraJson = paraJson.substring(0, reqSize); } return paraJson; } /** * 获取是否清空日志的标签 * * @return 返回日志是否清空 */ protected boolean requestLogInit() { boolean clear = Log.threadCurrent() == null; if (clear) { Log.threadBegin(); } return clear; } /** * 记录请求日志 * * @param joinPoint * @return */ protected long requestLog(String tag, ProceedingJoinPoint joinPoint) { long start = System.currentTimeMillis(); try { String name = joinPoint.getSignature().getName(); Log.info(joinPoint.getSignature().getDeclaringType(), " %s [ %s ] request: %s", tag, name, this.getMaxString(JsonHelper.serialize(getFirstDataParameter(joinPoint.getArgs())))); } catch (Exception ex) { ex.printStackTrace(); } return start; } /** * 保存日志 * * @param url * @param joinPoint * @param result * @param resultEx * @param start */ protected void responseLog(boolean clear, String tag, String url, ProceedingJoinPoint joinPoint, long start, Object result, Exception resultEx) { try { String name = joinPoint.getSignature().getName(); if (StringHelper.isEmpty(url)) { url = String.format("%s.%s", joinPoint.getSignature().getDeclaringTypeName(), name); } // 处理结果 ResponseResult responseResult; if (result instanceof ResponseResult) { responseResult = (ResponseResult) result; } else { responseResult = ResponseResult.result(result); } long time = System.currentTimeMillis() - start; if (resultEx != null) { responseResult = ExceptionHelper.getError(resultEx); Log.error(joinPoint.getSignature().getDeclaringType(), resultEx, "%s [ %s ] time %d ms, result: %s", tag, name, time, getMaxString(JsonHelper.serialize(responseResult))); resultEx.printStackTrace(); } else if (logCommon) { Log.info(joinPoint.getSignature().getDeclaringType(), "%s [ %s ] time %d ms, result: %s", tag, name, time, getMaxString(JsonHelper.serialize(responseResult))); } // 日志请求不记录,防止死循环递归 boolean isLog = isLog(name, url); if (isLog) { return; } // 正常请求不记录 if (!logAll && responseResult != null && responseResult.getCode() == ResultConstants.SUCCESS) { return; } LogVo logVo = initLogInterVo(url, joinPoint, responseResult); logVo.setUseTime((int) time); addLog(logVo); } catch (Exception e) { e.printStackTrace(); } finally { if (clear) { Log.threadCommit(); } } } /** * 是否属于日志服务 * * @param name * @param url * @return */ private boolean isLog(String name, String url) { boolean noFilter = applicationName.matches(notFilter) || name.matches(notFilter) || url.matches(notFilter); if (noFilter) { return false; } boolean isLog = applicationName.matches(filter) || name.matches(filter) || url.matches(filter); return isLog; } /** * 执行下一个函数,出现异常会继续执行 * * @return 是否继续执行 */ @Override public boolean next() { while (cache.size() > 0) { LogVo item = cache.poll(); if (item != null) { try { if (logFeign == null) { logFeign = context.getBean(LogFeign.class); } logFeign.save(item); } catch (Exception ex) { ex.printStackTrace(); } } } return true; } /** * 沉睡时间 * * @return */ @Override public int getNextTime() { return 1000; } }