Welcome to pay attention to personal wechat public number: Ha learning Java, the end of the article to share “Java core knowledge collation & interview. PDF” resource link!!
Personal website: www.exception.site/springboot/…
In fact, Ha has published a previous article on how to uniformly print request logs using AOP facets, so why do you want to publish another? Run out of stuff to write?
Ha ha, of course not! The reason is that there are still defects in the implementation scheme at that time. The reasons are as follows:
- It’s not flexible enough, because it cuts to all the Controller methods, that is, it cuts to death, and if we don’t want an interface to print the entry log, we can’t do it;
- If the Controller package level is too deep, the interfaces of many packages cannot be cut off.
Today we will focus on how to use custom annotations in Spring Boot to uniformly print entry and entry logs for AOP facets. Friends can collect a wave.
Without further ado, let’s get to the point!
directory
First, take a look at the output effect of section log
Add AOP Maven dependencies
Custom log annotations
Configure the AOP aspect
Five, how to use it?
Does it work well for file uploading?
7. Only want to use in development environment and test environment?
Eight, how to specify the priority of multi-slice?
First, take a look at the output effect of section log
Before taking a look at the implementation, let’s take a look at the output effect of the section log:
As you can see from the figure above, each request has a clear start and end, and the following parameters are printed:
- URL: request interface address.
- Description: Indicates the Chinese Description of the interface.
- HTTP Method: Request method, yes
POST
.GET
, orDELETE
And so on; - Class Method: Method path: package name + Method name;
- IP: IP address of the requester.
- Request Args: The input parameter of the Request is output in JSON format.
- Response Args: The Response parameter is output in JSON format.
- Time-consuming: Indicates the Time consumed by the request to estimate the performance index of each interface.
How’s that? It looks good, doesn’t it? Now let’s see, how do we implement this step by step?
Add AOP Maven dependencies
Add dependencies to the project pom.xml file:
<! -- AOP dependencies -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<! Print entry and exit parameters in JSON format -->
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.8.5</version>
</dependency>
Copy the code
Custom log annotations
Let’s customize a log annotation like this:
- When to use this annotation, we define it as runtime.
- ② where annotations are used, we define them as acting on methods.
- ③ Whether annotations will be included in JavaDoc;
- (4)Note name:
WebLog
; - ⑤ : Define an attribute, default is empty string;
Source code is as follows:
package site.exception.springbootaopwebrequest.aspect;
import java.lang.annotation.*;
/ * * *@authorDog Ha (wechat id: Ha learning Java) *@site www.exception.site
* @date 2019/2/12
* @timeOn the afternoon of 4 *@discription* * /
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
@Documented
public @interface WebLog {
/** * Log description **@return* /
String description(a) default "";
}
Copy the code
At this point, a complete custom annotation definition is complete.
Configure the AOP aspect
Before configuring an AOP aspect, we need to understand the role of AspectJ-related annotations:
- @aspect: Declare this class as an annotation class;
- Pointcut: defines a Pointcut followed by an expression that can be defined to cut an annotation or a method under a package;
After the pointcut is defined, it is around this pointcut:
- Before: Before the pointcut, weave in the relevant code;
- @after: After the pointcut, weave the relevant code;
- AfterReturning: AfterReturning from the cut point, weave related code, generally used to do some processing on the returned value of the scene;
- AfterThrowing: handles logic handling when an exception is thrown by the woven code;
- @around: Around, which allows you to weave code Around pointcuts and control when pointcuts are executed.
Next, define a WebLogAspes.java aspect class and declare a pointcut:
Then, define the @around surround for when to execute the pointcut:
- ① : Record the start time of calling the interface;
- (2) Before -> interface logic code -> @after -> @afterreturning;
- ③ : print out the parameter;
- (4) : printing interface processing time;
- ⑤ : Returns the return parameter result of the interface.
Look again at the @before method:
See annotation function description, because annotation says still quite clear!
And finally, to wrap things up with @after:
We print the end-of-log flag at the end of each interface. Finally, take a look at the project package structure:
At this point, the section-related code is complete!
Complete code:
package site.exception.springbootaopwebrequest.aspect;
import com.google.gson.Gson;
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.context.annotation.Profile;
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.lang.reflect.Method;
/ * * *@authorDog Ha (wechat id: Ha learning Java) *@site www.exception.site
* @date 2019/2/12
* @timeOn the afternoon of 4 *@discription* * /
@Aspect
@Component
@Profile({"dev"."test"})
public class WebLogAspect {
private final static Logger logger = LoggerFactory.getLogger(WebLogAspect.class);
/** newline */
private static final String LINE_SEPARATOR = System.lineSeparator();
/** To customize@WebLogAnnotated as pointcut */
@Pointcut("@annotation(site.exception.springbootaopwebrequest.aspect.WebLog)")
public void webLog(a) {}
/** ** is woven into * before the pointcut@param joinPoint
* @throws Throwable
*/
@Before("webLog()")
public void doBefore(JoinPoint joinPoint) throws Throwable {
// Start printing the request log
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = attributes.getRequest();
// Get the description of the @weblog annotation
String methodDescription = getAspectLogDescription(joinPoint);
// Prints request parameters
logger.info("========================================== Start ==========================================");
// Prints the request URL
logger.info("URL : {}", request.getRequestURL().toString());
// Prints description information
logger.info("Description : {}", methodDescription);
// Prints Http method
logger.info("HTTP Method : {}", request.getMethod());
// Prints the full path to the controller call and the execution method
logger.info("Class Method : {}.{}", joinPoint.getSignature().getDeclaringTypeName(), joinPoint.getSignature().getName());
// Prints the requested IP
logger.info("IP : {}", request.getRemoteAddr());
// Prints the request entry parameter
logger.info("Request Args : {}".new Gson().toJson(joinPoint.getArgs()));
}
/** * is woven into * after the pointcut@throws Throwable
*/
@After("webLog()")
public void doAfter(a) throws Throwable {
// The interface ends with a line break for easy viewing
logger.info("=========================================== End ===========================================" + LINE_SEPARATOR);
}
/** * surround *@param proceedingJoinPoint
* @return
* @throws Throwable
*/
@Around("webLog()")
public Object doAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
long startTime = System.currentTimeMillis();
Object result = proceedingJoinPoint.proceed();
// Print out the parameter
logger.info("Response Args : {}".new Gson().toJson(result));
// Execution time
logger.info("Time-Consuming : {} ms", System.currentTimeMillis() - startTime);
return result;
}
/** * Get the description of the section annotation **@paramJoinPoint tangent point *@returnDescription@throws Exception
*/
public String getAspectLogDescription(JoinPoint joinPoint)
throws Exception {
String targetName = joinPoint.getTarget().getClass().getName();
String methodName = joinPoint.getSignature().getName();
Object[] arguments = joinPoint.getArgs();
Class targetClass = Class.forName(targetName);
Method[] methods = targetClass.getMethods();
StringBuilder description = new StringBuilder("");
for (Method method : methods) {
if (method.getName().equals(methodName)) {
Class[] clazzs = method.getParameterTypes();
if (clazzs.length == arguments.length) {
description.append(method.getAnnotation(WebLog.class).description());
break; }}}returndescription.toString(); }}Copy the code
Five, how to use it?
Since our pointcut is the custom @weblog annotation, we just need to add @weblog annotation to each interface method of the Controller Controller. If we don’t want an interface to print the entry log, we don’t need to add annotation:
Does it work well for file uploading?
It works! The section log works fine for both single-file and multi-file uploads, but I don’t want to post what I’m testing here. Interested partners can try!
7. Only want to use in development environment and test environment?
What about applications with high performance requirements that do not want to print logs in production but only want to use them in development or test environments? We simply add @profile to the slice, as shown below:
This specifies that prod only works in dev and test environments. Prod does not work in production.
Eight, how to specify the priority of multi-slice?
Let’s say we have more than one aspect defined in our service, such as our interface to the Web layer, not only to print logs, but also to verify tokens, etc. How do you specify the priority of an aspect? How do you specify the order in which the slices are executed?
We can specify the priority with the @order (I) annotation. Note that the lower the value of I, the higher the priority.
If we define the log aspect as @order (10) and then we define the token aspect checkTokenAspect.java as @order (11), then the execution Order between them is as follows:
We can sum it up:
- Before I cut to the point,
@Order
Is executed from small to large, that is, the smaller the priority is higher; - After the tangent point,
@Order
It is executed from large to small, that is, the larger the priority is higher;
Nine, Ref
Blog.didispace.com/springboota…
GitHub source code address
Github.com/weiwosuoai/…
Gifts | interview & learning welfare resources
Recently found a good PDF resource on the Internet “Java core knowledge & interview. PDF” to share with you, not only interview, learning, you are worth it!!
Access: pay attention to the public number: xiahaxuejava, background reply resources, both free access to resources without routine links, the following is the directory and some screenshots:
Important things to say twice, pay attention to the public number: small ha learning Java, background reply resources, both free no routine access to resources links!!