1.记录日志
使用aop来记录controller中的请求返回日志
pom.xml引入:
org.springframework.boot spring-boot-starter-aop
在完成了引入AOP依赖包后,一般来说并不需要去做其他配置。也许在Spring中使用过注解配置方式的人会问是否需要在程序主类中增加@EnableAspectJAutoProxy来启用,实际并不需要。
可以看下面关于AOP的默认配置属性,其中spring.aop.auto属性默认是开启的,也就是说只要引入了AOP依赖后,默认已经增加了@EnableAspectJAutoProxy。
# AOP spring.aop.auto=true # Add @EnableAspectJAutoProxy. spring.aop.proxy-target-class=false # Whether subclass-based (CGLIB) proxies are to be created (true) as opposed to standard Java interface-based proxies (false).
1.使用Around
@Aspect @Component public class ControllerAspect { private Logger logger = LoggerFactory.getLogger(getClass()); /** * Controller aspect. */ @Pointcut("execution(* com.shitou.huishi.service..*.*(..))") public void controllerAspect() { } /** * Around 手动控制调用核心业务逻辑,以及调用前和调用后的处理, ** 注意:当核心业务抛异常后,立即退出,转向AfterAdvice 执行完AfterAdvice,再转到ThrowingAdvice * * @param pjp * the pjp * @return object * @throws Throwable * the throwable
*/ @Around(value = "controllerAspect()") public Object aroundAdvice(ProceedingJoinPoint pjp) throws Throwable { RequestAttributes ra = RequestContextHolder.getRequestAttributes(); ServletRequestAttributes sra = (ServletRequestAttributes) ra; HttpServletRequest request = sra.getRequest(); logger.info("URL : " + request.getRequestURL().toString()); logger.info("HTTP_METHOD : " + request.getMethod()); logger.info("IP : " + request.getRemoteAddr()); logger.info("CLASS_METHOD : " + pjp.getSignature().getDeclaringTypeName() + "." + pjp.getSignature().getName()); logger.info("REQUEST ARGS : " + JSON.toJSONString(pjp.getArgs())); long startTime = System.currentTimeMillis(); try { Object response = pjp.proceed(); // 2.打印出参,返回结果 long endTime = System.currentTimeMillis(); // 3.出参打印 logger.info("RESPONSE:{}", response != null ? JSON.toJSONString(response) : ""); logger.info("SPEND TIME : {}ms", (endTime - startTime)); return response; } catch (AuthException e) { logger.info("RESPONSE ERROR:{}", e.getMsg()); throw e; } catch (HuishiApiException e) { logger.info("RESPONSE ERROR:{}", e.getMsg()); throw e; } catch (MethodArgumentNotValidException e) { logger.info("RESPONSE ERROR:{}", e.getMessage()); throw e; } catch (Throwable e) { logger.error("RESPONSE ERROR:{}", Arrays.toString(e.getStackTrace())); throw e; } finally { long endTime = System.currentTimeMillis(); logger.error("SPEND TIME : {}ms", (endTime - startTime)); } } }
2.使用Before,AfterReturning处理:
import java.util.Arrays; import javax.servlet.http.HttpServletRequest; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.annotation.AfterReturning; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.aspectj.lang.annotation.Pointcut; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Component; import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.ServletRequestAttributes; /** * Created by qhong on 2018/5/28 14:25 **/ @Aspect @Component public class LogAspect { private Logger logger = LoggerFactory.getLogger(getClass()); ThreadLocalstartTime = new ThreadLocal<>(); @Pointcut("execution(public * com.shitou.huishi.service.*.*(..))") public void logAspect(){} @Before("logAspect()") public void doBefore(JoinPoint joinPoint) throws Throwable { startTime.set(System.currentTimeMillis()); // 接收到请求,记录请求内容 ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); HttpServletRequest request = attributes.getRequest(); // 记录下请求内容 logger.info("URL : " + request.getRequestURL().toString()); logger.info("HTTP_METHOD : " + request.getMethod()); logger.info("IP : " + request.getRemoteAddr()); logger.info("CLASS_METHOD : " + joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName()); logger.info("ARGS : " + Arrays.toString(joinPoint.getArgs())); } @AfterReturning(returning = "ret", pointcut = "logAspect()") public void doAfterReturning(Object ret) throws Throwable { // 处理完请求,返回内容 logger.info("RESPONSE : " + ret); logger.info("SPEND TIME : " + (System.currentTimeMillis() - startTime.get())); } }
两种方式计算出来的时间,参数,返回体是一样的。
完善版本:
import com.alibaba.fastjson.JSON; import com.shitou.huishi.contract.datacontract.exception.AuthException; import com.shitou.huishi.contract.datacontract.exception.HuishiApiException; import java.util.Arrays; import javax.servlet.http.HttpServletRequest; 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.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Component; import org.springframework.web.bind.MethodArgumentNotValidException; import org.springframework.web.context.request.RequestAttributes; import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.ServletRequestAttributes; /** * 类描述: 日志拦截器,打印controller层的入参和出参
创建时间: 2016/7/29 0029
* * @author 李恒 */ @Aspect @Component public class ControllerAspect { private Logger logger = LoggerFactory.getLogger(getClass()); /** * Controller aspect. */ @Pointcut("execution(* com.shitou.huishi.service..*.*(..))") public void controllerAspect() { } /** * Around 手动控制调用核心业务逻辑,以及调用前和调用后的处理, ** 注意:当核心业务抛异常后,立即退出,转向AfterAdvice 执行完AfterAdvice,再转到ThrowingAdvice * * @param pjp the pjp * @return object * @throws Throwable the throwable
*/ @Around(value = "controllerAspect()") public Object aroundAdvice(ProceedingJoinPoint pjp) throws Throwable { RequestAttributes ra = RequestContextHolder.getRequestAttributes(); ServletRequestAttributes sra = (ServletRequestAttributes) ra; //防止不是http请求的方法,例如:scheduled if (ra == null || sra == null) { return pjp.proceed(); } HttpServletRequest request = sra.getRequest(); logger.info("URL : " + request.getRequestURL().toString()); logger.info("HTTP_METHOD : " + request.getMethod()); logger.info("IP : " + request.getRemoteAddr()); logger.info("CLASS_METHOD : " + pjp.getSignature().getDeclaringTypeName() + "." + pjp.getSignature().getName()); logger.info("REQUEST ARGS : " + JSON.toJSONString(pjp.getArgs())); long startTime = System.currentTimeMillis(); try { Object response = pjp.proceed(); // 3.出参打印 logger.info("RESPONSE:{}", response != null ? JSON.toJSONString(response) : ""); return response; } catch (Throwable e) { if (e instanceof AuthException) { logger.info("RESPONSE ERROR:{}", ((AuthException) e).getMsg()); } else if (e instanceof HuishiApiException) { logger.info("RESPONSE ERROR:{}", ((HuishiApiException) e).getMsg()); } else if (e instanceof MethodArgumentNotValidException) { logger.info("RESPONSE ERROR:{}", e.getMessage()); } else { logger.error("RESPONSE ERROR:{}", Arrays.toString(e.getStackTrace())); } throw e; } finally { long endTime = System.currentTimeMillis(); logger.info("SPEND TIME : {}ms", (endTime - startTime)); } } }
http://blog.didispace.com/springbootaoplog/
http://blog.didispace.com/springbootexception/