zoukankan      html  css  js  c++  java
  • java 注解结合 spring aop 自动输出日志新增拦截器与过滤器

    auto-log

    auto-log 是一款为 java 设计的自动日志监控框架。

    前面已经写过了两篇:

    java 注解结合 spring aop 实现自动输出日志

    java 注解结合 spring aop 实现日志 traceId 唯一标识

    经过前面2篇的代码实现,发现依然存在下列问题:

    (1)注解的使用依然不够便捷。

    如果每一个方法上都指定 @AutoLog,依然会比较麻烦。个人在使用的时候也不想这么麻烦。

    于是想添加基于类的注解。

    后期考虑是否可以基于包,动态指定 AOP 的扫描包范围。

    (2)对于日志的处理过于单一。

    比如我想添加所有操作的审计日志,然后存储到数据库。同时日志输出不变。

    发现以前的日志框架,不能很好的支撑。于是想添加日志输出的拦截器。

    (3)对于参数的过滤

    以前是直接基于 toString() 实现,发现有些人比较懒不写 toString(比如我),那么参数打印的信息就没有意义。

    于是替换成立 FastJSON,但是引来了新的问题,比如 HttpRequest 等参数直接序列化是会报错的,于是想添加基于参数的过滤器实现。

    需求,才是最好的创作动力。

    目前共计经过了 12 个版本的迭代,上面 3 个特性已经满足。

    特性

    • 基于注解+字节码,配置灵活

    • 自动适配常见的日志框架

    • 支持编程式的调用

    • 支持注解式,完美整合 spring

    • 支持整合 spring-boot

    • 支持慢日志阈值指定,耗时,入参,出参,异常信息等常见属性指定

    • 支持 traceId 特性

    • 支持类级别定义注解

    • 支持自定义拦截器和过滤器

    快速开始

    maven 引入

    <dependency>
        <group>com.github.houbb</group>
        <artifact>auto-log-core</artifact>
        <version>${最新版本}</version>
    </dependency>
    

    入门案例

    UserService userService = AutoLogHelper.proxy(new UserServiceImpl());
    userService.queryLog("1");
    
    • 日志如下
    [INFO] [2020-05-29 16:24:06.227] [main] [c.g.h.a.l.c.s.i.AutoLogMethodInterceptor.invoke] - public java.lang.String com.github.houbb.auto.log.test.service.impl.UserServiceImpl.queryLog(java.lang.String) param is [1]
    [INFO] [2020-05-29 16:24:06.228] [main] [c.g.h.a.l.c.s.i.AutoLogMethodInterceptor.invoke] - public java.lang.String com.github.houbb.auto.log.test.service.impl.UserServiceImpl.queryLog(java.lang.String) result is result-1
    

    代码

    其中方法实现如下:

    • UserService.java
    public interface UserService {
    
        String queryLog(final String id);
    
    }
    
    • UserServiceImpl.java

    直接使用注解 @AutoLog 指定需要打日志的方法即可。

    public class UserServiceImpl implements UserService {
    
        @Override
        @AutoLog
        public String queryLog(String id) {
            return "result-"+id;
        }
    
    }
    

    TraceId 的例子

    代码

    UserService service =  AutoLogProxy.getProxy(new UserServiceImpl());
    service.traceId("1");
    

    其中 traceId 方法如下:

    @AutoLog
    @TraceId
    public String traceId(String id) {
        return id+"-1";
    }
    

    测试效果

    信息: [ba7ddaded5a644e5a58fbd276b6657af] <traceId>入参: [1].
    信息: [ba7ddaded5a644e5a58fbd276b6657af] <traceId>出参:1-1.
    

    其中 ba7ddaded5a644e5a58fbd276b6657af 就是对应的 traceId,可以贯穿整个 thread 周期,便于我们日志查看。

    注解说明

    @AutoLog

    核心注解 @AutoLog 的属性说明如下:

    属性 类型 默认值 说明
    enable boolean true 是否启用
    param boolean true 是否打印入参
    result boolean true 是否打印出参
    costTime boolean false 是否打印耗时
    exception boolean true 是否打印异常
    slowThresholdMills long -1 当这个值大于等于 0 时,且耗时超过配置值,会输出慢日志
    description string "" 方法描述,默认选择方法名称
    interceptor Class[] 默认实现 拦截器实现,支持指定多个和自定义
    paramFilter Class 入参过滤器,支持自定义

    @TraceId

    @TraceId 放在需要设置 traceId 的方法上,比如 Controller 层,mq 的消费者,rpc 请求的接受者等。

    属性 类型 默认值 说明
    id Class 默认为 uuid traceId 的实现策略
    putIfAbsent boolean false 是否在当前线程没有值的时候才设置值
    enable boolean true 是否启用
    interceptor Class[] 默认实现 拦截器实现,支持指定多个和自定义

    自定义策略

    自定义日志拦截器(interceptor)

    内置拦截器

    AutoLogInterceptor 默认实现

    定义

    直接继承自 AbstractAutoLogInterceptor 类,并且实现对应的方法即可。

    public class MyAutoLogInterceptor extends AbstractAutoLogInterceptor {
    
        @Override
        protected void doBefore(AutoLog autoLog, IAutoLogInterceptorContext context) {
            System.out.println("自定义入参:" + Arrays.toString(context.filterParams()));
        }
    
        @Override
        protected void doAfter(AutoLog autoLog, Object result, IAutoLogInterceptorContext context) {
            System.out.println("自定义出参:" + result);
        }
    
        @Override
        protected void doException(AutoLog autoLog, Exception exception, IAutoLogInterceptorContext context) {
            System.out.println("自定义异常:");
            exception.printStackTrace();
        }
    
    }
    

    使用

    如下,这样日志输出,就会使用上面的指定策略。

    @AutoLog(interceptor = MyAutoLogInterceptor.class)
    public String my() {
        return "自定义策略";
    }
    

    自定义入参过滤器(paramFilter)

    内置

    WebParamFilter 主要用于过滤 HttpRequest HttpServlet 等无法直接 JSON 序列化的对象。

    自定义

    直接继承 AbstractParamFilter 类实现对应的方法即可。

    public class MyParamFilter extends AbstractParamFilter {
    
        @Override
        protected Object[] doFilter(Object[] params) {
            Object[] newParams = new Object[1];
            newParams[0] = "设置我我想要的值";
            return newParams;
        }
    
    }
    

    使用

    指定对应的参数过滤器。这样,无论入参是什么,都会变成我们指定的 [设置我我想要的值]

    @AutoLog(paramFilter = MyParamFilter.class)
    public String paramFilter() {
        return "自定义入参过滤器";
    }
    

    spring 整合使用

    完整示例参考 SpringServiceTest

    注解声明

    使用 @EnableAutoLog 启用自动日志输出

    @Configurable
    @ComponentScan(basePackages = "com.github.houbb.auto.log.test.service")
    @EnableAutoLog
    public class SpringConfig {
    }
    

    测试代码

    @ContextConfiguration(classes = SpringConfig.class)
    @RunWith(SpringJUnit4ClassRunner.class)
    public class SpringServiceTest {
    
        @Autowired
        private UserService userService;
    
        @Test
        public void queryLogTest() {
            userService.queryLog("1");
        }
    
    }
    
    • 输出结果
    信息: public java.lang.String com.github.houbb.auto.log.test.service.impl.UserServiceImpl.queryLog(java.lang.String) param is [1]
    五月 30, 2020 12:17:51 下午 com.github.houbb.auto.log.core.support.interceptor.AutoLogMethodInterceptor info
    信息: public java.lang.String com.github.houbb.auto.log.test.service.impl.UserServiceImpl.queryLog(java.lang.String) result is result-1
    五月 30, 2020 12:17:51 下午 org.springframework.context.support.GenericApplicationContext doClose
    

    springboot 整合使用

    maven 引入

    <dependency>
        <groupId>com.github.houbb</groupId>
        <artifactId>auto-log-springboot-starter</artifactId>
        <version>最新版本</version>
    </dependency>
    

    只需要引入 jar 即可,其他的什么都不用配置。

    使用方式和 spring 一致。

    测试

    @Autowired
    private UserService userService;
    
    @Test
    public void queryLogTest() {
        userService.query("spring-boot");
    }
    

    开源地址

    Github: https://github.com/houbb/auto-log

    Gitee: https://gitee.com/houbinbin/auto-log

    Road-Map

    • [ ] 优化日志中的方法路径名称

    考虑补全对应的类信息

    • [ ] 全局配置

    比如全局的慢日志阈值设置等

    • [ ] jvm-sandbox 特性

    • [ ] 编译时注解特性

    原文地址

    java 注解结合 spring aop 自动输出日志新增拦截器与过滤器

    公众号

  • 相关阅读:
    关系数据库&&NoSQL数据库
    NoSQL
    大数据时代的数据存储,非关系型数据库MongoDB
    判断是否为BST
    百度2017暑期实习生编程题
    memset()实现及细节
    在必须返回一个对象时,不要去尝试返回一个引用
    返回局部变量指针
    用引用返回值
    数组形参
  • 原文地址:https://www.cnblogs.com/houbbBlogs/p/13734577.html
Copyright © 2011-2022 走看看