美文网首页
系统添加操作日志配置

系统添加操作日志配置

作者: 初心myp | 来源:发表于2019-07-31 14:03 被阅读0次
目标:

每个系统都会有相应的日志,那么在这里就和大家分享一下,我做过的项目里,操作日志都是怎么记录入库的

首先我们记录的操作日志都是需要落库保存的,所以需要数据库表的支持。我们的实现方式是通过在方法上面加上我们自己写的注解,然后通过切面去获取相应的操作,在进行操作日志落库的。

分享一下数据设计:

create table operate_log
(
   id                   bigint not null auto_increment comment '主键id(自增) ',
   operator_code        varchar(64) not null default '' comment '操作人id',
   operator             varchar(50) not null default '' comment '操作人',
   uri                  varchar(500) not null default '' comment '请求路径',
   operate_ip           varchar(200) not null default '' comment '操作人ip',
   operate_type         varchar(50) not null default '' comment '操作类型',
   operate_desc         varchar(200) not null default '' comment '操作描述',
   request              text not null default '' comment '请求',
   system               varchar(12) not null default '' comment '系统',
   operate_time         datetime not null default CURRENT_TIMESTAMP comment '操作时间',
   primary key (id)
);

然后创建对应的实体类、业务层接口和实现类、持久化层的接口和xml文件,提供新增和查询的方法就可以了。

实现逻辑如下及代码:

第一步:需要自己写一个自定义注解,代码如下:
import com.chuxin.example.common.enums.OperationType;

import java.lang.annotation.*;

/**
 * <p>Description: [自定义注解-系统操作日志 拦截Controller]</p>
 * Created on: 11:38 2018/7/23
 * @author: myp
 */
