Springboot接口项目如何使用AOP记录日志
一、背景
一直想给项目构建一个统一的日志收集系统,先迈出第一步,构建一个日志收集类,用AOP实现无侵入日志收集
二、环境
1.此随笔内容基于springboot项目
2.数据库为mysql5.7.9版本
3.jdk版本为1.8
三、说明
此版采用数据库存储,之后考虑使用elasticsearch等工具存储
四、内容
1、构建日志采集实体类:BaseLogMessage
publicclassBaseLogMessage{
privateStringserverIP;
privateStringappName;
privateStringmethod;
privateStringtype;
privateStringuserCode;
privateStringuri;
privateStringoperationName;
privateStringoperationStatus;
privatelongstartTime;
privateObjectparameter;
privateObjectresult;
privateintSpendTime;
//此处省略get、set
}
2、构建一个配置文件读取类,用于读取配置文件中的系统名称:SystemPropetiesUtil
@Configuration
publicclassSystemPropetiesUtil{
@Value("${spring.application.name}")
privateStringsysName;//系统名称
//此处省略get、set
}
3、新建一个AOP类,在控制器方法上作为切点,执行日志收集:LogAspect
@Aspect
@Component
publicclassLogAspect{
@Autowired
privateSystemPropetiesUtilsystemPropetiesUtil;
//定义切点方法
@Pointcut("execution(public*cq..campus.prevented.controller.*.*(..))")
publicvoidcontrollerLog(){
}
publicstaticfinalLoggerLOGGER=LoggerFactory.getLogger(LogAspect.class);
@Around("controllerLog()")
publicObjectdoAround(ProceedingJoinPointjoinPoint)throwsThrowable{
longstartTime=System.currentTimeMillis();
//获取当前请求对象
ServletRequestAttributesattributes=(ServletRequestAttributes)RequestContextHolder.getRequestAttributes();
HttpServletRequestrequest=attributes.getRequest();
//记录请求信息
BaseLogMessagebaseLogMessage=newBaseLogMessage();
//1.获取到所有的参数值的数组
Object[]args=joinPoint.getArgs();
Signaturesignature=joinPoint.getSignature();
MethodSignaturemethodSignature=(MethodSignature)signature;
//2.获取到方法的所有参数名称的字符串数组
String[]parameterNames=methodSignature.getParameterNames();
Objectresult=joinPoint.proceed();
Methodmethod=methodSignature.getMethod();
if(method.isAnnotationPresent(ApiOperation.class)){
ApiOperationapiOperation=method.getAnnotation(ApiOperation.class);
baseLogMessage.setOperationName(apiOperation.value());
}
longendTime=System.currentTimeMillis();
StringurlStr=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));
//数据库存储操作
returnresult;
}
/**
*异常返回通知,用于拦截异常日志信息连接点抛出异常后执行
*
*@paramjoinPoint切入点
*@parame异常信息
*/
@AfterThrowing(pointcut="controllerLog()",throwing="e")
publicvoidsaveExceptionLog(JoinPointjoinPoint,Throwablee){
longstartTime=System.currentTimeMillis();
if(null==kafkaClient){
kafkaClient=KafkaProducerClient.getInstance(systemPropetiesUtil.getKafkaHost());
//redisClient=RedisClient.getInstance(systemPropetiesUtil.getReidsHost(),Integer.parseInt(systemPropetiesUtil.getRedisPort()),"");
}
//获取RequestAttributes
RequestAttributesrequestAttributes=RequestContextHolder.getRequestAttributes();
//从获取RequestAttributes中获取HttpServletRequest的信息
HttpServletRequestrequest=(HttpServletRequest)requestAttributes
.resolveReference(RequestAttributes.REFERENCE_REQUEST);
StringurlStr=request.getRequestURL().toString();
BaseLogMessagebaseLogMessage=newBaseLogMessage();
Signaturesignature=joinPoint.getSignature();
MethodSignaturemethodSignature=(MethodSignature)signature;
Methodmethod=methodSignature.getMethod();
StringBufferstrbuff=newStringBuffer();
for(StackTraceElementstet:elements){
strbuff.append(stet+"\n");
}
Stringmessage=exceptionName+":"+exceptionMessage+strbuff.toString();
try{
Object[]args=joinPoint.getArgs();
String[]parameterNames=methodSignature.getParameterNames();
longendTime=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));
//数据库存储操作
}catch(Exceptione2){
e2.printStackTrace();
}
}
/**
*根据方法和传入的参数获取请求参数
*/
privateObjectgetParameter(Methodmethod,Object[]args){
List
五、问题
1、如果方法正常执行,不进入AOP类,请检查AOP的切点是否书写正确。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。