Grails 通过自定义注解@AuditLog+AOP实现系统日志记录

1、引入spring-aop组件 和 fastjson组件

// https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-aop
compile group: 'org.springframework.boot', name: 'spring-boot-starter-aop', version: '2.1.10.RELEASE'

// https://mvnrepository.com/artifact/com.alibaba/fastjson
compile group: 'com.alibaba', name: 'fastjson', version: '1.2.66'

2、自定义注解@AuditLog

package middol.annotation;

import java.lang.annotation.*;

/**
* @Description:    系统日志
* @Author:         [email protected]
* @CreateDate:     2020/3/19 20:51
* @Version:        1.0
*/
//注解在方法上
@Target(ElementType.METHOD)
//再运行时
@Retention(RetentionPolicy.RUNTIME)
//文档
@Documented
public @interface AuditLog {
    /**
     * 日志内容
     * @return
     */
    String value() default "";

    /**
     * 日志类型
     * @return
     */
    int logType() default 1;

    /**
     * 操作类型 (增删改查)
     * @return
     */
    int optionType() default 0;

}

3、创建日志切面

package middol.aops;

import com.alibaba.fastjson.JSONObject;
import middol.IpUtils;
import middol.annotation.AuditLog;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
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 AuditLogAspect {
    @Pointcut("@annotation(middol.annotation.AuditLog)")
    public void auditLog(){

    }

    @Around("auditLog()")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable{
        long beginTime = System.currentTimeMillis();
        //执行方法
        Object proceed = joinPoint.proceed();
        //执行时长
        long time = System.currentTimeMillis() - beginTime;

        //保存日志
        saveLog(joinPoint, time);

        return proceed;
    }

    private void saveLog(ProceedingJoinPoint joinPoint, long time) {
        //获取目标对象
        MethodSignature signature = (MethodSignature)joinPoint.getSignature();
        //获取目标方法
        Method method = signature.getMethod();
        AuditLog auditLog = method.getAnnotation(AuditLog.class);

        if(auditLog != null){
            //获取注解上的描述,操作日志内容
            System.out.println(auditLog.value());
            System.out.println(auditLog.logType());
            System.out.println(auditLog.optionType());
        }

        //获取请求的方法名
        String className = joinPoint.getSignature().getDeclaringTypeName();
        String methodName = method.getName();
        System.out.println(className +"."+methodName+"()");

        //获取操作类型
        int optionType = auditLog.optionType();
        System.out.println(optionType);

        //获取请求参数
        Object[] args = joinPoint.getArgs();
        //使用fastjson 将object对象转换为字符串
        System.out.println("参数:"+JSONObject.toJSONString(args));

        //获取request信息
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        /**如果是用nginx反向代理的话 request.getRemoteAddr() 不能获取ip
         * 如果使用了多级反向代理的话,X-Forwarded-For的值并不止一个,而是一串IP地址,X-Forwarded-For中第一个非unknown的有效IP字符串,则为真实IP地址
         */
        String ip = IpUtils.getIpAddr(request);
        System.out.println(ip);


        //获取url参数
        System.out.println(request.getQueryString());

        //获取登录信息,如果你用security插件 则是 springSecurityService.getPrincipal()?.getUsername()
        String usename = "SYS";
    }
}

4、测试

IpUtils工具类

package middol;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.http.HttpServletRequest;
/**
* @Description:    IP工具类
* @Author:         [email protected]
* @CreateDate:     2020/3/19 21:37
* @Version:        1.0
*/
public class IpUtils {
    private static Logger logger = LoggerFactory.getLogger(IpUtils.class);

    /**
     * 获取IP地址
     *
     * 使用Nginx等反向代理软件, 则不能通过request.getRemoteAddr()获取IP地址
     * 如果使用了多级反向代理的话,X-Forwarded-For的值并不止一个,而是一串IP地址,X-Forwarded-For中第一个非unknown的有效IP字符串,则为真实IP地址
     */
    public static String getIpAddr(HttpServletRequest request) {
        String ip = null;
        try {
            ip = request.getHeader("x-forwarded-for");
            if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) {
                ip = request.getHeader("Proxy-Client-IP");
            }
            if (StringUtils.isEmpty(ip) || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
                ip = request.getHeader("WL-Proxy-Client-IP");
            }
            if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) {
                ip = request.getHeader("HTTP_CLIENT_IP");
            }
            if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) {
                ip = request.getHeader("HTTP_X_FORWARDED_FOR");
            }
            if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) {
                ip = request.getRemoteAddr();
            }
        } catch (Exception e) {
            logger.error("IPUtils ERROR ", e);
        }

//        //使用代理,则获取第一个IP地址
//        if(StringUtils.isEmpty(ip) && ip.length() > 15) {
//			if(ip.indexOf(",") > 0) {
//				ip = ip.substring(0, ip.indexOf(","));
//			}
//		}

        return ip;
    }
}
发布了102 篇原创文章 · 获赞 40 · 访问量 7万+

猜你喜欢

转载自blog.csdn.net/qq_16165281/article/details/104977799