What does interface log do
In our daily development process, we can view some details of this interface through the interface log.For example, the IP of the client, the type of client, the response time, the type of request, the interface method of the request and so on, we can make statistical analysis on these data to extract the information we want.
How to get the interface log
Here, we use the AOP of Spring's two killers, define a tangent point at the Controller layer, then analyze the requesting object to get interface information, and open a ThreadLocal to record response time.
Notes on AOP
- @Aspect: Defines a class as a tangent class.
- @Pointcut: Define a starting point.
- @Before: Cut in at the beginning of the entry point.
- @After: Cut in at the end of the entry point.
- @AfterReturning: Entering content after the entry point returns content (which can be used to do some processing on processing the return value).
- @Around: Cut in before and after the entry point and control when to execute the entry point's own content
- @AfterThrowing: Used to handle handling logic after an exception is thrown in the cut-in content section.
- @Order: Operations before the entry point are performed from small to large by order value; operations after the entry point are performed from large to small by order value.
Practical application
One: Introducing dependency
First, we need to add a dependency that introduces aop, a UserAgentUtils package for analyzing client information, and a Lombook package for @Slf4j print logs:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId> </dependency> <dependency> <groupId>eu.bitwalker</groupId> <artifactId>UserAgentUtils</artifactId> <version>1.20</version> </dependency>
Two: Define a ResponseAop tangent class
This class has already been defined in the previous Unified Return Values and Exception Handling and is improved here.Let me rewrite the code here:
@Aspect @Order(5) @Component @Slf4j public class ResponseAop
Three: Define a ThreadLocal variable
Defining the base type directly here has synchronization problems, so we define a ThreadLocal object to record the time consumed.
ThreadLocal<Long> startTime = new ThreadLocal<>();
Four: Define the point of tangency
The point of tangency should be written correctly to ensure that AOP works!Here are some simple writings, followed by a separate chapter on execution expression writing.
- Any public method:
execution(public * *(..))
- Execution of any method starting with "set":
execution(* set*(..))
- Execution of any method of the Service interface:
execution(* com.xyz.service.Service.*(..))
- Execution of any method defined in the service package:
execution(* com.xyz.service.*.*(..))
- Execution of any method that defines any class in the service package and all subpackages:
execution(* com.xyz.service..*.*(..))
/** * Tangent Point */ @Pointcut("execution(public * indi.viyoung.viboot.*.controller..*(..))") public void httpResponse() { }
Five: Get request information in @Before
@Before("httpResponse()") public void doBefore(JoinPoint joinPoint){ //Start Timing startTime.set(System.currentTimeMillis()); ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); HttpServletRequest request = attributes.getRequest(); //Print the requested content UserAgent userAgent = UserAgent.parseUserAgentString(request.getHeader("User-Agent"));//Get User-Agent in Request Header log.info("Interface Path:{}" , request.getRequestURL().toString()); log.info("Browser:{}", userAgent.getBrowser().toString()); log.info("Browser version:{}",userAgent.getBrowserVersion()); log.info("operating system: {}", userAgent.getOperatingSystem().toString()); log.info("IP : {}" , request.getRemoteAddr()); log.info("Request type:{}", request.getMethod()); log.info("Class method : " + joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName()); log.info("Request parameters : {} " + Arrays.toString(joinPoint.getArgs())); }
Six: Get the return value and execution time of the method in @AfterReturning
@AfterReturning(returning = "ret" , pointcut = "httpResponse()") public void doAfterReturning(Object ret){ //Return content after processing the request log.info("Method return value:{}" , ret); log.info("Method execution time:{}Millisecond", (System.currentTimeMillis() - startTime.get())); }
Seven: Test results
Next, we access an interface:
2019-02-21 21:03:31.358 INFO 11788 --- [nio-8090-exec-5] indi.viyoung.viboot.aop.ResponseAop : Interface Path: http://localhost:8090/users 2019-02-21 21:03:31.359 INFO 11788 --- [nio-8090-exec-5] indi.viyoung.viboot.aop.ResponseAop : Browser: CHROME 2019-02-21 21:03:31.359 INFO 11788 --- [nio-8090-exec-5] indi.viyoung.viboot.aop.ResponseAop : Browser version: 72.0.3626.109 2019-02-21 21:03:31.360 INFO 11788 --- [nio-8090-exec-5] indi.viyoung.viboot.aop.ResponseAop : operating system: MAC_OS_X 2019-02-21 21:03:31.360 INFO 11788 --- [nio-8090-exec-5] indi.viyoung.viboot.aop.ResponseAop : IP : 0:0:0:0:0:0:0:1 2019-02-21 21:03:31.360 INFO 11788 --- [nio-8090-exec-5] indi.viyoung.viboot.aop.ResponseAop : Request type: GET 2019-02-21 21:03:31.360 INFO 11788 --- [nio-8090-exec-5] indi.viyoung.viboot.aop.ResponseAop : Class method : indi.viyoung.viboot.apilog.controller.UserController.findAll 2019-02-21 21:03:31.360 INFO 11788 --- [nio-8090-exec-5] indi.viyoung.viboot.aop.ResponseAop : Request parameters : {} [] ... 2019-02-21 21:03:31.393 INFO 11788 --- [nio-8090-exec-5] indi.viyoung.viboot.aop.ResponseAop : Method return value: ReturnVO{code='2000', message='Operation Successful', data=[User(id=10000001, password=123456, userName=vi-young), User(id=10000002, password=123456, userName=vi-young), User(id=10000003, password=123123, userName=lxt), User(id=10000004, password=123456, userName=yangwei)]} 2019-02-21 21:03:31.393 INFO 11788 --- [nio-8090-exec-5] indi.viyoung.viboot.aop.ResponseAop : Method execution time: 36ms
As you can see, we've got the information we want~
In future applications, we will save this information in the database and use some data analysis tools for analysis.
Public Number
Your recommendation is of great help to me!