最近有个新需求,是对用户的某些操作进行监控,操作记录要写入数据库,首先想到了使用Filter过滤器和Spring的Interceptor(拦截器),这两种都需要复杂的配置(能用代码解决的问题绝不上手),于是灵机一动想到了基于注解实现AOP,在要进行监控的Action加上该注解,完美,开始!
package com.asiainfo.annotation; import java.lang.annotation.*; /** * @description: 自动以注解 * @author: Mr-box * @create: 2019-05-23 10:00 **/ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) @Documented public @interface EagleEye { String desc() default ""; } 复制代码
package com.asiainfo.aspect; 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.springframework.stereotype.Component; import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.ServletRequestAttributes; import javax.servlet.http.HttpServletRequest; import java.util.Arrays; /** * @description: 定义AOP切面 * @author: Mr-box * @create: 2019-05-23 10:00 **/ @Aspect @Component public class LogAspect { // 定义切点 @Pointcut("@annotation(com.asiainfo.annotation.EagleEye)") public void eagleEye() { } // 利用环绕增强来实现我们的功能 @Around("eagleEye()") public Object surroundInform(ProceedingJoinPoint proceedingJoinPoint) { System.out.println("环绕通知开始..."); ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); HttpServletRequest request = attributes.getRequest(); System.out.println("请求路径 : " + request.getRequestURL()); System.out.println("请求方式 : " + request.getMethod()); System.out.println("方法名 : " + proceedingJoinPoint.getSignature().getName()); System.out.println("类路径 : " + proceedingJoinPoint.getSignature().getDeclaringTypeName()); System.out.println("参数 : " + Arrays.toString(proceedingJoinPoint.getArgs())); try { // 真实业务代码,这里是伪代码 Object o = proceedingJoinPoint.proceed(); System.out.println("方法环绕proceed,结果是 :" + o); return o; } catch (Throwable e) { e.printStackTrace(); return null; } } } 复制代码
package com.asiainfo.action; import com.asiainfo.annotation.EagleEye; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; /** * @description: 定义AOP切面 * @author: Mr-box * @create: 2019-05-23 10:00 **/ @RestController public class TestAction { @EagleEye(desc = "测试接口") @RequestMapping(value = "/sayHello") public String test(String params)throws Exception{ System.out.println("参数:" + params); return "hello "+ params; } } 复制代码
浏览器调用: http://127.0.0.1:8081/aop-demo/sayHello?params=lala 观察日志输出:
. ____ _ __ _ _ /// / ___'_ __ _ _(_)_ __ __ _ / / / / ( ( )/___ | '_ | '_| | '_ // _` | / / / / /// ___)| |_)| | | | | || (_| | ) ) ) ) ' |____| .__|_| |_|_| |_/__, | / / / / =========|_|==============|___/=/_/_/_/ :: Spring Boot :: (v2.2.5.RELEASE) 2019-05-23 10:00 INFO 3183 --- [ main] com.asiainfo.SpringAopDemoApplication : Starting SpringAopDemoApplication on zhangdsdeiMac.local with PID 3183 (/Users/zhangds/Development/code/spring-aop-demo/target/classes started by zhangds in /Users/zhangds/Development/code/spring-aop-demo) 2019-05-23 10:00 INFO 3183 --- [ main] com.asiainfo.SpringAopDemoApplication : No active profile set, falling back to default profiles: default 2019-05-23 10:00 INFO 3183 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 8081 (http) 2019-05-23 10:00 INFO 3183 --- [ main] o.apache.catalina.core.StandardService : Starting service [Tomcat] 2019-05-23 10:00 INFO 3183 --- [ main] org.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/9.0.31] 2019-05-23 10:00 INFO 3183 --- [ main] o.a.c.c.C.[.[localhost].[/aop-demo] : Initializing Spring embedded WebApplicationContext 2019-05-23 10:00 INFO 3183 --- [ main] o.s.web.context.ContextLoader : Root WebApplicationContext: initialization completed in 627 ms 2019-05-23 10:00 INFO 3183 --- [ main] o.s.s.concurrent.ThreadPoolTaskExecutor : Initializing ExecutorService 'applicationTaskExecutor' 2019-05-23 10:00 INFO 3183 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8081 (http) with context path '/aop-demo' 2019-05-23 10:00 INFO 3183 --- [ main] com.asiainfo.SpringAopDemoApplication : Started SpringAopDemoApplication in 1.115 seconds (JVM running for 1.654) 2019-05-23 10:00 INFO 3183 --- [nio-8081-exec-1] o.a.c.c.C.[.[localhost].[/aop-demo] : Initializing Spring DispatcherServlet 'dispatcherServlet' 2019-05-23 10:00 INFO 3183 --- [nio-8081-exec-1] o.s.web.servlet.DispatcherServlet : Initializing Servlet 'dispatcherServlet' 2019-05-23 10:00 INFO 3183 --- [nio-8081-exec-1] o.s.web.servlet.DispatcherServlet : Completed initialization in 4 ms 请求路径 : http://127.0.0.1:8081/aop-demo/sayHello 请求方式 : GET 方法名 : test 类路径 : com.asiainfo.action.TestAction 参数 : [lala] 环绕通知开始... 参数:lala 方法环绕proceed,结果是 :hello lala 复制代码