Aop记录用户操作

1.引入依赖

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

2.准备操作

SystemLog实体类

@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@TableName("system_log")
public class SystemLog implements Serializable{
    private static final long serialVersionUID = 505066661880897158L;
    //日志id
    @TableId
    private Long logId;
    //操作人
    private String operator;
    //请求方式
    private String method;
    //操作模块
    private String module;
    //创建时间
    private Date time;
    //操作类型(curd)
    private String type;
    //操作地址
    private String ip;
    //操作结果
    private String operatorResult;
    //逻辑删除
    @TableLogic
    private Integer delFlag;

}

对应表结构system_log

CREATE TABLE `system_log` (
  `log_id` bigint NOT NULL AUTO_INCREMENT COMMENT '日志id',
  `operator` char(1) COLLATE utf8mb4_general_ci NOT NULL COMMENT '操作人',
  `method` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '请求方式',
  `module` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '操作模块',
  `type` varchar(64) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '操作类型(curd)',
  `time` datetime DEFAULT NULL COMMENT '创建时间',
  `ip` varchar(64) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '操作地址',
  `operator_result` char(16) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '操作结果',
  `del_flag` int DEFAULT '1' COMMENT '逻辑删除',
  PRIMARY KEY (`log_id`)
) ENGINE=InnoDB AUTO_INCREMENT=33 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;

image

3.Aop实现

1.自定义注解

@Target(ElementType.METHOD) // 方法注解
@Retention(RetentionPolicy.RUNTIME) // 运行时可见
public @interface SysLog {

    String module();//操作模块

    String type();//操作类型

}

2.编写切面类

@Slf4j
@Component
@Aspect
public class LogAopAspect {

    @Autowired
    private SystemLogService systemLogService;

    @Around("@annotation(com.hxut.mrs.annotation.SysLog)")
    public Object aroundAdvice(ProceedingJoinPoint pjp) throws Throwable {
        //ProceedingJoinPoint.proceed()方法前为前置通知,之后为返回通知,catch中为异常通知, finally为后置通知

        // 获取方法签名
        MethodSignature methodSignature = (MethodSignature) pjp.getSignature();
        //获取方法
        Method method = methodSignature.getMethod();
        //获取方法上的注解
        SysLog sysLog = method.getAnnotation(SysLog.class);

        //获取注解上对应的属性
        String module = sysLog.module();//系统模块
        String type = sysLog.type();//操作类型(删除/增加/修改/查询)
        Long userId = SecurityUtil.getUserId();//操作人(登录的用户)
        //获取ip与请求方式
        HttpServletRequest request = HttpContextUtil.getRequest();
        String requestMethod = request.getMethod();
        String ipAddress = HttpContextUtil.getIpAddress();

        //封装对象属性
        SystemLog systemLog = SystemLog.builder()
                .operator(userId.toString())
                .method(requestMethod)
                .module(module)
                .type(type)
                .ip(ipAddress)
                .build();

        Object result = null;
        try{

            //执行代理方法
             result = pjp.proceed();
            //相当于后置通知(方法成功执行之后走这里)
            systemLog.setOperatorResult("操作成功");

        } catch (Exception e) {
            systemLog.setOperatorResult("操作失败");
        }finally {

            //相当于最终通知
            systemLog.setTime(new Date());
            systemLogService.save(systemLog);

        }

        return result;
    }

}

3.测试controller

    /**
     * 根据userId获取登录信息
     * @param userId
     * @return
     */
    @GetMapping("/userInfo/{userId}")
    @SysLog(module = "用户模块", type = "获取登录用户信息")
    public R<LoginUserInfoVo> getUserInfo(@PathVariable Long userId){
        return userService.getUserInfo(userId);
    }

访问此接口查看system_log是否记录操作
测试成功!!!
image

posted @ 2023-03-22 17:25  长情c  阅读(48)  评论(0)    收藏  举报