AOP- Oriented Programming - Logs

aop notification front, rear notification, return notification, the notification surround execution order:

进入环绕通知
前置通知
Object result=(boolean)jointPoint.proceed();  //执行该方法
退出环绕通知
后置通知
返回通知

Demand: How to slice a log type, the print out client IP, the path request, request parameters, return parameters, the method call time?

We see from the above, we can surround notice achieve common printing parameters.

But consider the following points:

  1. How to obtain the parameters in the surround request notification process;
  2. How to get the client IP;
  3. How to get the request parameters;
  4. How to get return result;

solution

  • Gets the request object
RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) requestAttributes;
HttpServletRequest request = servletRequestAttributes.getRequest();
  • Obtain client IP

[Client] [reaches request IP server load balancing] (e.g. Nginx), and then forwarded to the application server []. The application server by request.getRemoteAddr()the IP method to obtain the time [is] the IP server load balancing. Generally configured in Nginx, [so] the application server can get request.getHeader("X-Forwarded-For")the acquired actual IP client.

To prevent tampering with the IP address must be configured outermost Nginx X-Forwarded-For为$remote_addrget actual IP client, to prevent tampering with X-Forwarded-For parameters.

How to get the server request IP

  private String getIp(HttpServletRequest request) {
        String ip = request.getHeader("X-Forwarded-For");
        if (StringUtils.isNotBlank(ip)) {
            if (!"unKnown".equalsIgnoreCase(ip)) {
                String[] ips = ip.split(",");
                return ips[0];
            }
        }
        ip = request.getHeader("X-Real-IP");
        if (StringUtils.isNotBlank(ip) && !"unKnown".equalsIgnoreCase(ip)) {
            return ip;
        }
        ip = request.getHeader("Proxy-Client-IP");
        if (StringUtils.isNotBlank(ip) && !"unKnown".equalsIgnoreCase(ip)) {
            return ip;
        }
        ip = request.getHeader("WL-Proxy-Client-IP");
        if (StringUtils.isNotBlank(ip) && !"unKnown".equalsIgnoreCase(ip)) {
            return ip;
        }
        //若是没有使用代理,直接获取到服务器请求地址
        String remoteAddr = request.getRemoteAddr();
        return "0:0:0:0:0:0:0:1".equals(remoteAddr) ? "127.0.0.1" : ip;
    }
  • Around advice

Adding spring.xml configuration file:

<!--启动@AspectJ支持-->
<aop:aspectj-autoproxy proxy-target-class="true"/>
package com.springmvc.common.aspect;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;

import org.apache.commons.lang3.StringUtils;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import org.springframework.stereotype.Component;

import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import java.text.SimpleDateFormat;

import java.util.HashMap;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;


/**
 * @ClassName SystemLogAspect
 * @Description 日志切面
 * @Author xueruiye
 * @Date 2019/6/6
 * @Version 1.0
 **/
@Component
@Aspect
public class SystemLogAspect {
    private static final Logger logger = LoggerFactory.getLogger(SystemLogAspect.class);

    //环绕通知
    @Around("execution(public  * com.*.web.*.*(..))")
    public Object doAround(ProceedingJoinPoint pjp) throws Throwable {
        Object result = null;
        Map<String, Object> printLogParamMap = new HashMap<String, Object>();

        try {
            //获取request对象
            RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
            ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) requestAttributes;
            HttpServletRequest request = servletRequestAttributes.getRequest();

            //获取请求的URI地址以及IP地址
            String requestURI = request.getRequestURI();

            //获取完整的url路径()
            //            String requestURL = request.getRequestURL().toString();
            String requestIP = getIp(request);

            //获取切面方法参数
            StringBuilder sb = new StringBuilder();

            if (requestURI.contains("login") ||
                    requestURI.contains("register")) {
                sb.append("[为保护用户隐私,登录时隐藏用户名和密码]");
            } else {
                try {
                    Object[] args = pjp.getArgs();

                    if ((pjp.getArgs() != null) && (pjp.getArgs().length > 0)) {
                        //打印请求参数,但是不打印request、response等参数
                        sb.append("[");

                        int count = 0;

                        for (Object obj : pjp.getArgs()) {
                            count++;

                            String paramType = obj.getClass().getName();

                            if (paramType.contains("HttpServletRequest") ||
                                    paramType.contains("HttpServletResponse") ||
                                    paramType.contains("MyRequestWrapper")) {
                                sb.append(" 参数【").append(count).append("-");
                                sb.append("打印参数类型:").append(paramType)
                                  .append(" ");
                            } else {
                                sb.append(" ").append("参数【" + count + "】—");
                                sb.append("打印参数内容:")
                                  .append(JSONObject.toJSONString(obj))
                                  .append(" ");
                            }
                        }

                        sb.append("]");
                    } else {
                        sb.append("[输入参数为空]");
                    }
                } catch (Exception e) {
                    logger.error("[doAround]获取输入参数失败", e);
                }
            }

            /**
             * 获取拦截方法的返回值-result
             */
            long startTimeMillis = System.currentTimeMillis();
            //获取ResponseVo对象
            result = pjp.proceed();

            long endTimeMillis = System.currentTimeMillis();

            printLogParamMap.put("requestURI", requestURI);
            printLogParamMap.put("clientIP", requestIP);
            printLogParamMap.put("requestParam", sb);
            printLogParamMap.put("responseParam", result);
            printLogParamMap.put("startTimeMillis", startTimeMillis);
            printLogParamMap.put("endTimeMillis", endTimeMillis);
            printLog(printLogParamMap);
        } catch (Exception e) {
            logger.error("操作日志打印失败!", e.getMessage(), e);
        }

