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层采用如上注解的方式就可以在操作时记录操作的日志了。

猜你喜欢

转载自blog.csdn.net/banjw_129/article/details/81316111