@Target({ElementType.PARAMETER, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface SystemControllerLog {
    /**
     * 操作描述 业务名称description
     * @return
     */
    String description() default "";

    /**
     * 日志类型(0:操作日志 1:监控日志)
     * @return
     */
    int logType() default 0;

    /**
     * 操作类型 create modify delete
     * @return
     */
    OperationType operationType();
}

OperationType枚举类

package com.chuxin.example.common.enums;

/**
 * <p>Description: [操作日志类型]</p>
 * Created on 2018年11月05日
 * @author <a href="mailto: ***@163.com">myp</a>
 * @version 1.0
 */
public enum OperationType {
    INSERT,UPDATE,QUERY,DELETE
}
第二步:编写切入类
package com.xiaojukeji.fund.service.aspect;

import com.alibaba.fastjson.JSON;
import com.chuxin.example.common.annotation.SystemControllerLog;
import com.chuxin.example.common.util.IpAddressUtil;
import com.chuxin.example.dao.model.OperateLog;
import com.chuxin.example.dao.model.User;
import com.chuxin.example.service.OperateLogService;
import com.chuxin.example.service.UserService;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;
import java.util.Date;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;

/**
 * <p>Description: [切入类]</p>
 * Created on: 12:37 2018/7/23
 * @author: myp
 */
@Component  //将该类加入ioc 容器
@Aspect // 指定该类为切面类
public class SystemLogAspect {
    //注入Service用于把日志保存数据库
    @Resource
    private OperateLogService logService;

    //注入Service用于获取当前登录用户信息
    @Resource
    private UserService userService;

    @Value("${chuxin.example.serverName}")
    private String  serverName;

    //本地异常日志记录对象
    private static final Logger logger = LoggerFactory.getLogger(SystemLogAspect.class);


    //Controller层切点
    @Pointcut("@annotation(com.chuxin.example.common.annotation.SystemControllerLog)")
    public void controllerAspect() {
    }

    /**
     * 前置通知 用于拦截Controller层记录用户的操作
     *
     * @param joinPoint 切点
     */
    @Before("controllerAspect()")
    public void doBefore(JoinPoint joinPoint) {

        HttpServletRequest request = ((ServletRequestAttributes)
                RequestContextHolder.getRequestAttributes()).getRequest();
        //读取登录用户
        User currentUser = userService.getCurrentUser();
        //请求的IP
        String ip = IpAddressUtil.getIpAddress(request);
        try {
            //获取信息
            Map<String, Object> map = getControllerMethodDescription(joinPoint);
            //*========数据库日志=========*//
            OperateLog log = new OperateLog();
            //域账号,直接从登陆信息中获取,现在暂时写死
            log.setOperatorCode(currentUser.getEmplId());
            log.setOperator(currentUser.getEmplName());
            log.setUri(request.getRequestURL().toString());
            log.setOperateIp(ip);
            log.setOperateDesc(map.get("description").toString());
            log.setOperateType(map.get("operationType").toString());
            log.setRequest(getArgs(request, joinPoint));
            log.setOperateTime(new Date());
            log.setSystem(serverName);
            logService.insertSelective(log);
        } catch (Exception e) {
            //记录本地异常日志
            logger.error("存储用户操作日志异常,异常信息:{}", e.getMessage());
        }
    }


    /**
     * 获取注解中对方法的描述信息 用于Controller层注解
     *
     * @param joinPoint 切点
     * @return 方法描述
     * @throws Exception
     */
    public static Map<String, Object> getControllerMethodDescription(JoinPoint joinPoint) throws Exception {
        String targetName = joinPoint.getTarget().getClass().getName();
        String methodName = joinPoint.getSignature().getName();
        Object[] arguments = joinPoint.getArgs();
        Class targetClass = Class.forName(targetName);
        Method[] methods = targetClass.getMethods();
        Map<String, Object> map = new HashMap<>();
        for (Method method : methods) {
            if (method.getName().equals(methodName)) {
                Class[] clazzs = method.getParameterTypes();
                if (clazzs.length == arguments.length) {
                    String description = method.getAnnotation(SystemControllerLog.class).description();
                    Integer logType = method.getAnnotation(SystemControllerLog.class).logType();
                    String operationType = method.getAnnotation(SystemControllerLog.class).operationType().toString();
                    map.put("logType", logType);
                    map.put("operationType", operationType);
                    map.put("description", description);
                    break;
                }
            }
        }
        return map;
    }

    /**
     * Discription:[获取请求参数]
     * @param request 请求对象
     * @return String 请求参数
     * Created on 2018/7/31
     * @author: myp
     */
    public static String getArgs(HttpServletRequest request, JoinPoint joinPoint){
        Enumeration<String> parameterNames = request.getParameterNames();
        Map<String,Object> requestParams = new HashMap<>();
        while (parameterNames.hasMoreElements()){
            String argName = parameterNames.nextElement();
            String value = request.getParameter(argName);
            requestParams.put(argName,value);
        }
        if (requestParams.size()<=0) {
            Object[] args = joinPoint.getArgs();
            for (Object arg : args) {
                if (null == arg) {
                    continue;
                }
                if (arg instanceof HttpServletRequest || arg instanceof HttpServletResponse) {
                    continue;
                }
                String argName = arg.getClass().getName();
                Object value = arg;
                requestParams.put(argName,value);
            }
        }
        return JSON.toJSONString(requestParams);
    }
}

第三步:控制类方法上使用
// 在控制类方法上加该注解即可
@SystemControllerLog(description = "编辑***", operationType = OperationType.UPDATE)

通过以上操作就可以完成操作日志的记录了。


上述代码用到的工具类如下:

import javax.servlet.http.HttpServletRequest;

/**
 * 自定义访问对象工具类
 * <p>
 * 获取对象的IP地址等信息
 *
 * @author myp
 */
public class IpAddressUtil {
    /**未识别*/
    public static final String UNKNOWN = "unknown";

    /**
     * 获取用户真实IP地址,不使用request.getRemoteAddr();的原因是有可能用户使用了代理软件方式避免真实IP地址, 参考文章:
     * http://developer.51cto.com/art/201111/305181.htm
     * <p>
     * 可是,如果通过了多级反向代理的话,X-Forwarded-For的值并不止一个,而是一串IP值,究竟哪个才是真正的用户端的真实IP呢?
     * 答案是取X-Forwarded-For中第一个非unknown的有效IP字符串。
     * <p>
     * 如:X-Forwarded-For:192.168.1.110, 192.168.1.120, 192.168.1.130, 192.168.1.100
     * <p>
     * 用户真实IP为: 192.168.1.110
     *
     * @param request
     * @return
     */
    public static String getIpAddress(HttpServletRequest request) {
        //获取ip
        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.getHeader("HTTP_CLIENT_IP");
        }
        if (ip == null || ip.length() == 0 || UNKNOWN.equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_X_FORWARDED_FOR");
        }
        if (ip == null || ip.length() == 0 || UNKNOWN.equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        return ip;
    }
}

相关文章

  • 系统添加操作日志配置

    目标:每个系统都会有相应的日志,那么在这里就和大家分享一下,我做过的项目里,操作日志都是怎么记录入库的 首先我们记...

  • SpringBoot脱离SpringCloud使用Feign

    快速导航 [添加依赖] 添加依赖 [添加核心配置类] 添加核心配置类TestFeignConfig [添加日志配置...

  • Django日志配置

    日志用于记录或收集系统运行过程中的各种日志信息 在项目配置文件中添加日志器配置 日志一般位于项目根目录下的logs...

  • 【硬派网络计费系统管理】- 系统配置管理

    系统配置主要是对一些系统相关的数据配置,包括数据库,日志配置。 注意,系统配置影响系统的运行状态,所有操作必须由超...

  • 系统添加异常日志配置

    目标:每个系统都会有相应的日志,那么在这里就和大家分享一下,我做过的项目里,异常日志都是怎么记录入库的 首先我们记...

  • 如何优雅地记录操作日志

    操作日志几乎存在于每个系统中,而这些系统都有记录操作日志的一套 API。操作日志和系统日志不一样,操作日志必须要做...

  • Funboot开发:系统日志组件

    系统日志组件 目录 系统日志 使用MongoDb存储日志 系统日志 系统日志分为操作日志、错误日志、登录日志、数据...

  • 07.模型详解 -- 查询函数

    添加测试数据 在SQLyog中执行 配置mysql数据库日志 通过日志文件可以查看对数据库的操作记录,mysql默...

  • 3.23日

    今天老师带我们配置了网络服务器系统,根据步骤进行配置,对文件进行修改添加等操作,在整个过程中对Linux系统的操作

  • elk分析nginx日志

    日志格式示例 nginx日志示例 配置logstash logstash 配置文件 添加pattern_dir ...

网友评论

      本文标题:系统添加操作日志配置

      本文链接:https://www.haomeiwen.com/subject/wuezrctx.html