springboot中实现rabbitmq异步日志记录功能

Posted 等你的夏天

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了springboot中实现rabbitmq异步日志记录功能相关的知识,希望对你有一定的参考价值。

1)定义切面;

Log.java

package com.seecen.redis.aop;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Log {

    LogType logType() default LogType.QUERY;
    String  content() default "";

}

LogType.java

package com.seecen.redis.aop;

/**
 *
 * 日志类型枚举类
 */
public enum LogType {
    INSERT("1"),DELETE("2"),UPDATE("3"),LOGIN("4"),QUERY("5"),REGISTER("6");
    private String type;

    LogType(String type) {
        this.type = type;
    }

    public String getType() {
        return type;
    }
}

LogAspect.java

package com.seecen.redis.aop;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.seecen.redis.entity.TLog;
import com.seecen.redis.mapper.TLogMapper;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
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.util.Map;

/**
 * @author bigpeng
 * @create 2020-07-22-10:17
 */
@Aspect
@Component
@Slf4j
public class LogAspect {
    @Autowired
    private TLogMapper logMapper;
    @Autowired
    private RabbitTemplate rabbitTemplate;


    //定义切入点,使用了该注解的方法将被AOP切入
    @Pointcut("@annotation( com.seecen.redis.aop.Log)")
    public void logPointCut(){}

    /**
     * 使用前置通知来完成日志的记录
     * @param joinPoint 连接点信息
     */
    @Before("logPointCut()")
    public void logBefore(JoinPoint joinPoint) throws JsonProcessingException {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        Log logAnnotation = method.getAnnotation(Log.class);
        String type = logAnnotation.logType().getType();
        String content = logAnnotation.content();
        //获取request对象
        ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = requestAttributes.getRequest();
        //请求的IP地址
        String ip = request.getRemoteAddr();
        //请求数据
        Map<String, String[]> data = request.getParameterMap();
        String dataJsonStr="";
        if(data!=null) {
            ObjectMapper objectMapper = new ObjectMapper();
            dataJsonStr= objectMapper.writeValueAsString(data);
        }
        TLog tLog = new TLog();
        tLog.setContent(content);
        tLog.setData(dataJsonStr);
        tLog.setIp(ip);
        tLog.setType(type);
        // log {}表示占位符
        log.info("请求日志信息:{}",tLog);
        // 插入数据库
        long start = System.currentTimeMillis();
        logMapper.insertSelective(tLog);
        log.info("直接插入数据库耗时:{}",System.currentTimeMillis()-start);
        start=System.currentTimeMillis();
        //  发消息队列
        rabbitTemplate.convertAndSend("log.exchange","aopLog",tLog);
        log.info("发送mq消息耗时:{}",System.currentTimeMillis()-start);
    }

}

2)在RabbitConfig.java文件中配置相关的配置信息;

RabbitConfig.java

 //声明队列
    @Bean
    public Queue logQueue(){
        return new Queue("log.queue");
    }
    //声明交换机
    @Bean
    public DirectExchange logExchange(){
        return new DirectExchange("log.exchange",true,false);
    }
    //绑定交换机和队列
    @Bean
    public Binding logBinding(){
        return BindingBuilder.bind(logQueue()).to(logExchange()).with("aopLog");
    }

3)写一个日志的消费者;

LogConsumer.java

package com.seecen.redis.rabbitmq;

import com.seecen.redis.entity.TLog;
import com.seecen.redis.mapper.TLogMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
@Slf4j
public class LogConsumer {
    @Autowired
    private TLogMapper logMapper;

    @RabbitListener(queues = {"log.queue"},
            containerFactory = "rabbitListenerContainerFactory")
    public void insertLog(TLog tLog){
        if (tLog!=null){
            logMapper.insertSelective(tLog);
            log.info("接收到消息:{}",tLog);
        }
    }
}

4)在需要使用的方法上面加上相关的注解;

@Log(logType = LogType.REGISTER,content = "用户注册")

5)测试;查看数据库,即可看到日志信息;

 

以上是关于springboot中实现rabbitmq异步日志记录功能的主要内容,如果未能解决你的问题,请参考以下文章

SpringBoot RabbitMQ异步登录日志

在SpringBoot中实现异步事件驱动

在SpringBoot中实现异步事件驱动

Spring Boot中实现logback多环境日志配置

SpringBoot异步调用--@Async详解

SpringBoot异步调用--@Async详解