Source: https: //macrozheng.github.io/mall-learning/#/technology/aop_log
AOP
AOP is an abbreviation for Aspect Oriented Programming, meaning: Aspect Oriented Programming, dynamic agent program features a technology to achieve unity maintained by way of pre-compiled and run. AOP can use to isolate each part of the business logic such that the business logic to reduce the degree of coupling between the parts, improve the reusability of the program, while improving efficiency of development.
AOP related terms
Notification (Advice)
Notification section describes the work to be done and when. For example, we need to cut the log records call duration of each interface, you need to separately record the current time before and after the interface calls, and then taking the difference.
- Pre-notification (Before): call notification function before the target method invocation;
- After returning advice (After): call notification function after the target method call, do not care about the method returns the result;
- Return notification (AfterReturning): call notification function after the target method is successful;
- Exception notification (AfterThrowing): call notification function after the target method throws an exception;
- Around advice (Around): notification wrapped objective methods, behavior before and after the execution of the target method invocation custom.
A connection point (the JoinPoint)
Notification function is applied timing. For example, when an interface method is called it is to cut logs of connection points.
Tangent point (Pointcut)
Cut points define a range notification function is applied. Applications such as the log is cut all the interfaces, i.e., all the interface method of the controller layer.
Section (Aspect)
And the notification section is a combination of cut points that define when and where to apply notifications.
Introduction (Introduction)
In the case of existing classes without modification, or add a new method to an existing class attributes.
Weaving (Weaving)
The cut to the target object and create a new proxy object of the process.
Spring annotation is used to create a section
Related Notes
- @Aspect: used to define the section
- @Before: notification method will be executed before the target method invocation
- @After: notification method will be executed after the target method returns or throws an exception
- @AfterReturning: notification method will be executed after the target method returns
- @AfterThrowing: notification method after the execution of the target method throws an exception
- @Around: notification method will encapsulate the target method
- @Pointcut: Expressions defined cut point
Cut point expression
Specifies the scope of the notification to be applied, the expression format:
execution (Method modifier return packet belongs to the type of method. class name. Method name (parameter method)
// com.macro.mall.tiny.controller package for all classes public methods are applied in section notify Execution ( public * com.macro.mall.tiny.controller. *. * (..)) // COM. All methods macro.mall.tiny.service the package and its sub-classes for all packets are cut in the notification application Execution (com.macro.mall.tiny.service .. * *. * (..)) // COM All methods are applied .macro.mall.tiny.service.PmsBrandService class section in the notification execution (* com.macro.mall.tiny.service.PmsBrandService. * (.. ))
Add AOP section implements the interface logging
Adding the log information package type WebLog
Package for log information to be recorded, including description of the operation, time, elapsed time, url, request parameters and return result information.
Package com.xc.mall2.dto; Import lombok.Getter; Import lombok.Setter; Import lombok.ToString; / ** * log encapsulation layer based Controller * XC ON by the Created 190903. * / @Getter @Setter @ToString public class WebLog { / ** * operation description * / Private String description; / ** * operation user * / Private String username; / ** * operation time * / Private Long the startTime; / ** * elapsed time * / Private Integer spendTime ; / ** * root * / Private String the basePath; / ** * the URI * / Private String URI; / ** * the URL * / Private String URL; / ** * request type * / Private String Method; / ** * IP address * / Private String IP; / ** * request parameter * / Private Object parameter; / ** * returns the result of the request of * / Private Object result; }
Add cut class WebLogAspect
Section defines a log, the log information acquired in the surround require notification, the controller layer and applied to all public methods to go.
package com.xc.mall2.component; import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.URLUtil; import cn.hutool.json.JSONUtil; import com.xc.mall2.dto.WebLog; import io.swagger.annotations.ApiOperation; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.Signature; import org.aspectj.lang.annotation.*; import org.aspectj.lang.reflect.MethodSignature; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; import org.springframework.util.StringUtils; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.ServletRequestAttributes; import javax.servlet.http.HttpServletRequest; import java.lang.reflect.Method; import java.lang.reflect.Parameter; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; /** * 统一日志处理切面 * Created by xc on 190903. */ @Aspect @Component @Order(1) public class WebLogAspect { private static final Logger LOGGER = LoggerFactory.getLogger(WebLogAspect.class); @Pointcut("execution(public * com.xc.mall2.controller.*.*(..))") public void webLog() { } @Before("webLog()") public void doBefore(JoinPoint joinPoint) throws Throwable { } @AfterReturning(value = "webLog()", returning = "ret") public void doAfterReturning(Object ret) throws Throwable { } @Around("webLog()") public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable { long startTime = System.currentTimeMillis(); //获取当前请求对象 ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); HttpServletRequest request = attributes.getRequest(); //记录请求信息 WebLog webLog = new WebLog(); Object result = joinPoint.proceed(); Signature signature = joinPoint.getSignature(); MethodSignature methodSignature = (MethodSignature) signature; Method method = methodSignature.getMethod(); if (method.isAnnotationPresent(ApiOperation.class)) { ApiOperation apiOperation = method.getAnnotation(ApiOperation.class); webLog.setDescription(apiOperation.value()); } long endTime = System.currentTimeMillis(); String urlStr = request.getRequestURL().toString(); webLog.setBasePath(StrUtil.removeSuffix(urlStr, URLUtil.url(urlStr).getPath())); webLog.setIp(request.getRemoteUser()); webLog.setMethod(request.getMethod()); webLog.setParameter(getParameter(method, joinPoint.getArgs())); webLog.setResult(result); webLog.setSpendTime((int) (endTime - startTime)); webLog.setStartTime(startTime); webLog.setUri(request.getRequestURI()); webLog.setUrl (request.getRequestURL () toString ().); logger.info ( "{}" , JSONUtil.parse (Weblog)); return Result; } / ** * acquisition request parameters and parameters passed according to the method * / Private Object the getParameter (Method, Method, Object [] args) { List <Object> = argList new new the ArrayList <> (); the Parameter [] Parameters = method.getParameters (); for ( int I = 0; I <Parameters. length; I ++ ) { // the modified annotation RequestBody parameters as a request parameter requestBody requestBody = parameters [I] .getAnnotation (requestBody. class ); IF ( ! requestBody = null ) { argList.add (args [I]); } // the modified annotation RequestParam parameters as a request parameter RequestParam requestParam = Parameters [I] .getAnnotation (RequestParam. Class ); IF (requestParam =! Null ) { the Map <String, Object> = Map new new the HashMap <> (); Key String = Parameters [I] .getName (); IF (! StringUtils.isEmpty(requestParam.value())) { Key = requestParam.value (); } map.put (Key, args [I]); argList.add (Map); } } IF (argList.size() == 0) { return null; } else if (argList.size() == 1) { return argList.get(0); } else { return argList; } } }
Interface Test:
2019-09-03 16:48:31.866 INFO 14208 --- [nio-8080-exec-2] com.xc.mall2.component.WebLogAspect : {"result":{"code":200,"data":{"total":11,"totalPage":11,"pageSize":1,"list":[{"productCommentCount":100,"name":"万和","bigPic":"","logo":"http://macro-oss.oss-cn-shenzhen.aliyuncs.com/mall/images/20180607/timg(5).jpg","showStatus":1,"id":1,"sort":0,"productCount":100,"firstLetter":"W","factoryStatus":1}],"pageNum":1},"message":"操作成功"},"basePath":"http://localhost:8080","method":"GET","ip":"test","parameter":[{"pageNum":1},{"pageSize":1}],"description":"分页查询品牌列表","startTime":1567500511861,"uri":"/brand/list","url":"http://localhost:8080/brand/list","spendTime":5}