使用AOP结合自定义注解实现在MongoDB添加日志功能

使用AOP(面向切面编程)结合自定义注解来实现在MongoDB添加日志功能,需要执行以下步骤:

 学习更多MongoDB操作可以看这一篇SpringBoot操作Mongodb

导入依赖

以下两个是aop和MongoDB的依赖

  <!--        aop-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-data-mongodb -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-mongodb</artifactId>
        </dependency>

yml配置文件

spring:
  data:
    mongodb:
      uri: mongodb://192.168.10.26:27017/mylog

----------------------------------------------------------
如果使用properties就是用如下 192.168.10.26为ip 27017为端口 mylog为表名自己改即可
spring.data.mongodb.uri=mongodb://192.168.10.26:27017/mylog

实体类

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@AllArgsConstructor
@NoArgsConstructor
@Data
public class OperationLog {
    private Long id; //日志id
    private String userCode; //操作人
    private String ip; //操作ip
    private String type; //操作类型
    private String description; //操作名称
    private String model; //操作模块
    private String operationTime; //操作时间
    private String result; //操作结果
}

定义自定义注解

你需要定义一个自定义注解,用于标记需要添加日志的方法。

import java.lang.annotation.*;

@Target(ElementType.METHOD)//注解放置的目标位置即方法级别
@Retention(RetentionPolicy.RUNTIME)//注解在哪个阶段执行
@Documented
public @interface OperationLogAnnotation {
    String operModul() default ""; // 操作模块

    String operType() default "";  // 操作类型

    String operDesc() default "";  // 操作说明
}

创建切面类

接下来,你需要创建一个切面类,它将包含在执行方法前后添加日志的逻辑。可以按照以下示例创建切面类:



import cn.hutool.core.util.IdUtil;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.text.ParseException;


/**
 * 操作日志切面处理类
 */
@Aspect
@Component
public class OperationLogAspect {
    @Autowired
    private MongoTemplate mongoTemplate;

    /**
     * 设置操作日志切入点 在注解位置切入代码
     */
    @Pointcut("@annotation(OperationLogAnnotation)")
    public void operLogPointcut() {
    }

    /**
     * 记录操作日志
     */
    @AfterReturning(returning = "result", value = "operLogPointcut()")
    public void saveOperLog(JoinPoint joinPoint, Object result) throws ParseException {
        // 获取RequestAttributes 直接获取ThreadLocal里面的值,这样就保证了每一次获取到的Request是该请求的request.
        RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();//RequestContextHolder既是持有上下文的Request容器
        // 从获取RequestAttributes中获取HttpServletRequest的信息
        HttpServletRequest request = (HttpServletRequest) requestAttributes.resolveReference(RequestAttributes.REFERENCE_REQUEST);
        try {
            //将返回值转换成map集合
//            HttpResult map = (HttpResult) result;
            //创建日志对象
            OperationLog operationLog = new OperationLog();
            //设置id
            operationLog.setId(IdUtil.getSnowflake().nextId());
            // 从切面织入点处通过反射机制获取织入点处的方法
            MethodSignature signature = (MethodSignature) joinPoint.getSignature();//MethodSignature 包含了被拦截方法的一些信息,如目标方法的返回类型,目标方法的参数列表信息
            //获取切入点所在的方法
            Method method = signature.getMethod();
            //获取操作
            OperationLogAnnotation annotation = method.getAnnotation(OperationLogAnnotation.class);
            if (annotation != null) {
                operationLog.setModel(annotation.operModul());
                operationLog.setType(annotation.operType());
                operationLog.setDescription(annotation.operDesc());
            }
            //操作时间
            operationLog.setOperationTime(MongoUtils.getNowTime());
            //操作用户
//            String jwt = request.getHeader("jwt");
//            Map payLoad = JWTUtil.getPayload(jwt);
//            String username = (String) payLoad.get("username");
//用户信息如何加密的 就如何解密 获取用户信息
            operationLog.setUserCode("用户待完善");
            //操作IP
            operationLog.setIp(IPUtil.getRemoteHost(request));//获取真实ip
            //返回值信息
//            operationLog.setResult(map.getMsg());
            //保存日志
            mongoTemplate.insert(operationLog);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

工具类

/**
 * @program: SpringBoot_MongoDB
 * @author: 阿水
 * @create: 2023-06-08 16:52
 **/

import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;

/**
 * mongodb工具类
 */
public class MongoUtils {

    /**
     * 获取MongoDB的当前时间,时区UTC转GMT
     * @return GMT时区时间
     */
    public static String getNowTime() {
        Date currentDate = new Date();

        // 创建日期格式化对象
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");

        // 格式化日期对象为字符串
        String formattedDate = sdf.format(currentDate);

        // 输出当前年月日时分秒以及毫秒
//        System.out.println("当前时间:" + formattedDate);

        return formattedDate;


    }
}
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import javax.servlet.http.HttpServletRequest;

/**
 * @Description
 * @Author 刘品水
 * @Data 2023/5/16 20:12
StringUtils都差不多 看着选你习惯用的就好
 */
public class IPUtil {
    /**
     * 获取目标主机的ip
     */
    public static String getRemoteHost(HttpServletRequest request) {
        String Xip = request.getHeader("X-Real-IP");
        String XFor = request.getHeader("X-Forwarded-For");
        if (StringUtils.isNotBlank(XFor) && !"unKnown".equalsIgnoreCase(XFor)) {
            // 多次反向代理后会有多个ip值,第一个ip才是真实ip
            int index = XFor.indexOf(",");
            if (index != -1) {
                return XFor.substring(0, index);
            } else {
                return XFor;
            }
        }
        XFor = Xip;
        if (StringUtils.isNotEmpty(XFor) && !"unKnown".equalsIgnoreCase(XFor)) {
            return XFor;
        }
        if (StringUtils.isBlank(XFor) || "unKnown".equalsIgnoreCase(XFor)) {
            XFor = request.getHeader("Proxy-Client-IP");
        }
        if (StringUtils.isBlank(XFor) || "unKnown".equalsIgnoreCase(XFor)) {
            XFor = request.getHeader("WL-Proxy-Client-IP");
        }
        if (StringUtils.isBlank(XFor) || "unKnown".equalsIgnoreCase(XFor)) {
            XFor = request.getHeader("HTTP_CLIENT_IP");
        }
        if (StringUtils.isBlank(XFor) || "unKnown".equalsIgnoreCase(XFor)) {
            XFor = request.getHeader("HTTP_X_FORWARDED_FOR");
        }
        if (StringUtils.isBlank(XFor) || "unKnown".equalsIgnoreCase(XFor)) {
            XFor = request.getRemoteAddr();
        }

        return XFor;
    }
    
}

运行效果如下:

猜你喜欢

转载自blog.csdn.net/lps12345666/article/details/131187758