SpringBoot之使用AOP处理请求
AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。AOP是Spring框架中的一个重要内容,它通过对既有程序定义一个切入点,然后在其前后切入不同的执行内容,比如常见的有:打开数据库连接/关闭数据库连接、打开事务/关闭事务、记录日志等。基于AOP不会破坏原来程序逻辑,因此它可以很好的对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。
1、首先添加jpa 依赖包
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId> </dependency>
2、新建一个拦截类HttpAspect,直接可以创建@Aspect ,并使用@Aspect和@Component标注这个类:
具体代码注释,如下所示:
package com.wyt.demo; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.ProceedingJoinPoint; 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; @Aspect @Component public class HttpAspect { private final static Logger logger = LoggerFactory.getLogger(HttpAspect.class); /** * 1)execution(* *(..)) * //表示匹配所有方法 * 2)execution(public * com.wyt.demo.service.UserService.*(..)) * //表示匹配com.wyt.demo.server.UserService中所有的公有方法 * 3)execution(* com.wyt.demo.server..*.*(..)) * //表示匹配com.wyt.demo.server包及其子包下的所有方法 * @return */ @Pointcut("execution(* com.wyt.demo.HelloControll.*(..))") public void log() { } @Before("log()") public void doBefore(JoinPoint joinPoint) { logger.info("before"); // 拦截器中获取请求 只需要在方法体中使用以下方法 ServletRequestAttributes attributes =(ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); HttpServletRequest request = attributes.getRequest(); // 通过request获取url,ip等信息。 // url logger.info("url={}", request.getRequestURL()); // ip logger.info("ip={}", request.getRemoteAddr()); // method logger.info("method={}", request.getMethod()); // 类方法 logger.info("class_method={}", joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName()); // 参数 logger.info("args={}", joinPoint.getArgs()); } /** * @Around 表示包围一个函数,也就是可以在函数执行前做一些事情,也可以在函数执行后做一些事情, 也就是所谓的切点. * @param pjp * @return * @throws Throwable */ @Around("log()") public Object aroundMethod(ProceedingJoinPoint pjp) throws Throwable { Object ob = null; System.out.println(pjp.getSignature().getDeclaringType()); //通过pjp对象获取Signature对象,该对象封装了连接点的信息。比如通过getDeclaringType获取连接点所在类的 class对象 //getName获取连接点的名称即方法名。 logger.info("---------------------------"); pjp.proceed(); logger.info("---------------------------"); return ob; } @After("log()") public void doAfter() { logger.info("after"); } /** * 获取返回内容 * @param object */ @AfterReturning(returning = "object", pointcut = "log()") public void doAfterReturning(Object object) { logger.info("response={}", object.toString()); } /**************************************************************/ /** * @AfterThrowing 增强处理主要用于处理程序中未处理的异常。 * @param ex */ // 匹配包下所有类的所有方法的执行作为切入点 @AfterThrowing(throwing="ex" , pointcut="log()") // 声明ex时指定的类型会限制目标方法必须抛出指定类型的异常 // 此处将ex的类型声明为Throwable,意味着对目标方法抛出的异常不加限制 public void doRecoveryActions(Throwable ex) { logger.info("目标方法中抛出的异常:" + ex); logger.info("模拟Advice对异常的修复..."); } // 总结:AOP的AfterThrowing处理虽然可以对目标方法的异常进行处理,但这种处理与直接使用catch捕捉不同,catch捕捉意味着完全处理该异常, // 如果catch块中没有重新抛出新的异常,则该方法可能正常结束; // 而AfterThrowing处理虽然处理了该异常,但它不能完全处理异常,该异常依然会传播到上一级调用者,即JVM。 /*******************************************************************/ }
控制台打印:
切面方法说明
@Aspect 作用是把当前类标识为一个切面供容器读取
@Before 标识一个前置增强方法,相当于BeforeAdvice的功能
@AfterReturning 后置增强,相当于AfterReturningAdvice,方法退出时执行
@AfterThrowing 异常抛出增强,相当于ThrowsAdvice
@After final增强,不管是抛出异常或者正常退出都会执行
@Around 环绕增强,相当于MethodInterceptor