“This is the 26th day of my participation in the Gwen Challenge in November. Check out the details: The Last Gwen Challenge in 2021.”

preface

In many background management systems, there are clear permissions and role control, and of course, operation log records. This article will develop a logging facility based on Spring’s AOP features. The entire development project is recorded below

Quick start

Using Spring’s AOP features, let’s first learn what AOP is. AOP in the application development process refers to section-oriented programming that implements program functionality through precompilation and dynamic proxies. AOP mainly includes pointcut, aspect, join point, target group, notification, weaving mode and so on. The common notification types include pre-notification, surround notification, and post-notification. The surround notification is generally used during logging. Specific AOP related concepts we are not familiar with can go to query.

Version information

This Spring Boot implements logging function based on AOP annotations, and the main version information is as follows:

Spring Boot 2.3.0.RELEASE
aspectjweaver 1.9.6
maven 3
Copy the code

The main dependency is AspectJweaver. If the Versions of AspectJWeaver and Spring Boot are different, exceptions such as failure to find pointcuts may be reported. You can replace the bit-related versions to solve the problem.

< the dependency > < groupId > org. Aspectj < / groupId > < artifactId > aspectjweaver < / artifactId > < version > 1.9.6 < / version > </dependency>Copy the code

Basic information

Operation logs are recorded in the database or search engine for easy query. Logs record the operator, operation time, request parameters, REQUEST IP address, request connection, and operation type. The SQL for creating a table in this example is as follows:

