自定义注解+AOP实现请求日志记录

需求描述:

在所有的接口中记录客户端发送过来的请求。记录信息包括:

  1. 请求链接
  2. 请求类型
  3. 请求IP
  4. 请求描述等…

实现效果:
自定义注解+AOP实现请求日志记录_第1张图片


1、自定义注解

package com.nys.annotation;

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

/**
 * 自定义注解-API监控
 * @author nysheng
 */
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface ApiEyes {
     
    String value() default "";
}


2、AOP实现

package com.nys.aop;

import com.nys.annotation.ApiEyes;
import com.nys.utils.IPUtil;
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.slf4j.Logger;
import org.slf4j.LoggerFactory;
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;

/**
 * AOP实现-切入所有被注解@ApiEyes标记的方法
 * @author nysheng
 */
@Aspect
@Component
public class MyAspect {
     
    //日志记录
    private Logger logger= LoggerFactory.getLogger(MyAspect.class);
    //切入点配置为注解@ApiEyes
    @Pointcut("@annotation(com.nys.annotation.ApiEyes)")
    public void apiEyes(){
     }
    /**
     * 环绕通知
     * @param joinPoint
     * @return
     * @throws Throwable
     */
    @Around("apiEyes()")
    public Object before(ProceedingJoinPoint joinPoint) throws Throwable {
     
        //1.请求开始
        logger.info("=====请求进入======");
        long start=System.currentTimeMillis();
        //2.获取注解对象
        Signature signature = joinPoint.getSignature();
        MethodSignature methodSignature=(MethodSignature)signature;
        Method method = methodSignature.getMethod();
        ApiEyes apiEyes = method.getAnnotation(ApiEyes.class);
        //3.获取注解属性
        String value = apiEyes.value();
        //4.获取request
        ServletRequestAttributes requestAttributes = (ServletRequestAttributes)RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = requestAttributes.getRequest();
        //5.记录日志
        logger.info("请求链接:{}",request.getRequestURL().toString());
        logger.info("请求类型:{}",request.getMethod());
        logger.info("请求IP:{}",IPUtil.getIpAddress(request));
        logger.info("请求描述:{}",value);
        //6.执行
        Object object=joinPoint.proceed();
        //7.请求结束
        long end=System.currentTimeMillis();
        logger.info("请求用时:{}",(end-start));
        logger.info("=====请求结束======");
        return object;
    }
}

3、获取IP

package com.nys.utils;
import javax.servlet.http.HttpServletRequest;

/**
 * IP工具类,获取客户端请求的真实IP地址
 * @author nysheng
 */
public class IPUtil {
     
    public static String getIpAddress(HttpServletRequest request) {
     
        String ip = null;
        //X-Forwarded-For:Squid 服务代理
        String ipAddresses = request.getHeader("X-Forwarded-For");
        if (ipAddresses == null || ipAddresses.length() == 0 || "unknown".equalsIgnoreCase(ipAddresses)) {
     
            //Proxy-Client-IP:apache 服务代理
            ipAddresses = request.getHeader("Proxy-Client-IP");
        }
        if (ipAddresses == null || ipAddresses.length() == 0 || "unknown".equalsIgnoreCase(ipAddresses)) {
     
            //WL-Proxy-Client-IP:weblogic 服务代理
            ipAddresses = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ipAddresses == null || ipAddresses.length() == 0 || "unknown".equalsIgnoreCase(ipAddresses)) {
     
            //HTTP_CLIENT_IP:有些代理服务器
            ipAddresses = request.getHeader("HTTP_CLIENT_IP");
        }
        if (ipAddresses == null || ipAddresses.length() == 0 || "unknown".equalsIgnoreCase(ipAddresses)) {
     
            //X-Real-IP:nginx服务代理
            ipAddresses = request.getHeader("X-Real-IP");
        }

        //有些网络通过多层代理,那么获取到的ip就会有多个,一般都是通过逗号(,)分割开来,并且第一个ip为客户端的真实IP
        if (ipAddresses != null && ipAddresses.length() != 0) {
     
            ip = ipAddresses.split(",")[0];
        }

        //还是不能获取到,最后再通过request.getRemoteAddr();获取
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ipAddresses)) {
     
            ip = request.getRemoteAddr();
        }
        return ip.equals("0:0:0:0:0:0:0:1")?"127.0.0.1":ip;
    }
}


4、使用方法

直接在要监听的方法上加上@ApiEyes注解即可
自定义注解+AOP实现请求日志记录_第2张图片


注:SSM环境需要在Spring配置文件中加入

<context:component-scan base-package="com.nys"/>

<aop:aspectj-autoproxy proxy-target-class="true" />

相关:
https://mp.weixin.qq.com/s/zjn_lrnSLmswqH-Txvr5eg

你可能感兴趣的:(编程技术,SSM,aop,注解)