SpringBoot - AOP统一处理请求日志
什么是AOP
首先什么是面向切片编程,就指是把逻辑代码和处理琐碎事务的代码分离开,以便能够分离复杂度。
实际上也就是说,让不同的类设计不同的方法。这样代码就分散到一个个的类中去了。这样做的好处是降低了代码的复杂程度,使类可重用。
但是人们也发现,在分散代码的同时,也增加了代码的重复性。什么意思呢?比如说,我们在两个类中,可能都需要在每个方法中做日志。按面向对象的设计方法,我们就必须在两个类的方法中都加入日志的内容。也许他们是完全相同的,但就是因为面向对象的设计让类与类之间无法联系,而不能将这些重复的代码统一起来。
也许有人会说,那好办啊,我们可以将这段代码写在一个独立的类独立的方法里,然后再在这两个类中调用。但是,这样一来,这两个类跟我们上面提到的独立的类就有耦合了,它的改变会影响这两个类。那么,有没有什么办法,能让我们在需要的时候,随意地加入代码呢?这种在运行时,动态地将代码切入到类的指定方法、指定位置上的编程思想就是面向切面的编程。
举个例子:先假设你有一段逻辑代码要写~ 在这段代码之前要写log;代码完成之后要写log。结局就是一大堆的log代码就淹没了逻辑代码。aop的想法就是将非逻辑部分的代码抽离出来,只考虑逻辑代码就行了,我把框框画好,这里写前面的log,这里写逻辑,这里写后面的log。
这里我们就用AOP来统一记录请求日志。
maven依赖
<!--aop-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
建立处理类
比如我们要记录UserController类所有方法的请求日志。
package cn.notemi.aspect;
import com.sun.deploy.net.HttpRequest;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.*;
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;
import javax.servlet.http.HttpServletRequest;
/**
* Title:HttpAspect
* Description:AOP HTTP 请求
*
* @author Flicker
* @create 2017-08-03 下午 11:20
**/
@Aspect
@Component
public class HttpAspect {
private final static Logger logger = LoggerFactory.getLogger(HttpAspect.class);
@Pointcut("execution(public * cn.notemi.controller.UserController.*(..))")
public void log(){
}
//方法前执行
@Before("log()")
public void doBefore(JoinPoint joinPoint){
ServletRequestAttributes attribute = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = attribute.getRequest();
//url
logger.info("url={}",request.getRequestURI());
//method
logger.info("method={}",request.getMethod());
//ip
logger.info("ip={}",request.getRemoteAddr());
//类方法
logger.info("class_method={}",joinPoint.getSignature().getDeclaringTypeName()+ "."+joinPoint.getSignature().getName());
//参数
logger.info("args={}",joinPoint.getArgs());
}
//方法后执行
@After("log()")
public void doAfter(){
logger.info("2");
}
//获取请求结果
@AfterReturning(returning = "object" , pointcut = "log()")
public void doAfterReturing(Object object){
logger.info("response={}",object.toString());
}
}
@Pointcut是标识方法,execution(public * cn.notemi.controller.UserController.*(..))
就代表标识UserController下所有的方法。
是不是很简单呢?
AOP是spring重要的特性,还有IOC,如果不理解两者的话,spring的精髓你就没领悟到,所以推荐大家学习。