CREATE TABLE 'log_info' (' id 'int(11) NOT NULL AUTO_INCREMENT,' model 'vARCHar (255) DEFAULT NULL COMMENT' module ', 'log_type' tinyint(4) DEFAULT NULL COMMENT '0= other,1= new,2= modify,3= delete,4= grant,5= export,6= import,7= delete,8= login,9= delete,10 query ', 'url' varchar(255) DEFAULT NULL COMMENT 'request ',' method 'varchar(255) DEFAULT NULL COMMENT' request ', 'class_name' varchar(255) DEFAULT NULL COMMENT 'class id ',' class_name 'varchar(255) DEFAULT NULL COMMENT' method id ', 'params' varchar(500) DEFAULT NULL COMMENT' id ', 'IP' varchar(255) DEFAULT NULL COMMENT 'IP ', 'user_id' int(11) DEFAULT NULL COMMENT 'iD ',' user_name 'varchar(255) DEFAULT NULL COMMENT' iD ', 'sys_info' varchar(255) DEFAULT NULL COMMENT 'sys_info ', 'create_user' varchar(200) CHARACTER SET utf8 DEFAULT NULL COMMENT 'founder ', 'create_time' datetime DEFAULT NULL COMMENT 'create_time ', 'update_user' varchar(200) CHARACTER SET utf8 DEFAULT NULL COMMENT 'update_user' 'update_time' datetime DEFAULT NULL COMMENT 'update time ',' data_state 'tinyint(4) NOT NULL DEFAULT '1' COMMENT '0 deleted 1 undeleted ', PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4;Copy the code

This section divides the operation types into 11 log operations, including log login, log logout, add, delete, modify, query, import, export, and delete.

@getter @allargsconstructor Public enum LogTypeEnum {/** * 0= others,1= New,2= Modified,3= Deleted,4= Authorized,5= Exported,6= Imported,7= Forcible Back,8= Login,9= Empty data,10 Query * * / OTHER (0, "OTHER"), ADD (1, "new"), the UPDATE (2, "modify"), DEL (3, "delete"), the AUTH (4, "authorization"), the EXPORT (5, "EXPORT"), the IMPORT (6, "IMPORT"), the QUIT (7, "strong back"), GENERATE_CODE (8, "login"), the CLEAR (9, "empty"), the QUERY (10, "QUERY"),; @EnumValue private int value; private String desc; }Copy the code

The Log notes

Once the data is initialized, it is time to write a custom Log annotation. The annotations used this time are mainly annotations for methods. Details are as follows:

  • @target: The Target location of the annotation, including interface, class, enumeration, field, method, constructor, package, etc. It can be configured as required. The log uses this method-based annotation.
  • @Retention: The Retention of annotations, either in source code, in classes, or in runtime. This log operation record must be used in RUNTIME, so select RUNTIME.
  • Documented: A literal document stating that the annotation will be included in javadoc.
@target (ElementType.METHOD) @Retention(RetentionPolicy.runtime) @documented Public @interface Log {/** * module ** / String  model() default ""; /** * Operation ** / LogTypeEnum logType() default LogTypeEnum.OTHER; }Copy the code

LogAspect

Define the LogAspect aspect of a log. You need to use @aspect and @Component in the class to indicate that this is a section method that scans packages at run time. Note that you need to define aspects and notification types in this method. Finally, you can query the information required by operation logs based on the comments and request parameters. Since there is no need to log in to the direct interface request this time, the default values for operator and action ID are used in the demo. In this example, only some operation logs are extracted. You need to add many logs to the project and modify them as required.

@Aspect @Component public class LogAspect { @Resource private LogInfoMapper logInfoMapper; /** * @className logPointCut * @description: pointcut information * @author JavaZhan @public id :Java full stack architect * @version V1.0 **/ @Pointcut("@annotation(com.example.demo.log.Log)") public void logPointCut(){ } /** * @ClassName aroundForLog * @author JavaZhan @public id :Java full stack architect * @version V1.0 **/ @around ("logPointCut()") public Object aroundForLog(ProceedingJoinPoint point) throws Throwable { long beginTime = System.currentTimeMillis(); Object result = point.proceed(); saveSmsLog(point); return result; } /** * @ClassName saveLogInfo * @Description: * @author JavaZhan @public id :Java full Stack architect * @version V1.0 **/ private void saveLogInfo(ProceedingJoinPoint joinPoint) { MethodSignature signature = (MethodSignature) joinPoint.getSignature(); Method method = signature.getMethod(); LogInfo logInfo = new LogInfo(); logInfo.setClassName(joinPoint.getTarget().getClass().getName()); logInfo.setMethodName(signature.getName()); Log log = method.getAnnotation(Log.class); if(log ! = null){ logInfo.setModel(log.model()); logInfo.setLogType(log.logType().getValue()); } Object[] args = joinPoint.getArgs(); try{ String params = JSONObject.toJSONString(args); logInfo.setParams(params); }catch (Exception e){ } ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); HttpServletRequest request = servletRequestAttributes.getRequest(); logInfo.setIp(IpUtils.getIpAddr(request)); logInfo.setUrl(request.getServletPath()); logInfo.setMethod(request.getMethod()); logInfo.setUserId(123); logInfo.setUserName("admin"); logInfo.setCreateTime(new Date()); logInfo.setDataState(1); // Save the operation log loginfomapper. insert(logInfo); }}Copy the code

The test log

This example will test against commonly used interfaces. In the Controller method, we call custom annotations that specify the method’s model information and action type information based on what the method actually means to use.

@RequestMapping("user") @Controller public class UserController { @Resource private UserService userService; @requestMapping ("getAllUser") @responseBody @log (model = "QUERY User",logType = logTypeen.query) public List<User> getAllUser(){ return userService.getAllUser(); } @requestMapping ("getUserById") @responseBody @log (model = "getUserById",logType = LogTypeEnum.QUERY) public User getUserById(Integer id ){ return userService.getById(id); }}Copy the code

Call interface:http://127.0.0.1:8888/user/getAllUserThe returned data information is as follows.In the log table, you can see that a new log about the user list has been added.Access the other interfaces below:http://127.0.0.1:8888/user/getUserById?id=1The returned data information is as follows.

In the log table, you can see that a new log information about the specified user has been obtained.

conclusion

Well, the above is Spring Boot based on AOP annotations to achieve the logging function of the example, thank you for reading, I hope you like, if it is helpful to you, welcome to like favorites. If there are shortcomings, welcome comments and corrections. See you next time.

About the author: [Little Ajie] a love tinkering with the program ape, JAVA developers and enthusiasts. Public number [Java full stack architect] maintainer, welcome to pay attention to reading communication.