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());
    }
}

 

转载于:https://www.cnblogs.com/zengnansheng/p/11185459.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值