Log annotations and cache optimization for SpringBoot

This article has participated in the “Digitalstar Project” and won a creative gift package to challenge the creative incentive money

Log notes:

Regarding logging in SpringBoot, I wrote in a previous article:

Click to enter

This time through annotation +Aop way to achieve log output;

First we need to define an annotation class:

 @Target(ElementType.METHOD)
 @Retention(RetentionPolicy.RUNTIME)
 @Documented
 public @interface LogAnnotation {
     String module(a) default "";  / / module name
     String operation(a) default ""; / / the operation name
 }
Copy the code

Then define the pointcut:

 // Define the pointcut
 @Pointcut("@annotation(com.xbhog.springbootvueblog.common.aop.LogAnnotation)")
 public void logPointCut(a) {}Copy the code

In vernacular, the annotation is always the tangent point; More professional explanation words can be their own Baidu or Google;

With a pointcut, we need to implement notification events, which use wrap notification, which means both before and after enhancement.

 // Wrap around the processing stream before and after
 @Around("logPointCut()")
 public Object around(ProceedingJoinPoint point) throws Throwable {
     long beginTime = System.currentTimeMillis();
     // Execute method
     Object result = point.proceed();
     // Execution time (ms)
     long time = System.currentTimeMillis() - beginTime;
     // Save the log
     recordLog(point, time);
     return result;
 }
Copy the code

Point.proceed () is the method that needs to be executed under the annotation; Similar to the following code snippet:

 @logannotation (module = "listArticle", operation = "show home show data ")
 public Result listArticle(@RequestBody PageParams pageParams) {
     return articleService.listArticle(pageParams);
 }
Copy the code

Then we need to set up the recordLog, where we use reflection to get the corresponding class name and method name and other information.

 private void recordLog(ProceedingJoinPoint joinPoint, long time) {
     MethodSignature signature = (MethodSignature) joinPoint.getSignature();
     Method method = signature.getMethod();
     LogAnnotation logAnnotation = method.getAnnotation(LogAnnotation.class);
     log.info("=====================log start================================");
     log.info("module:{}",logAnnotation.module());
     log.info("operation:{}",logAnnotation.operation());
 ​
     // The method name of the request
     String className = joinPoint.getTarget().getClass().getName();
     String methodName = signature.getName();
     log.info("request method:{}",className + "." + methodName + "()");
 ​
     // Request parameters
     Object[] args = joinPoint.getArgs();
     String params = JSON.toJSONString(args[0]);
     log.info("params:{}",params);
 ​
     // Get request set IP address
     HttpServletRequest request = HttpContextUtils.getHttpServletRequest();
     log.info("ip:{}", IpUtils.getIpAddr(request));
 ​
 ​
     log.info("excute time : {} ms",time);
     log.info("=====================log end================================");
 }
Copy the code

In this way, the cut point and the cut surface have been completed. When using the method, you only need to add annotations directly above the method to obtain the log information corresponding to the method, so that when the online error can be directly located.

Cache optimization:

This is implemented in a specific project, and the process is generally similar to the above implementation, using annotations.

Why need to use a cache to improve the access efficiency of web content, because the memory read faster than the speed of the hard disk read much more, it is better to the user’s experience, but not all of the data in the cache, because memory is more expensive than disk and so on what data cache can make user equilibrium and server also requires a certain experience.

Cache comments:

 @Target({ElementType.METHOD})
 @Retention(RetentionPolicy.RUNTIME)
 @Documented
 public @interface Cache {
     long expire(a) default1 times 60 times 1000;  // Survival time
     String name(a) default "";  // The cache name
 }
Copy the code

This sets the lifetime and name of the data so that the data can be read in memory for a certain amount of time.

Let’s take a look at the AOP implementation of caching:

Let’s take a quick look at the process for surrounding notifications:

Get the class name and the method name, and then set two arrays, one to hold the parameter type and one to hold the parameter.

If params is not empty, encrypt the current string parameter, save the current encrypted password in Redis, and check whether RedisValue is empty every time you enter the section. If it is empty, The method below the annotation, if not empty, reads the data directly from Redis and displays it in the foreground.

Through logging Aop and caching Aop functional operations, the results are as follows:

The end:

If you see this or happen to help you, please click 👍 or ⭐ thank you;

There are mistakes, welcome to point out in the comments, the author will see the modification.