zoukankan      html  css  js  c++  java
  • 在 Spring Boot 中来实现 AOP 切面实现日志统一输出

    AOP全称:Aspect Oriented Programming。是一种面向切面编程的,利用预编译方式和运行期动态代理实现程序功能统一的一种技术。它也是Spring很重要的一部分,和IOC一样重要。利用AOP可以很好的对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。

    本文主要利用注解解决系统日志统一输出问题

    话不多说,直接上代码:

    工程pom.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
        <parent>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-parent</artifactId>
            <version>2.3.0.RELEASE</version>
            <relativePath/> <!-- lookup parent from repository -->
        </parent>
        <groupId>com.mscloudmesh.aop</groupId>
        <artifactId>springboot-aop-logs</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <name>springboot-aop-logs</name>
        <description>springboot-aop-logs</description>
    
        <properties>
            <java.version>1.8</java.version>
        </properties>
    
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
    
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-aop</artifactId>
            </dependency>
    
            <dependency>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
                <version> 1.18.12</version>
            </dependency>
    
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-test</artifactId>
                <scope>test</scope>
                <exclusions>
                    <exclusion>
                        <groupId>org.junit.vintage</groupId>
                        <artifactId>junit-vintage-engine</artifactId>
                    </exclusion>
                </exclusions>
            </dependency>
        </dependencies>
    
        <build>
            <plugins>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                </plugin>
            </plugins>
        </build>
    
    </project>
    

    log日志注解类:

    package com.mscloudmesh.aop.springbootaoplogs.annoation;
     
    import java.lang.annotation.*;
    
    /**
     * @author kevin
     * @date 2020/6/9
     */
    @Documented
    @Retention(RetentionPolicy.RUNTIME)
    @Target({ElementType.METHOD})
    public @interface Log {
        String value() default "";
    }
    日志切面类实现:
     
     
    
    package com.mscloudmesh.aop.springbootaoplogs.aspect;
    
    import com.mscloudmesh.aop.springbootaoplogs.annoation.Log;
    import lombok.extern.slf4j.Slf4j;
    import org.aspectj.lang.ProceedingJoinPoint;
    import org.aspectj.lang.Signature;
    import org.aspectj.lang.annotation.Around;
    import org.aspectj.lang.annotation.Aspect;
    import org.aspectj.lang.annotation.Pointcut;
    import org.aspectj.lang.reflect.MethodSignature;
    import org.springframework.core.annotation.AnnotationUtils;
    import org.springframework.stereotype.Component;
    import org.springframework.web.context.request.RequestContextHolder;
    import org.springframework.web.context.request.ServletRequestAttributes;
    
    import java.lang.reflect.Method;
    import java.text.SimpleDateFormat;
    import java.util.Arrays;
    import java.util.Date;
    
    @Aspect
    @Component
    @Slf4j
    public class LogAspect {
    
        //设置切入点:这里直接拦截被@RestController注解的类
        @Pointcut("within(@org.springframework.web.bind.annotation.RestController *)")
        public void pointcut() {
    
        }
    
        /**
         * 切面方法,记录日志
         *
         * @return
         */
        @Around("pointcut()")
        public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {
            long beginTime = System.currentTimeMillis();//1、开始时间 
            //利用RequestContextHolder获取requst对象
            ServletRequestAttributes requestAttr = (ServletRequestAttributes) RequestContextHolder.currentRequestAttributes();
            String uri = requestAttr.getRequest().getRequestURI();
            log.info("方法请求开始: {}  URI: {}", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()), uri);
            //访问目标方法的参数 可动态改变参数值
            Object[] args = joinPoint.getArgs();
            //方法名获取
            String methodName = joinPoint.getSignature().getName();
            log.info("请求方法:{}, 请求参数: {}", methodName, Arrays.toString(args));
    
            Signature signature = joinPoint.getSignature();
            if (!(signature instanceof MethodSignature)) {
                throw new IllegalArgumentException("非法注解");
            }
            //调用实际方法
            Object object = joinPoint.proceed();
    
            //获取执行的方法
            MethodSignature methodSign = (MethodSignature) signature;
            Method method = methodSign.getMethod();
    
    
            Log log_desc = AnnotationUtils.getAnnotation(method, Log.class);
    
            log.info("log描述:{}", log_desc.value());
    
    
            long endTime = System.currentTimeMillis();
            log.info("方法请求结束: {},  URI: {},耗时:{}", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()), uri, endTime - beginTime);
    
            return object;
        }
    
    
    }Controller测试类:
      
    
    package com.mscloudmesh.aop.springbootaoplogs.controller;

    import com.mscloudmesh.aop.springbootaoplogs.annoation.Log;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RequestParam;
    import org.springframework.web.bind.annotation.RestController;

    @RestController
    public class DemoController {

    @GetMapping("/log")
    @Log(value = "请求了测试方法")
    public String test(@RequestParam("param") String param) {
    return param+":aop日志测试";
    }
    }

    springboot主程序类:
      

    package com.mscloudmesh.aop.springbootaoplogs;

    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;

    @SpringBootApplication
    public class SpringbootAopLogsApplication {

    public static void main(String[] args) {
    SpringApplication.run(SpringbootAopLogsApplication.class, args);
    }

    }

    application.yml配置文件:

    server:
    port: 8080
    spring:
    application:
    name: aop-logs

    请求http://localhost:8080/log?param=kevin

    输出日志:
      2020-06-09 23:04:49.793  INFO 10057 --- [nio-8080-exec-1] c.m.a.s.aspect.LogAspect                 : 方法请求开始: 2020-06-09 23:04:49  URI: /log
    2020-06-09 23:04:49.794  INFO 10057 --- [nio-8080-exec-1] c.m.a.s.aspect.LogAspect                 : 请求方法:test, 请求参数: [kevin]
    2020-06-09 23:04:49.803  INFO 10057 --- [nio-8080-exec-1] c.m.a.s.aspect.LogAspect                 : log描述:请求了测试方法
    2020-06-09 23:04:49.803  INFO 10057 --- [nio-8080-exec-1] c.m.a.s.aspect.LogAspect                 : 方法请求结束: 2020-06-09 23:04:49,  URI: /log,耗时:10

  • 相关阅读:
    字符串系列——Immediate Decodability
    Java I/O流操作(四)对象的序列化
    table自动拉伸在chrome与IE中的区别
    【web开发】spring+hibernate4支持中文排序
    SQL批量重命名中文字段名为对应拼音首字母字段名脚本
    Hibernate执行查询后又立马执行了更新(defaultaccess)
    上传图片之上传前预览图片
    挖掘FPTree
    Linux下Json库的编译及代码测试
    C语言中的位运算和逻辑运算
  • 原文地址:https://www.cnblogs.com/mscm/p/13082927.html
Copyright © 2011-2022 走看看