Springboot使用AOP记录用户操作日志

Aop类 LogAop

package com.qishimai.travelplan.controller;
import com.qishimai.travelplan.pojo.Sys_log;
import com.qishimai.travelplan.pojo.Sys_user;
import com.qishimai.travelplan.pojo.common.Constant;
import com.qishimai.travelplan.service.Sys_logService;
import com.qishimai.travelplan.service.Sys_userService;
import com.qishimai.travelplan.utils.JwtUtil;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RequestMapping;
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.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
@Component
@Aspect
public class LogAop {
    @Autowired
    private HttpServletRequest request;
    @Autowired
    private Sys_logService sysLogService;
    @Autowired
    private Sys_userService sys_userService;
    private Class clazz;//访问的类,对象
    private Method method;//访问的方法,对象
    Object[] args = null;
    //前置通知 只要是获取开始的时间,执行的类是哪一个,执行的是哪一个方法
    @Before("execution(public * com.qishimai.travelplan.controller..*.*(..))")
    public void doBefore(JoinPoint joinPoint) {
        try {
            clazz = joinPoint.getTarget().getClass();//具体要访问的类
            String requestMethod = joinPoint.getSignature().getName();//获取访问的方法名==method.getName()
            args = joinPoint.getArgs();//获取访问的方法的参数
            //获取具体执行的方法的Method对象
            if (args == null || args.length == 0) {
                method = clazz.getMethod(requestMethod);//只能获取无参的方法名
            } else {
                Class[] classArgs = new Class[args.length];
                for (int i = 0; i < args.length; i++) {
                    classArgs[i] = args[i].getClass();//此处难理解
                }
                method = clazz.getMethod(requestMethod, classArgs);//获取有参方法名
            }
        } catch (Exception e) {
            System.out.println("***********" + e.getMessage());//打印输出异常信息
        }
    }
    //后置通知
    @After("execution(public * com.qishimai.travelplan.controller..*.*(..))")
    public void doAfter(JoinPoint joinPoint) {
        try {
            String url = "";
            //获取url
            if (clazz != null && method != null & clazz != LogAop.class) {
                //1获取类上的@RequestMapping("/..)
                RequestMapping classAnnotation = (RequestMapping) clazz.getAnnotation(RequestMapping.class);
                if (classAnnotation != null) {
                    String[] classValue = classAnnotation.value();
                    //2获取方法上的@RequestMapping("/xxx)
                    RequestMapping methodAnnotation = method.getAnnotation(RequestMapping.class);
                    if (methodAnnotation != null) {
                        String[] methodValue = methodAnnotation.value();
                        url = classValue[0] + methodValue[0];
                        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
                        String token = request.getHeader("Authorization");
                        System.err.println("token  :  " + token);
                        Sys_log sys_log = new Sys_log();
                        if (!"".equals(token)) {
                            String username = JwtUtil.getClaim(token, Constant.ACCOUNT);
                            Sys_user sys_user = sys_userService.findUserByPhone(username);
                            sys_log.setUser_id(sys_user.getUser_id());//获取用户id
                            sys_log.setUser_name(sys_user.getUser_name());
                        } else {
                            sys_log.setUser_id(0);
                            sys_log.setUser_name("匿名用户");
                        }
                        //类名太长,直接截取最后一段controller名称
                        String className = clazz.getName().substring(clazz.getName().lastIndexOf(".")+1);
                        sys_log.setLog_content("[类名]" + className + "[方法名]" + method.getName() + "[参数]" + Arrays.toString(args));
                        if (methodValue[0].contains("find") || methodValue[0].contains("select")) {
                            sys_log.setLog_type(0);//查询
                        } else if (methodValue[0].contains("save") || methodValue[0].contains("insert")) {
                            sys_log.setLog_type(1);//插入
                        } else if (methodValue[0].contains("update")) {
                            sys_log.setLog_type(3);//更新
                        } else if (methodValue[0].contains("delete")) {
                            sys_log.setLog_type(2);//删除
                        } else {
                            sys_log.setLog_type(4);//其他操作
                        }
                        SimpleDateFormat dateFormat = new SimpleDateFormat("yy-MM-dd HH:mm:ss");
                        String format = dateFormat.format(new Date());
                        sys_log.setLog_time(format);

                        //调用service层完成存储日志的操作
                        sysLogService.saveLog(sys_log);
                    }
                }
            }
        } catch (Exception e) {
            System.out.println("************" + e.getMessage());
        }
    }
}

日志实体类

@Data
@ToString
public class Sys_log implements Serializable {
    private int log_id;//日志ID
    private int user_id;//用户ID
    private String user_name;//用户名称
    private int log_type;//日志操作类型 增删改查:查:0,增:1,删:2,改:3
    private String log_content;//操作内容    操作接口
    private String log_time;//记录时间
}

承接LogAop的方法String username = JwtUtil.getClaim(token, Constant.ACCOUNT);

Constant类