        return result;
    }

    /**
     * 日志打印
     * @param printLogParamMap
     */
    private void printLog(Map<String, Object> printLogParamMap) {
        //将毫秒数解析成时间
        Long startTimeMillis = (Long) printLogParamMap.get("startTimeMillis");
        Long endTimeMillis = (Long) printLogParamMap.get("endTimeMillis");
        SimpleDateFormat sdt = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss:SSS");
        String startTime = sdt.format(startTimeMillis);
        String endTime = sdt.format(endTimeMillis);

        StringBuilder soutParam = new StringBuilder();
        soutParam.append("\n").append("客户端IP:")
                 .append(printLogParamMap.get("clientIP"));
        soutParam.append("\n").append("请求路径:")
                 .append(printLogParamMap.get("requestURI"));
        soutParam.append("\n").append("起止时间:")
                 .append(String.format("%s到%s", startTime, endTime));
        soutParam.append("\n").append("请求耗时:")
                 .append(endTimeMillis - startTimeMillis).append("ms");
        soutParam.append("\n").append("输入参数:")
                 .append(printLogParamMap.get("requestParam"));
        soutParam.append("\n").append("输出参数:")
                 .append(JSON.toJSONString(printLogParamMap.get("responseParam")));
        logger.info(soutParam.toString());
    }

    /**
     * 获取请求Ip
     *
     * @param request
     * @return
     */
    private String getIp(HttpServletRequest request) {
        String ip = request.getHeader("X-Forwarded-For");

        if (StringUtils.isNotBlank(ip)) {
            if (!"unKnown".equalsIgnoreCase(ip)) {
                String[] ips = ip.split(",");

                return ips[0];
            }
        }

        ip = request.getHeader("X-Real-IP");

        if (StringUtils.isNotBlank(ip) && !"unKnown".equalsIgnoreCase(ip)) {
            return ip;
        }

        ip = request.getHeader("Proxy-Client-IP");

        if (StringUtils.isNotBlank(ip) && !"unKnown".equalsIgnoreCase(ip)) {
            return ip;
        }

        ip = request.getHeader("WL-Proxy-Client-IP");

        if (StringUtils.isNotBlank(ip) && !"unKnown".equalsIgnoreCase(ip)) {
            return ip;
        }

        //若是没有使用代理,直接获取到服务器请求地址
        String remoteAddr = request.getRemoteAddr();

        return "0:0:0:0:0:0:0:1".equals(remoteAddr) ? "127.0.0.1" : ip;
    }
}

Renderings:

客户端IP:127.0.0.1
请求路径:/springmvc/user
起止时间:2019-06-06 16:06:41:466到2019-06-06 16:06:41:498
请求耗时:32ms
输入参数:[输入参数为空]
输出参数:{"empty":false,"model":{"roleEditFlag":"true","roleInfos":[{"id":2,"roleName":"客服"},{"id":93,"roleName":"销售"}]},"modelMap":{"$ref":"$.model"},"reference":true,"viewName":"success"}

Reproduced in: https: //www.jianshu.com/p/97c3686d0588

Guess you like

Origin blog.csdn.net/weixin_33816946/article/details/91146406