Aop實現請求日志記錄功能


環境 SpringBoot2.0 

maven

<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>com.google.code.gson</groupId>
            <artifactId>gson</artifactId>
            <version>2.8.2</version>
        </dependency>

自定義一個注解MyLog

package com.zns.annotation;

import java.lang.annotation.*;

@Target({ ElementType.PARAMETER, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface MyLog
{
    /** 描述 */
    String desc() default "";
}

增加一個切面MyLogAspect

package com.zns.aspect;

import com.google.gson.Gson;
import com.zns.annotation.MyLog;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import java.net.URLDecoder;
import java.util.Arrays;
import java.util.stream.Collectors;

@Aspect
@Component
@EnableAsync
public class MyLogAspect {
    private static final Logger logger = LoggerFactory.getLogger(MyLogAspect.class);

    @Autowired
    private Gson gson;

    /**
     * 用包名的方式定義切入點
     */
    /*@Pointcut("execution(* com.zns.controller.*.*(..))")
    public void pointCut() {
    }*/

    /**
     * 用注解的方式定義切入點
     */
    @Pointcut("@annotation(com.zns.annotation.MyLog)")
    public void pointCut() {
    }

    /**
     * 前置通知
     *
     * @param joinPoint
     */
    @Before("pointCut()")
    public void doBeforeAdvice(JoinPoint joinPoint) {
        //System.out.println("進入方法前執行.....");
    }

    /**
     * 后置異常通知
     */
    @AfterThrowing("pointCut()")
    public void throwss(JoinPoint jp) {
        //System.out.println("方法異常時執行.....");
    }

    /**
     * 后置最終通知,final增強,不管是拋出異常或者正常退出都會執行
     */
    @After("pointCut()")
    public void after(JoinPoint jp) {
        //System.out.println("方法最后執行.....");
    }

    /**
     * 處理完請求,返回內容
     *
     * @param ret
     */
    @AfterReturning(returning = "ret", pointcut = "pointCut()")
    public void doAfterReturning(Object ret) {
        //System.out.println("方法的返回值 : " + ret);
    }

    /**
     * 環繞通知,相當於MethodInterceptor
     */
    @Around("pointCut()")
    public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {
        //請求返回信息
        Object res = null;
        //請求開始時間
        long startTime = System.currentTimeMillis();
        //請求結束時間
        long endTime = 0L;
        //請求時長(毫秒)
        long duration = 0L;
        try {
            //執行方法
            res = joinPoint.proceed();
            endTime = System.currentTimeMillis();
            duration = endTime - startTime;
            return res;
        } finally {
            try {
                //方法執行完成后增加日志
                MethodSignature signature = (MethodSignature) joinPoint.getSignature();
                HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();

                //客戶端操作系統
                String osName = System.getProperty("os.name");
                //客戶端操作系統版本
                String osVersion = System.getProperty("os.version");
                //客戶端瀏覽器的版本類型
                String userAgent = request.getHeader("user-agent");
                //請求ip
                String requestIp = request.getRemoteAddr();
                //請求url
                String requestUrl = request.getRequestURL().toString();
                //請求uri
                String requestUri = request.getRequestURI();
                //請求方式 get,post等
                String requestType = request.getMethod();
                //請求參數
                String requestParam = getParams(joinPoint, request);
                //請求執行的類路徑
                String classPath = signature.getDeclaringTypeName();
                //請求執行的方法名
                String methodName = signature.getName();

                //獲取注解的自定義屬性
                MyLog annotation = signature.getMethod().getAnnotation(MyLog.class);
                String desc = "";
                if (annotation != null) {
                    desc = annotation.desc();
                }

                //輸出
                System.out.println("客戶端操作系統: " + osName);
                System.out.println("客戶端操作系統版本: " + osVersion);
                System.out.println("客戶端瀏覽器的版本類型: " + userAgent);
                System.out.println("請求ip: " + requestIp);
                System.out.println("請求url: " + requestUrl);
                System.out.println("請求uri: " + requestUri);
                System.out.println("請求方式: " + requestType);
                System.out.println("請求參數: " + requestParam);
                System.out.println("請求執行的類路徑: " + classPath);
                System.out.println("請求執行的方法名: " + methodName);
                System.out.println("請求執行的方法描述: " + desc);
                System.out.println("請求開始時間: " + startTime);
                System.out.println("請求結束時間: " + endTime);
                System.out.println("請求時長(毫秒): " + duration);
                System.out.println("請求返回信息: " + gson.toJson(res));

            } catch (Exception e) {
                System.out.println(e.getMessage());
                e.printStackTrace();
            }
        }
    }

    /**
     * 獲取請求參數 支持get,post(含與不含@RequestBody接收都可以獲取)
     *
     * @param joinPoint
     * @param request
     * @return
     * @throws Exception
     */
    public String getParams(JoinPoint joinPoint, HttpServletRequest request) throws Exception {
        String method = request.getMethod();
        String queryString = request.getQueryString();
        String params = "";
        Object[] args = joinPoint.getArgs();
        if (args.length > 0) {
            if ("POST".equals(method)) {
                Object object = args[0];
                //過濾掉 ServletRequest 和 ServletResponse 類型的參數
                Object paramObject = Arrays.stream(args).filter(t -> !(t instanceof ServletRequest) && !(t instanceof ServletResponse)).collect(Collectors.toList());
                params = gson.toJson(paramObject);
            } else if ("GET".equals(method)) {
                params = queryString;
            }
            params = URLDecoder.decode(params, "utf-8");
        }
        return params;
    }

}

 

控制器調用測試

package com.zns.controller;

import com.zns.annotation.MyLog;
import com.zns.bean.Person;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@RestController
public class TestController {
    @RequestMapping(path = "/hello")
    @MyLog(desc = "這是一個hello")
    public String testHello(HttpServletRequest request, HttpServletResponse response) throws Exception {
        return "hello,world";
    }

    @RequestMapping(path = "/query")
    @MyLog(desc = "這是一個查詢")
    public Person query(@RequestBody Person person,HttpServletRequest request, HttpServletResponse response) throws Exception {
        return new Person(person.getId(), person.getName());
    }
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM