SpringBoot AOP记录用户操作日志

Aop记录用户操作日志相关依赖

<!-- https://mvnrepository.com/artifact/org.aspectj/aspectjrt -->
		<dependency>
			<groupId>org.aspectj</groupId>
			<artifactId>aspectjrt</artifactId>
			<version>1.9.5</version>
		</dependency>

		<!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver -->
		<dependency>
			<groupId>org.aspectj</groupId>
			<artifactId>aspectjweaver</artifactId>
			<version>1.9.5</version>
		</dependency>

自定义注解

import java.lang.annotation.*;

/**
 * 自定义日志注解
 *
 * @author zz
 * @since 2020/6/16
 */
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface OperLog {
    String value() default "";
}

创建数据库表和实体

import lombok.Getter;
import lombok.Setter;

import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
import java.util.Date;

/**
 * 日志
 *
 * @author zz
 * @since 2020/6/16
 */

@Setter
@Getter
@Entity
@Table(name = "sys_log")
public class SysLog {

    @Id
    private String id;
    private String username;
    private String operation;
    private Integer time;
    private String method;
    private String params;
    private String ip;
    private Date operationTime;
    private String url;
}

在这里插入图片描述

dao层接口

import org.springframework.data.jpa.repository.JpaRepository;

/**
 * 日志dao接口
 *
 * @author zz
 * @since 2020/6/16
 */
public interface SysLogDao extends JpaRepository<SysLog,Integer> {
}

访问指定接口时生成日志,保存日志

/**
 * 根据切点表达式在访问指定接口时生成日志,保存日志
 *
 * @author zz
 * @since 2020/6/16
 */

@Aspect
@Component
@Slf4j
public class OperLogAspect {

    /**
     * 设置操作日志切入点 记录操作日志
     */
    @Autowired
    private SysLogDao sysLogDao;

    /**
     * 在注解的位置切入代码
     * 表示匹配com.baidu.well.controller包下的所有方法
     */

    @Pointcut("execution(* com.baidu.well.controller.*.*(..))")
    public void operLogPoinCut() {
    }

    /**
     * 正常返回通知,拦截用户操作日志,连接点正常执行完成后执行, 如果连接点抛出异常,则不会执行
     *
     * @param joinPoint 切入点
     * @param keys      返回结果
     */
    @AfterReturning(value = "operLogPoinCut()", returning = "keys")
    public void saveOperLog(JoinPoint joinPoint, Object keys) {
        long beginTime = System.currentTimeMillis();
        // 获取RequestAttributes
        RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
        // 从获取RequestAttributes中获取HttpServletRequest的信息
        HttpServletRequest request = (HttpServletRequest) requestAttributes
                .resolveReference(RequestAttributes.REFERENCE_REQUEST);

        SysLog sysLog = new SysLog();
        String id = UUID.randomUUID().toString().replace("-", "");
        sysLog.setId(id);
        try {
            // 从切面织入点处通过反射机制获取织入点处的方法
            MethodSignature signature = (MethodSignature) joinPoint.getSignature();
            // 获取切入点所在的方法
            Method method = signature.getMethod();
            // 获取操作
            OperLog opLog = method.getAnnotation(OperLog.class);
            if (opLog != null) {
                String value = opLog.value();
                sysLog.setOperation(value);
            }
            // 获取请求的类名
            String className = joinPoint.getTarget().getClass().getName();
            // 获取请求的方法名
            String methodName = method.getName();
            methodName = className + "." + methodName + "()";

            // 请求方法
            sysLog.setMethod(methodName);
            String params = getParams(joinPoint, method);

            sysLog.setParams(params);
            // 请求用户名称
            User user = (User) SecurityUtils.getSubject().getPrincipal();
            sysLog.setUsername(user.getUserName);
            // 访问的url
            sysLog.setUrl(request.getRequestURL().toString());
            // 请求IP
            sysLog.setIp(IPUtils.getIpAddr(request));
            // 创建时间
            sysLog.setOperationTime(new Date());
            sysLog.setTime((int) (System.currentTimeMillis() - beginTime));
            // 保存日志
            sysLogDao.save(sysLog);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    // 获取请求的参数名称
    private String getParams(JoinPoint joinPoint, Method method) {
        // 请求的方法参数值
        Object[] args = joinPoint.getArgs();
        // 请求的方法参数名称
        LocalVariableTableParameterNameDiscoverer u = new LocalVariableTableParameterNameDiscoverer();
        String[] paramNames = u.getParameterNames(method);
        String params = null;
        if (args != null && paramNames != null) {
            for (int i = 0; i < args.length; i++) {
                params += "  " + paramNames[i] + ": " + args[i];
            }
        }
        return params;
    }
}

获取Ip地址的工具类

import javax.servlet.http.HttpServletRequest;

/**
 * 获取请求的Ip地址
 *
 * @author zz
 * @since 2020/6/16
 */
public class IPUtils {

    private static final String X_FORWARDED_FOR = "x-forwarded-for";

    public static String getIpAddr(HttpServletRequest request) {
        String ip = request.getHeader(X_FORWARDED_FOR);
        if (ip == null||ip.length()==0||"unknown".equalsIgnoreCase(ip)){
            ip = request.getHeader("Proxy-client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        return "0:0:0:0:0:0:0:1".equals(ip) ? "127.0.0.1" : ip;

    }
}

注意:在Controller接口上添加自定的注解@OperLog,实现记录用户的操作日志

SpringBoot项目启动类添加包扫描的注解

@EnableAspectJAutoProxy(proxyTargetClass=true) 默认值就是true
@SpringBootApplication
@ComponentScan("com.nec.wellness.*")
@EnableAspectJAutoProxy(proxyTargetClass=true)
public class WellnessDbApplication {

	public static void main(String[] args) {
		SpringApplication.run(WellnessDbApplication.class, args);
	}

}
  • 1
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值