springboot使用aop记录后台操作日志

硅谷探秘者 1878 0 0

1.Log注解

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

//该注解可以放在controller类上,但是只有 modular 参数有效;
//该注解也可以放在controller类的方法上,如果只有方法上有Log注解,那么只会解析该注解上的信息,
//如果类和方法上都有Log注解,且方法上的 modular参数 不是默认值,那么以方法上的 modular 参数为准,否则以类上的 modular 参数为准;

@Target({ElementType.METHOD,ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Log {
    /** 方法模块 */
    String modular() default "";
    /** 功能描述 */
    String describe() default "";
}

2.日志信息封装DTO

import lombok.Data;
import lombok.ToString;
import java.time.LocalDateTime;
/**
 * @ClassName LogMessage
 * @Description: 日志数据封装
 * @Author Jiajiajia
 * @Version V1.0
 **/
@Data
@ToString
public class LogMessage {
    //操作人id
    private Long operationUserId;
    //操作人
    private String operationUser;
    //操作模块
    private String modular;
    //具体方法描述
    private String describe;
    //来源计算机ip地址
    private String ip;
    //操作状态
    private byte state;
    //请求类型
    private String type;
    //执行时间
    private LocalDateTime createTime=LocalDateTime.now();
    //其他信息
    private String message;

    public void setState(State state){
        this.state=state.getState();
    }
    /**
     *  操作状态的枚举类
     */
    public enum State{
        SUCCESS((byte)0),ERROR((byte)1);
        private byte state;
        State(byte state){
            this.state=state;
        }
        public byte getState(){
            return state;
        }
    }
}

3.注解解析

利用反射技术,获取注解所在类的类信息,方法信息,和注解信息


import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
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.net.InetAddress;
import java.net.UnknownHostException;

/**
 * @ClassName AopTest
 * @Author Jiajiajia
 * @Version V1.0
 **/
@Aspect
@Component
public class LogAopAdapter {
    /**
     *  如果同步操作那就在这里注入dao层,在doAfter或throwing方法中将message对象插入数据库;
     *  如果异步操作,那就在doAfter或throwing方法中将message对象放入阻塞队列异步执行,或者使用mq,
     *  或者使用springboot的异步事件等;
     */
//    @Resource
//    private LogAopDao logAopDao;

    @Pointcut("@annotation(com.test.Log)")
    public void log(){}

    /**
     *  前置通知
     * @param joinPoint
     * @throws Throwable
     */
    @Before("log()")
    public void doBefore(JoinPoint joinPoint) throws Throwable {
    }

    /**
     *  后置通知
     * @param joinPoint
     * @throws Throwable
     */
    @After("log()&&@annotation(logMessage)")
    public void doAfter(JoinPoint joinPoint,Log logMessage)throws Throwable{
        LogMessage message = getMessage(joinPoint,logMessage);
        message.setState(LogMessage.State.SUCCESS);
        System.out.println(message);
    }

    /**
     *  异常通知
     * @param joinPoint
     * @param ex
     * @throws Exception
     */
    @AfterThrowing(value="log()&&@annotation(logMessage)", throwing="ex")
    public void throwing(JoinPoint joinPoint,Log logMessage,Exception ex) throws Exception{
        LogMessage message = getMessage(joinPoint,logMessage);
        message.setMessage(ex.getMessage());
        message.setState(LogMessage.State.ERROR);
        System.out.println(message);
    }

    private LogMessage getMessage(JoinPoint joinPoint,Log mlog)throws Exception{
        LogMessage message=new LogMessage();
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        message.setType(request.getMethod());
        message.setIp(getUserRealIp(request));
        Signature signature = joinPoint.getSignature();
        Class c=signature.getDeclaringType();
        if(!"".equals(mlog.describe())){
            message.setDescribe(mlog.describe());
        }
        if(!"".equals(mlog.modular())){
            message.setModular(mlog.modular());
        }else{
            Log clog=(Log)c.getAnnotation(Log.class);
            if(clog!=null){
                if(!"".equals(clog.modular())){
                    message.setModular(clog.modular());
                }
            }
        }
        return message;
    }

    /**
     * 获取源主机ip地址
     * @param request
     * @return
     * @throws UnknownHostException
     */
    public static String getUserRealIp(HttpServletRequest request) throws UnknownHostException {
        String ip;
        if  (request.getHeader("x-forwarded-for") == null)  {
            ip = request.getRemoteAddr();
        }  else  {
            ip = request.getHeader("x-forwarded-for");
        }
        if  ("127.0.0.1".equals(ip))  {
            ip = InetAddress.getLocalHost().getHostAddress();
        }
        return ip;
    }
}

4.测试代码

测试代码
@Log(modular = "测试模块")
@RestController
public class TestController {
    @GetMapping("test")
    @Log(describe = "测试描述")
    public String test(){
        if(true){
	//手动抛异常
            throw new Exception("异常");
        }
        return "test";
    }
}

 


评论区
请写下您的评论...
暂无评论...
猜你喜欢
框架 3694 springaop实现此次的目的是实现对controller中的方法执行情况进行的有方法执行时间,人,请求的路径,方法的入参,模块,功能等。并实现利注解的方式实现对被
框架,springboot 88 springboot自带的logback打印多环境打印生产环境输出到控制和文件,一天一个文件,保留30天开发环境输出到控制 二、logback-spring.xml配置文件详情?xmlversion="1.
数据库 1266 MariaDB/MySQL中,主要有5种文件:1.错误(errorlog):mysql服务的启停时正确和错误的信息,还启动、停止、运行过程中的错误信息。2.查询(generallog):
数据库 1194 开启和设置二进制切换二进制相关参数二进制恢复数据库上一篇文章介绍了普通查询和慢查询等参考:mysql分析,本篇主要介绍二进制。一、什么是二进制  二进制主要
git 940 码;完成编辑,我们gitadd将工区文件添加到暂存区;然gitcommit提交文件到我们自己的分支。命令:gitcheckoutfiles或者gitcheckout.:把文件从暂存区域复
框架 1282 }/pattern/layoutencoderpattern${PATTERN}/patterncharsetUTF-8/charset/encoder/appender!--下面配置一些第三方包的过滤级别,
java项目 1394 springboot+mybatis配置多数据源并利aop实现自动切换(demo)
spring/springmvc 1400 "spring在ioc容器中获取aop的受理对象",这句话是什么意思呢?有时候我们会在spring项目中对一下类进行代理,比如我们会spring的aop和自定义注解对一些接口访问添加,再比如对
归档
2018-11  12 2018-12  33 2019-01  28 2019-02  28 2019-03  32 2019-04  27 2019-05  33 2019-06  6 2019-07  12 2019-08  12 2019-09  21 2019-10  8 2019-11  15 2019-12  25 2020-01  9 2020-02  5 2020-03  16 2020-04  4 2020-06  1 2020-07  7 2020-08  13 2020-09  9 2020-10  5 2020-12  3 2021-01  1 2021-02  5 2021-03  7 2021-04  4 2021-05  4 2021-06  1 2021-07  7 2021-08  2 2021-09  8 2021-10  9 2021-11  16 2021-12  14 2022-01  7 2022-05  1 2022-08  3 2022-09  2 2022-10  2 2022-12  5 2023-01  3 2023-02  1 2023-03  4 2023-04  2 2023-06  3 2023-07  4 2023-08  1 2023-10  1 2024-02  1 2024-03  1 2024-04  1
标签
算法基础 linux 前端 c++ 数据结构 框架 数据库 计算机基础 储备知识 java基础 ASM 其他 深入理解java虚拟机 nginx git 消息中间件 搜索 maven redis docker dubbo vue 导入导出 软件使用 idea插件 协议 无聊的知识 jenkins springboot mqtt协议 keepalived minio mysql ensp 网络基础 xxl-job rabbitmq haproxy srs 音视频 webrtc javascript
目录
没有一个冬天不可逾越,没有一个春天不会来临。最慢的步伐不是跬步,而是徘徊,最快的脚步不是冲刺,而是坚持。