AOP实现系统操作日志

写一篇关于通过AOP实现记录系统日志的文章,便于日后查阅。

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

/**

  • Service注解
  • @return:
  • @author: cjy
  • @date: 2020/9/11 16:50
    */
    @Documented
    @Target({ElementType.METHOD})
    @Retention(RetentionPolicy.RUNTIME)
    public @interface ControllerMonitor {
    String value() default “”;
    }

import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Maps;
import com.xlcloud.business.vip.mapper.log.SystemLogMapper;
import com.xlcloud.business.vip.model.log.SystemLog;
import org.aspectj.lang.ProceedingJoinPoint;
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.beans.factory.annotation.Autowired;
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;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;

/**

  • 系统操作日志 aop

  • @author cjy

  • @create 2020-09-11 16:52
    */
    @Aspect
    @Component
    public class SystemLogAspect {
    private SimpleDateFormat dateFormat = new SimpleDateFormat(“yyyy-mm-dd HH:mm:ss”);

    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    @Autowired
    private SystemLogMapper systemLogMapper;

    @Pointcut("@annotation(com.xlcloud.business.vip.aop.log.ControllerMonitor)")
    public void systemLog() {
    }

    @Around(value = “systemLog()”)
    public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {
    ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
    HttpServletRequest request = attributes.getRequest();
    //1、记录执行时间
    long startTime = System.currentTimeMillis();
    Object result = joinPoint.proceed(joinPoint.getArgs());
    long endTime = System.currentTimeMillis();
    long totalTime = endTime - startTime;
    //2、有无日志监控注解,有则输出
    String methodName = joinPoint.getTarget().getClass().getName() + “.” + joinPoint.getSignature().getName() + “()”;
    MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
    Method targetMethod = methodSignature.getMethod();
    Map<String, Object> map = toMap(request);
    if (targetMethod.isAnnotationPresent(ControllerMonitor.class)) {
    logger.info(“Method: {}, Start: {}, End: {}, Total: {}ms”, methodName, dateFormat.format(startTime), dateFormat.format(endTime), totalTime);
    }
    String operateName = map.get(“operateName”) != null ? String.valueOf(map.get(“operateName”)) : null;
    //3、入系统日志表
    SystemLog systemLog = new SystemLog();
    systemLog.setClientIp(IpUtil.getClientIp(request));
    systemLog.setReqUri(request.getRequestURI());
    systemLog.setMethod(joinPoint.getTarget().getClass().getName() + “.” + joinPoint.getSignature().getName() + “()”);
    // systemLog.setParam(JSONObject.toJSONString(joinPoint.getArgs()));
    systemLog.setParam(JSONObject.toJSONString(map));
    systemLog.setOperator(operateName);
    systemLog.setStartTime(String.valueOf(startTime));
    systemLog.setEndTime(String.valueOf(endTime));
    systemLog.setTotalTime(totalTime == 0 ? null : String.valueOf(totalTime));
    systemLog.setReturnData(JSONObject.toJSONString(result));
    systemLog.setCreateUser(operateName);
    systemLog.setUpdateUser(operateName);
    systemLog.setCreateTime(new Date());
    systemLog.setUpdateTime(new Date());
    systemLog.setIsDelete(0);
    systemLogMapper.insert(systemLog);
    return result;
    }

    private Map<String, Object> toMap(HttpServletRequest request) {
    HashMap map = Maps.newHashMap();
    Enumeration paramNames = request.getParameterNames();
    while (paramNames.hasMoreElements()) {
    String paramName = (String) paramNames.nextElement();
    String[] paramValues = request.getParameterValues(paramName);
    if (paramValues.length == 1) {
    String paramValue = paramValues[0];
    if (paramValue.length() != 0) {
    map.put(paramName, paramValue);
    }
    }
    }
    return map;
    }
    }

