We often need to record the operation of some important functions when we are doing projects, so as to track who is operating this function in the future; Exceptions may occur when we operate some functions, but we need to locate the reason for each exception. We have to go to the server to query the log, and we can't count the exceptions, so as to improve our project. It would be good if we could make a special function to record the operation log and exception log, Of course, we certainly have methods to do this, and it won't be difficult. We can add the code to record the log in the required methods and the code to record exceptions in each method, and finally save the recorded log to the database. It sounds easy, but when we do it, we will find that this work is very cumbersome, and we are doing some repetitive work and adding a lot of redundant code. It is certainly not feasible to record logs in this way.
We have learned the three major features of Spring, IOC (control inversion), DI (dependency injection) and AOP (aspect oriented). The main function of AOP is to separate the logging, performance statistics, security control, transaction processing, exception handling and other codes from the business logic code. Today, we'll use springBoot Aop for logging. Well, after a lot of nonsense, we'd better ship the goods.
1, Create a log table with the following structure:
Operation log table
Exception log table
2, Add Maven dependency
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId> </dependency>
3, Create operation log annotation class
import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * Custom action log annotation */ @Target(ElementType.METHOD) //Target location for annotation placement,METHOD It can be annotated at the method level @Retention(RetentionPolicy.RUNTIME) //At what stage do annotations execute @Documented public @interface OperLog { String operModul() default ""; // Operation module String operType() default ""; // Operation type String operDesc() default ""; // Operating instructions }
4, Create a section class to record the operation log
import java.lang.reflect.Method; import java.util.Date; import java.util.HashMap; import java.util.Map; import javax.servlet.http.HttpServletRequest; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.annotation.AfterReturning; import org.aspectj.lang.annotation.AfterThrowing; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Pointcut; import org.aspectj.lang.reflect.MethodSignature; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; import org.springframework.web.context.request.RequestAttributes; import org.springframework.web.context.request.RequestContextHolder; import com.gexin.fastjson.JSON; import com.hyd.zcar.cms.common.utils.IPUtil; import com.hyd.zcar.cms.common.utils.annotation.OperLog; import com.hyd.zcar.cms.common.utils.base.UuidUtil; import com.hyd.zcar.cms.common.utils.security.UserShiroUtil; import com.hyd.zcar.cms.entity.system.log.ExceptionLog; import com.hyd.zcar.cms.entity.system.log.OperationLog; import com.hyd.zcar.cms.service.system.log.ExceptionLogService; import com.hyd.zcar.cms.service.system.log.OperationLogService; /** * Section processing class, operation log, exception log record processing */ @Aspect @Component public class OperLogAspect { /** * Operation version number * <p> * When the project is started, it is passed from the command line, for example: java -jar xxx.war --version=201902 * </p> */ @Value("${version}") private String operVer; @Autowired private OperationLogService operationLogService; @Autowired private ExceptionLogService exceptionLogService; /** * Set the operation log entry point to record the entry code of the operation log at the annotation position */ @Pointcut("@annotation(com.hyd.zcar.cms.common.utils.annotation.OperLog)") public void operLogPoinCut() { } /** * Set the operation exception entry point, record the exception log, and scan all operations under the controller package */ @Pointcut("execution(* com.hyd.zcar.cms.controller..*.*(..))") public void operExceptionLogPoinCut() { } /** * It returns the notification normally, intercepts the user operation log, and executes after the normal execution of the connection point. If the connection point throws an exception, it will not execute * * @param joinPoint breakthrough point * @param keys Return results */ @AfterReturning(value = "operLogPoinCut()", returning = "keys") public void saveOperLog(JoinPoint joinPoint, Object keys) { // obtain RequestAttributes RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes(); // Get from RequestAttributes Get in HttpServletRequest Information about HttpServletRequest request = (HttpServletRequest) requestAttributes .resolveReference(RequestAttributes.REFERENCE_REQUEST); OperationLog operlog = new OperationLog(); try { operlog.setOperId(UuidUtil.get32UUID()); // Primary key ID // Method for obtaining weaving in point through reflection mechanism from cutting in point MethodSignature signature = (MethodSignature) joinPoint.getSignature(); // Get the method where the pointcut is located Method method = signature.getMethod(); // Get operation OperLog opLog = method.getAnnotation(OperLog.class); if (opLog != null) { String operModul = opLog.operModul(); String operType = opLog.operType(); String operDesc = opLog.operDesc(); operlog.setOperModul(operModul); // Operation module operlog.setOperType(operType); // Operation type operlog.setOperDesc(operDesc); // pedagogical operation } // Gets the requested class name String className = joinPoint.getTarget().getClass().getName(); // Gets the requested method name String methodName = method.getName(); methodName = className + "." + methodName; operlog.setOperMethod(methodName); // Request method // Requested parameters Map<String, String> rtnMap = converMap(request.getParameterMap()); // Convert the array of parameters to json String params = JSON.toJSONString(rtnMap); operlog.setOperRequParam(params); // Request parameters operlog.setOperRespParam(JSON.toJSONString(keys)); // Return results operlog.setOperUserId(UserShiroUtil.getCurrentUserLoginName()); // Request user ID operlog.setOperUserName(UserShiroUtil.getCurrentUserName()); // Request user name operlog.setOperIp(IPUtil.getRemortIP(request)); // request IP operlog.setOperUri(request.getRequestURI()); // request URI operlog.setOperCreateTime(new Date()); // Creation time operlog.setOperVer(operVer); // Operation version operationLogService.insert(operlog); } catch (Exception e) { e.printStackTrace(); } } /** * The exception return notification is used to intercept the exception log information and execute after the connection point throws an exception * * @param joinPoint breakthrough point * @param e Abnormal information */ @AfterThrowing(pointcut = "operExceptionLogPoinCut()", throwing = "e") public void saveExceptionLog(JoinPoint joinPoint, Throwable e) { // obtain RequestAttributes RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes(); // Get from RequestAttributes Get in HttpServletRequest Information about HttpServletRequest request = (HttpServletRequest) requestAttributes .resolveReference(RequestAttributes.REFERENCE_REQUEST); ExceptionLog excepLog = new ExceptionLog(); try { // Method for obtaining weaving in point through reflection mechanism from cutting in point MethodSignature signature = (MethodSignature) joinPoint.getSignature(); // Get the method where the pointcut is located Method method = signature.getMethod(); excepLog.setExcId(UuidUtil.get32UUID()); // Gets the requested class name String className = joinPoint.getTarget().getClass().getName(); // Gets the requested method name String methodName = method.getName(); methodName = className + "." + methodName; // Requested parameters Map<String, String> rtnMap = converMap(request.getParameterMap()); // Convert the array of parameters to json String params = JSON.toJSONString(rtnMap); excepLog.setExcRequParam(params); // Request parameters excepLog.setOperMethod(methodName); // Request method name excepLog.setExcName(e.getClass().getName()); // Exception name excepLog.setExcMessage(stackTraceToString(e.getClass().getName(), e.getMessage(), e.getStackTrace())); // Abnormal information excepLog.setOperUserId(UserShiroUtil.getCurrentUserLoginName()); // operator ID excepLog.setOperUserName(UserShiroUtil.getCurrentUserName()); // Operator name excepLog.setOperUri(request.getRequestURI()); // operation URI excepLog.setOperIp(IPUtil.getRemortIP(request)); // operator IP excepLog.setOperVer(operVer); // Operation version number excepLog.setOperCreateTime(new Date()); // Abnormal time exceptionLogService.insert(excepLog); } catch (Exception e2) { e2.printStackTrace(); } } /** * Transform request parameters * * @param paramMap request Gets the parameter array of the */ public Map<String, String> converMap(Map<String, String[]> paramMap) { Map<String, String> rtnMap = new HashMap<String, String>(); for (String key : paramMap.keySet()) { rtnMap.put(key, paramMap.get(key)[0]); } return rtnMap; } /** * Convert exception information to string * * @param exceptionName Exception name * @param exceptionMessage Abnormal information * @param elements Stack information */ public String stackTraceToString(String exceptionName, String exceptionMessage, StackTraceElement[] elements) { StringBuffer strbuff = new StringBuffer(); for (StackTraceElement stet : elements) { strbuff.append(stet + "\n"); } String message = exceptionName + ":" + exceptionMessage + "\n\t" + strbuff.toString(); return message; } }