1. 程式人生 > >SpringBoot通過AOP儲存操作日誌

SpringBoot通過AOP儲存操作日誌

專案中的一些重要操作需要記錄操作日誌,以便於以後操作出問題進行追蹤是誰操作引起的。

pom.xml引入AOP依賴

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

<!-- aop -->
<dependency>
    <groupId>org.springframework.boot</groupId
>
<artifactId>spring-boot-starter-aop</artifactId> </dependency>

在controller層新增攔截操作日誌

@Target({ElementType.PARAMETER, ElementType.METHOD})    
@Retention(RetentionPolicy.RUNTIME)    
@Documented
public @interface SystemControllerLog {
    String description()  default "";
    String type() default
"b"; }
package com.rzg.dgztc.mall.manage.aop;

import com.rzg.dgztc.mall.manage.domain.PartnerLogisticsBean;
import com.rzg.dgztc.mall.manage.service.MallOptLogService;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj
.lang.annotation.Pointcut; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; 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; @Aspect @Component public class SystemLogAspect { private static final Logger log = LoggerFactory.getLogger(SystemLogAspect.class); @Autowired private MallOptLogService logService; // controller層切點 @Pointcut("@annotation(com.rzg.dgztc.mall.manage.aop.SystemControllerLog)") public void serviceAspect() {} @Before("serviceAspect()") public void doServiceBefore(JoinPoint joinPoint) { HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); //請求的IP String ip = request.getRemoteAddr(); //請求的引數 String param = getParam(joinPoint); //請求的引數 String methodName = (joinPoint.getTarget().getClass().getName() + "." + joinPoint.getSignature().getName() + "()"); log.info("=====Service前置通知開始,方法:" + methodName + "======="); log.info("請求方法:" + (joinPoint.getTarget().getClass().getName() + "." + joinPoint.getSignature().getName() + "()")); log.info("方法型別:" + getServiceMthodType(joinPoint)); log.info("引數:" + param); log.info("請求IP:" + ip); log.info("=====Service前置通知結束====="); log.info("url ={}",request.getRequestURI()); //日誌記錄到資料庫 logService.writeManageOptLog(ip, getServiceMthodType(joinPoint), methodName + param, request.getRequestURI()); } /** * 方法引數 * @param joinPoint * @return */ private String getParam(JoinPoint joinPoint){ StringBuilder params = new StringBuilder(); if (joinPoint.getArgs() != null && joinPoint.getArgs().length > 0) { for ( int i = 0; i < joinPoint.getArgs().length; i++) { if(joinPoint.getArgs()[i].getClass() == PartnerLogisticsBean.class){ params.append(joinPoint.getArgs()[i].toString()).append(";"); }else{ params.append(joinPoint.getArgs()[i]).append(";"); } } } return params.toString(); } //操作型別,用於區分操作 private static String getServiceMthodType(JoinPoint joinPoint){ String targetName = joinPoint.getTarget().getClass().getName(); String methodName = joinPoint.getSignature().getName(); Object[] arguments = joinPoint.getArgs(); Class targetClass = null; try { targetClass = Class.forName(targetName); } catch (ClassNotFoundException e) { e.printStackTrace(); } assert targetClass != null; Method[] methods = targetClass.getMethods(); String type = "b"; for (Method method : methods) { if (method.getName().equals(methodName)) { Class[] clazzs = method.getParameterTypes(); if (clazzs.length == arguments.length) { type = method.getAnnotation(SystemControllerLog.class).type(); break; } } } return type; } }

日誌儲存到資料庫

package com.rzg.dgztc.mall.manage.service;

import com.rzg.dgztc.mall.constant.ShiroConstants;
import com.rzg.dgztc.mall.entity.mall.MallOptLog;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;

@Component
public class MallOptLogService {

    /**
     * 記錄系統日誌
     *
     * @param ip
     * @param type
     * @param logContent
     */
    @Async
    public void writeManageOptLog(String ip, String type, String logContent, String url) {
        MallOptLog log = new MallOptLog();
        log.setLog_content(logContent);
        log.setOpt_type(type);
        if (null != ShiroConstants.getCurrentUser()) {
            log.setOpt_user(ShiroConstants.getCurrentUser().getId());
        }
        log.setUrl(url);
        log.setOpt_time(ShiroConstants.currentTimeSecond());
        log.setOpt_ip(ip);
        log.insert();
    }
}

最後在Controller層介面處新增

@SystemControllerLog(description = "下發分成", type = "d")
    /**
     * 下發分成
     *
     * @param orderId 訂單id
     * @return
     */
    @RequestMapping(value = "/grantDivide/{orderId}")
    @ResponseBody
    @SystemControllerLog(description = "下發分成", type = "d")
    public String grantDivide(@PathVariable String orderId) {

    }

在需要記錄操作日誌的controller層採用如上註解的方式就可以在操作時記錄操作的日誌了。