系统操作日志实现_JAVA

最近需求需要记录系统日志,在网上查询发现目前有两种主流方式。一种是利用AOP注解实现,一种是利用拦截器实现。

AOP实现的方式更为灵活,但需要为每一个需要记录的方法上加上注解(类似于白名单)。

我这个需求需要记录的是系统操作日志,范围更广,使用拦截器排除特定的Url会更适合(类似于黑名单)。

 

AOP实现系统操作日志及参考文章https://blog.csdn.net/u011521890/article/details/74990338

异常及错误日志参考我的另一篇文章https://blog.csdn.net/weixin_42456466/article/details/89672890

 

拦截器实现系统操作日志:

日志拦截器类

这里我省略了写入数据库dao层的操作,直接用logger日志打印出来。


import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.core.MethodParameter;
import org.springframework.web.context.support.WebApplicationContextUtils;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;
import java.util.HashMap;


public class LogInterceptor implements HandlerInterceptor {
    private final Logger logger = LoggerFactory.getLogger(LogInterceptor.class);

    @Override
    public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object handler) {

        SystemOperationLog log = null;
        try {
            log = LoggerUtil.getLog(httpServletRequest,(HandlerMethod) handler);
        } catch (Exception e) {
            logger.error(e.getLocalizedMessage());
        }
        httpServletRequest.setAttribute(LoggerUtil.LOG_OPERATE, log);
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object handler, ModelAndView modelAndView){

    }

    @Override
    public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object handler, Exception e)  {
        //返回视图时,插入操作日志
        SystemOperationLog log = (SystemOperationLog) httpServletRequest.getAttribute(LoggerUtil.LOG_OPERATE);
        if (log == null) {
            logger.warn("日志信息为空");
        } else {
            HashMap<String, Object> logMap = new HashMap<>(8);
            logMap.put("createTime",log.getCreateTime());
            logMap.put("ip",log.getIp());
            logMap.put("description",log.getDescription());
            logMap.put("operation",log.getOperationType());
            logMap.put("operator",log.getOperator());
            logMap.put("result", null == httpServletRequest.getAttribute("flag"));
            logger.info("执行记录系统操作日志操作{}",logMap);
        }
    }



}

 

loggUtil类

这里我获取方法的描述是通过swagger工具中的value注释获取的,自定义log类中的字段根据你的需求来更改。

import org.apache.commons.lang3.StringUtils;
import org.springframework.web.method.HandlerMethod;
import javax.servlet.http.HttpServletRequest;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;

public class LoggerUtil {
    public static final String LOG_OPERATE = "operation";

    public LoggerUtil() {
    }

    public static SystemOperationLog getLog(HttpServletRequest request, HandlerMethod handler) {

        String description = null;
        Method method = handler.getMethod();
        Annotation[] declaredAnnotations = method.getDeclaredAnnotations();
        for (Annotation annotation : declaredAnnotations) {
            Class<? extends Annotation> clazz = annotation.annotationType();
            if ("io.swagger.annotations.ApiOperation".equals(clazz.getName())) {
                String annotationString = annotation.toString();
                String responseString = annotationString.substring(annotationString.indexOf("response=class"),annotationString.length());
                description = responseString.substring(responseString.indexOf("value=")+6,responseString.length()-1);
                break;
            }
        }


        SystemOperationLog log = new SystemOperationLog();
        log.setIp(LoggerUtil.getClientIp(request));
        log.setOperator("operator");
        log.setOperatorId(request.getHeader("userId"));
        log.setOperationType(handler.getMethod().getName());
        log.setDescription(description);
        log.getParametersMap().putAll(request.getParameterMap());
        return log;
    }


    /**
     * 获取客户端ip地址
     *
     * @param request
     * @return
     */
    public static String getClientIp(HttpServletRequest request) {
        String ip = request.getHeader("X-Real-IP");
        if (!StringUtils.isBlank(ip) && !"unknown".equalsIgnoreCase(ip)) {
            return ip;
        }
        ip = request.getHeader("X-Forwarded-For");
        if (!StringUtils.isBlank(ip) && !"unknown".equalsIgnoreCase(ip)) {
            // 多次反向代理后会有多个IP值,第一个为真实IP。
            int index = ip.indexOf(',');
            if (index != -1) {
                return ip.substring(0, index);
            } else {
                return ip;
            }
        } else {
            return request.getRemoteAddr();
        }
    }

}

配置拦截器拦截规则

排除登录接口


import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;


@Configuration
public class WebMvcConfig extends WebMvcConfigurerAdapter {
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new LogInterceptor()).addPathPatterns("/**").excludePathPatterns("/api/login");
        super.addInterceptors(registry);
    }
}

 

 

自定义log类

import lombok.Data;

import java.sql.Timestamp;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;

@Data
public class SystemOperationLog {

    /**
     * 操作时间
     */
    private String createTime = Timestamp.valueOf(LocalDateTime.now()).toString();

    /**
     *操作员
     */
    private String operator;

    /**
     *操作员id
     */
    private String operatorId;

    /**
     *客户端ip
     */
    private String ip;

    /**
     *操作类型
     */
    private String operationType;

    /**
     *操作描述
     */
    private String description;

    /**
     *传入参数
     */
    private Map<String, String[]> parametersMap = new HashMap<>();

    /**
     *是否操作成功
     */
    private Boolean flag;
}

 

主要是实现 HandlerInterceptor 接口,preHandle方法会在进入调用方法之前执行,afterCompletion会在调用方法结束之后执行。

获取相应的参数途径主要是通过

httpServletRequest.setAttribute("key",Object)方法传参,httpServletRequest.getAttribute(key)方法取参。
(HandlerMethod) handler;Method method = handler.getMethod();通过handler这个参数可以获取被调用的方法及其注解等信息。

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值