package com.qishimai.travelplan.pojo.common;
/**
* 常量
* @author WangWenlong
* @date 2019/4/3 16:03
*/
public class Constant {
    /**
     * redis-OK
     */
    public final static String OK = "OK";
    /**
     * redis过期时间,以秒为单位,一分钟
     */
    public final static int EXRP_MINUTE = 60;
    /**
     * redis过期时间,以秒为单位,一小时
     */
    public final static int EXRP_HOUR = 60 * 60;
    /**
     * redis过期时间,以秒为单位,一天
     */
    public final static int EXRP_DAY = 60 * 60 * 24;
    /**
     * redis-key-前缀-shiro:cache:
     */
    public final static String PREFIX_SHIRO_CACHE = "shiro:cache:";
    /**
     * redis-key-前缀-shiro:access_token:
     */
    public final static String PREFIX_SHIRO_ACCESS_TOKEN = "shiro:access_token:";
    /**
     * redis-key-前缀-shiro:refresh_token:
     */
    public final static String PREFIX_SHIRO_REFRESH_TOKEN = "shiro:refresh_token:";
    /**
     * JWT-account:
     */
    public final static String ACCOUNT = "account";
    /**
     * JWT-currentTimeMillis:
     */
    public final static String CURRENT_TIME_MILLIS = "currentTimeMillis";
    /**
     * PASSWORD_MAX_LEN
     */
    public static final Integer PASSWORD_MAX_LEN = 8;
}

JwtUtil工具类

package com.qishimai.travelplan.utils;
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTDecodeException;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.qishimai.travelplan.exception.CustomException;
import com.qishimai.travelplan.pojo.common.Constant;
import com.qishimai.travelplan.utils.common.Base64ConvertUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import java.io.UnsupportedEncodingException;
import java.util.Date;
/**
* JAVA-JWT工具类
* @author WangWenlong
*/
@Component
public class JwtUtil {
    /**
     * LOGGER
     */
    private static final Logger LOGGER = LoggerFactory.getLogger(JwtUtil.class);
    /**
     * 过期时间改为从配置文件获取
     */
    private static String accessTokenExpireTime;
    /**
     * JWT认证加密私钥(Base64加密)
     */
    private static String encryptJWTKey;
    @Value("${accessTokenExpireTime}")
    public void setAccessTokenExpireTime(String accessTokenExpireTime) {
        JwtUtil.accessTokenExpireTime = accessTokenExpireTime;
    }
    @Value("${encryptJWTKey}")
    public void setEncryptJWTKey(String encryptJWTKey) {
        JwtUtil.encryptJWTKey = encryptJWTKey;
    }
    /**
     * 校验token是否正确
     * @param token Token
     * @return boolean 是否正确
     * @author WangWenlong
     * @date 2019/4/3 9:05
     */
    public static boolean verify(String token) {
        try {
            // 帐号加JWT私钥解密
            String secret = getClaim(token, Constant.ACCOUNT) + Base64ConvertUtil.decode(encryptJWTKey);
            Algorithm algorithm = Algorithm.HMAC256(secret);
            JWTVerifier verifier = JWT.require(algorithm)
                    .build();
            DecodedJWT jwt = verifier.verify(token);
            return true;
        } catch (UnsupportedEncodingException e) {
            LOGGER.error("JWTToken认证解密出现UnsupportedEncodingException异常:" + e.getMessage());
            throw new CustomException("JWTToken认证解密出现UnsupportedEncodingException异常:" + e.getMessage());
        }
    }
    /**
     * 获得Token中的信息无需secret解密也能获得
     * @param token
     * @param claim
     * @return java.lang.String
     * @author WangWenlong
     * @date 2019/4/7 16:54
     */
    public static String getClaim(String token, String claim) {
        try {
            DecodedJWT jwt = JWT.decode(token);
            // 只能输出String类型,如果是其他类型返回null
            return jwt.getClaim(claim).asString();
        } catch (JWTDecodeException e) {
            LOGGER.error("解密Token中的公共信息出现JWTDecodeException异常:" + e.getMessage());
            throw new CustomException("解密Token中的公共信息出现JWTDecodeException异常:" + e.getMessage());
        }
    }
    /**
     * 生成签名
     * @param account 帐号
     * @return java.lang.String 返回加密的Token
     * @author WangWenlong
     * @date 2019/4/3 9:07
     */
    public static String sign(String account, String currentTimeMillis) {
        try {
            // 帐号加JWT私钥加密
            String secret = account + Base64ConvertUtil.decode(encryptJWTKey);
            // 此处过期时间是以毫秒为单位,所以乘以1000
            Date date = new Date(System.currentTimeMillis() + Long.parseLong(accessTokenExpireTime) * 1000);
            Algorithm algorithm = Algorithm.HMAC256(secret);
            // 附带account帐号信息
            return JWT.create()
                    .withClaim("account", account)
                    .withClaim("currentTimeMillis", currentTimeMillis)
                    .withExpiresAt(date)
                    .sign(algorithm);
        } catch (UnsupportedEncodingException e) {
            LOGGER.error("JWTToken加密出现UnsupportedEncodingException异常:" + e.getMessage());
            throw new CustomException("JWTToken加密出现UnsupportedEncodingException异常:" + e.getMessage());
        }
    }
}

最后调用添加方法,将日志插入到日志表(普通的增删改查,所以省略不写了)

猜你喜欢

转载自blog.csdn.net/qq_42227281/article/details/95499420