您好,登錄后才能下訂單哦!
這篇文章主要講解了Springboot接口項(xiàng)目使用AOP記錄日志的方法,內(nèi)容清晰明了,對此有興趣的小伙伴可以學(xué)習(xí)一下,相信大家閱讀完之后會(huì)有幫助。
一、 背景
一直想給項(xiàng)目構(gòu)建一個(gè)統(tǒng)一的日志收集系統(tǒng),先邁出第一步,構(gòu)建一個(gè)日志收集類,用AOP實(shí)現(xiàn)無侵入日志收集
二、 環(huán)境
1.此隨筆內(nèi)容基于spring boot項(xiàng)目
2.數(shù)據(jù)庫為mysql 5.7.9版本
3.jdk 版本為1.8
三、 說明
此版采用數(shù)據(jù)庫存儲(chǔ),之后考慮使用elasticsearch等工具存儲(chǔ)
四、 內(nèi)容
1、構(gòu)建日志采集實(shí)體類:BaseLogMessage
public class BaseLogMessage { private String serverIP; private String appName; private String method; private String type; private String userCode; private String uri; private String operationName; private String operationStatus; private long startTime; private Object parameter; private Object result; private int SpendTime; // 此處省略get、set }
2、構(gòu)建一個(gè)配置文件讀取類,用于讀取配置文件中的系統(tǒng)名稱:SystemPropetiesUtil
@Configuration public class SystemPropetiesUtil { @Value("${spring.application.name}") private String sysName;//系統(tǒng)名稱<br> // 此處省略get、set<br>}
3、新建一個(gè)AOP類,在控制器方法上作為切點(diǎn),執(zhí)行日志收集: LogAspect
@Aspect @Component public class LogAspect { @Autowired private SystemPropetiesUtil systemPropetiesUtil; //定義切點(diǎn)方法 @Pointcut("execution(public * cq..campus.prevented.controller.*.*(..))") public void controllerLog() { } public static final Logger LOGGER = LoggerFactory.getLogger(LogAspect.class); @Around("controllerLog()") public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable { long startTime = System.currentTimeMillis(); //獲取當(dāng)前請求對象 ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); HttpServletRequest request = attributes.getRequest(); //記錄請求信息 BaseLogMessage baseLogMessage = new BaseLogMessage(); //1.獲取到所有的參數(shù)值的數(shù)組 Object[] args = joinPoint.getArgs(); Signature signature = joinPoint.getSignature(); MethodSignature methodSignature = (MethodSignature) signature; //2.獲取到方法的所有參數(shù)名稱的字符串?dāng)?shù)組 String[] parameterNames = methodSignature.getParameterNames(); Object result = joinPoint.proceed(); Method method = methodSignature.getMethod(); if (method.isAnnotationPresent(ApiOperation.class)) { ApiOperation apiOperation = method.getAnnotation(ApiOperation.class); baseLogMessage.setOperationName(apiOperation.value()); } long endTime = System.currentTimeMillis(); String urlStr = request.getRequestURL().toString(); baseLogMessage.setUri(urlStr); baseLogMessage.setType("操作日志"); baseLogMessage.setServerIP(getRemoteIP(request)); baseLogMessage.setMethod(request.getMethod()); baseLogMessage.setAppName(systemPropetiesUtil.getSysName()); baseLogMessage.setResult(result); baseLogMessage.setParameter(getParameter(method, joinPoint.getArgs())); baseLogMessage.setSpendTime((int) (endTime - startTime)); baseLogMessage.setStartTime(endTime); LOGGER.info("{}", JsonUtils.objectToJson(baseLogMessage)); // 數(shù)據(jù)庫存儲(chǔ)操作 return result; } /** * 異常返回通知,用于攔截異常日志信息 連接點(diǎn)拋出異常后執(zhí)行 * * @param joinPoint 切入點(diǎn) * @param e 異常信息 */ @AfterThrowing(pointcut = "controllerLog()", throwing = "e") public void saveExceptionLog(JoinPoint joinPoint, Throwable e) { long startTime = System.currentTimeMillis(); if(null==kafkaClient){ kafkaClient = KafkaProducerClient.getInstance(systemPropetiesUtil.getKafkaHost()); // redisClient= RedisClient.getInstance(systemPropetiesUtil.getReidsHost(), Integer.parseInt(systemPropetiesUtil.getRedisPort()), ""); } // 獲取RequestAttributes RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes(); // 從獲取RequestAttributes中獲取HttpServletRequest的信息 HttpServletRequest request = (HttpServletRequest) requestAttributes .resolveReference(RequestAttributes.REFERENCE_REQUEST); String urlStr = request.getRequestURL().toString(); BaseLogMessage baseLogMessage = new BaseLogMessage(); Signature signature = joinPoint.getSignature(); MethodSignature methodSignature = (MethodSignature) signature; Method method = methodSignature.getMethod(); StringBuffer strbuff = new StringBuffer(); for (StackTraceElement stet : elements) { strbuff.append(stet + "\n"); } String message = exceptionName + ":" + exceptionMessage + strbuff.toString(); try { Object[] args = joinPoint.getArgs(); String[] parameterNames = methodSignature.getParameterNames(); long endTime = System.currentTimeMillis(); baseLogMessage.setUri(urlStr); baseLogMessage.setType("異常日志"); baseLogMessage.setServerIP(getRemoteIP(request)); baseLogMessage.setMethod(request.getMethod()); baseLogMessage.setAppName(systemPropetiesUtil.getSysName()); baseLogMessage.setResult(message); baseLogMessage.setParameter(getParameter(method, joinPoint.getArgs())); baseLogMessage.setSpendTime((int) (endTime - startTime)); baseLogMessage.setStartTime(endTime); LOGGER.info("{}", JsonUtils.objectToJson(baseLogMessage)); // 數(shù)據(jù)庫存儲(chǔ)操作 } catch (Exception e2) { e2.printStackTrace(); } } /** * 根據(jù)方法和傳入的參數(shù)獲取請求參數(shù) */ private Object getParameter(Method method, Object[] args) { List<Object> argList = new ArrayList<>(); Parameter[] parameters = method.getParameters(); for (int i = 0; i < parameters.length; i++) { RequestBody requestBody = parameters[i].getAnnotation(RequestBody.class); if (requestBody != null) { argList.add(args[i]); } RequestParam requestParam = parameters[i].getAnnotation(RequestParam.class); if (requestParam != null) { Map<String, Object> map = new HashMap<>(); String key = parameters[i].getName(); if (!StringUtils.isEmpty(requestParam.value())) { key = requestParam.value(); } map.put(key, args[i]); argList.add(map); } } if (argList.size() == 0) { return null; } else if (argList.size() == 1) { return argList.get(0); } else { return argList; } } /** * 獲取請求ip */ public static String getRemoteIP(HttpServletRequest request) { String ip =null; if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { ip = request.getHeader("X-Forwarded-For"); } if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { ip = request.getHeader("Proxy-Client-IP"); } if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { ip = request.getHeader("WL-Proxy-Client-IP"); } if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { ip = request.getRemoteAddr(); } if (ip != null) { //對于通過多個(gè)代理的情況,最后IP為客戶端真實(shí)IP,多個(gè)IP按照','分割 int position = ip.indexOf(","); if (position > 0) { ip = ip.substring(0, position); } } return ip; } }
五、 問題
1、如果方法正常執(zhí)行,不進(jìn)入AOP類,請檢查AOP的切點(diǎn)是否書寫正確。
看完上述內(nèi)容,是不是對Springboot接口項(xiàng)目使用AOP記錄日志的方法有進(jìn)一步的了解,如果還想學(xué)習(xí)更多內(nèi)容,歡迎關(guān)注億速云行業(yè)資訊頻道。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。