import javax.servlet.http.HttpServletRequest;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.UnknownHostException;
import java.util.Enumeration;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**

  • IP工具类

  • @author cjy

  • @create 2020-09-12 10:30
    */
    public class IpUtil {

    /**

    • 检查IP是否合法
    • @param ip
    • @return
      */
      public static boolean ipValid(String ip) {
      String regex0 = “(2[0-4]\d)” + “|(25[0-5])”;
      String regex1 = “1\d{2}”;
      String regex2 = “[1-9]\d”;
      String regex3 = “\d”;
      String regex = “(” + regex0 + “)|(” + regex1 + “)|(” + regex2 + “)|(” + regex3 + “)”;
      regex = “(” + regex + “).(” + regex + “).(” + regex + “).(” + regex + “)”;
      Pattern p = Pattern.compile(regex);
      Matcher m = p.matcher(ip);
      return m.matches();
      }

    /**

    • 获取本地ip 适合windows与linux
    • @return
      */
      public static String getLocalIP() {
      String localIP = “127.0.0.1”;
      try {
      Enumeration netInterfaces = NetworkInterface.getNetworkInterfaces();
      while (netInterfaces.hasMoreElements()) {
      NetworkInterface ni = (NetworkInterface) netInterfaces.nextElement();
      InetAddress ip = ni.getInetAddresses().nextElement();
      if (!ip.isLoopbackAddress() && ip.getHostAddress().indexOf("😊 == -1) {
      localIP = ip.getHostAddress();
      break;
      }
      }
      } catch (Exception e) {
      try {
      localIP = InetAddress.getLocalHost().getHostAddress();
      } catch (UnknownHostException e1) {
      e1.printStackTrace();
      }
      }
      return localIP;
      }

    /**

    • 获取客户机的ip地址
    • @param request
    • @return
      */
      public static String getClientIp(HttpServletRequest request) {
      String ip = request.getHeader(“x-forwarded-for”);
      if (ip == null || ip.length() == 0 || “unknown”.equalsIgnoreCase(ip)) {
      ip = request.getHeader(“Proxy-Client-IP”);
      }
      if (ip == null || ip.length() == 0 || “unknown”.equalsIgnoreCase(ip)) {
      ip = request.getHeader(“WL-Proxy-Client-IP”);
      }
      if (ip == null || ip.length() == 0 || “unknown”.equalsIgnoreCase(ip)) {
      ip = request.getRemoteAddr();
      }
      if (ip == null || ip.length() == 0 || “unknown”.equalsIgnoreCase(ip)) {
      ip = request.getHeader(“http_client_ip”);
      }
      if (ip == null || ip.length() == 0 || “unknown”.equalsIgnoreCase(ip)) {
      ip = request.getHeader(“HTTP_X_FORWARDED_FOR”);
      }
      // 如果是多级代理,那么取第一个ip为客户ip
      if (ip != null && ip.indexOf(",") != -1) {
      ip = ip.substring(ip.lastIndexOf(",") + 1, ip.length()).trim();
      }
      return ip;
      }

    /**

    • 把ip转化为整数
    • @param ip
    • @return
      */
      public static long translateIP2Int(String ip){
      String[] intArr = ip.split("\.");
      int[] ipInt = new int[intArr.length];
      for (int i = 0; i <intArr.length ; i++) {
      ipInt[i] = new Integer(intArr[i]).intValue();
      }
      return ipInt[0] * 256 * 256 * 256 + + ipInt[1] * 256 * 256 + ipInt[2] * 256 + ipInt[3];
      }

    public static void main(String[] args) {
    System.out.println(getLocalIP());
    }
    }

日志表结构设计
字段名 注释 类型 长度 是否必填 是否主键
id 自增ID int 11 是 是
client_ip 客户端ip varchar 100 否 否
req_uri 请求映射路径 varchar 100 否 否
method 方法名 varchar 200 否 否
param 参数 text 0 否 否
operator 操作人姓名 varchar 100 否 否
start_time 接口请求时间 varchar 50 否 否
end_time 接口返回时间 varchar 50 否 否
total_time 总消耗时间 varchar 50 否 否
return_data 接口返回数据 text 0 否 否
gmt_create 创建时间 datatime 0 是 否
gmt_create_user 创建人 varchar 50 是 否
gmt_modified 修改时间 datatime 0 是 否
gmt_modified_user 修改人 varchar 50 是 否
is_delete 是否删除(0:否 1:是) tinyint 2 是 否

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值