纷析云开源版- Springboot-增加操作日志接口

发布于:2025-02-22 ⋅ 阅读:(13) ⋅ 点赞:(0)

操作日志切面

package cn.gson.financial.aspect;

import cn.gson.financial.Utils.IpUtils;
import cn.gson.financial.base.BaseCrudController;
import cn.gson.financial.exception.ExceptionUtils;
import cn.gson.financial.kernel.controller.JsonResult;
import cn.gson.financial.kernel.enums.EventStatusEnum;
import cn.gson.financial.kernel.enums.LogLevelEnum;
import cn.gson.financial.kernel.model.vo.UserVo;
import cn.gson.financial.log.LogOperation;
import cn.gson.financial.kernel.model.dto.SysWebLogDTO;
import cn.gson.financial.kernel.service.SysWebLogService;
import com.alibaba.fastjson.JSON;
import com.google.gson.Gson;
import lombok.extern.slf4j.Slf4j;
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.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.Date;

/**
 * 操作日志切面
 */
@Slf4j
@Aspect
@Component
public class OperationLogAspect extends BaseCrudController{

    @Autowired
    private SysWebLogService saveLogService;

    @Autowired
    private HttpServletRequest request;

    // 定义切入点,拦截所有带有 @LogOperation 注解的方法
    @Pointcut("@annotation(cn.gson.financial.log.LogOperation)")
    public void logOperationPointCut() {}

    // 在目标方法执行前记录操作日志
    @Around("logOperationPointCut()")
    public Object logOperation(ProceedingJoinPoint joinPoint) throws Throwable {

        System.out.println("进入操作日志切面");
        // 后端接收时间
        long beginTime = System.currentTimeMillis();
        try {
        //执行方法
        Object result = joinPoint.proceed();

        //执行时长(毫秒)
        long time = System.currentTimeMillis() - beginTime;
        //保存日志
        if (!(result instanceof JsonResult)) {
            saveLog(joinPoint, beginTime, time, LogLevelEnum.INFO, EventStatusEnum.SUCCESS, result, null);
            return result;
        }

        JsonResult formatResult = (JsonResult) result;
        if (formatResult.isSuccess()) {
            saveLog(joinPoint, beginTime, time, LogLevelEnum.INFO, EventStatusEnum.SUCCESS, result, null);
            return result;
        }
        saveLog(joinPoint, beginTime, time, LogLevelEnum.ERROR, EventStatusEnum.FAIL, result, null);
        return result;

        } catch (Exception e) {
            //执行时长(毫秒)
            long time = System.currentTimeMillis() - beginTime;
            //保存日志
            saveLog(joinPoint, beginTime, time, LogLevelEnum.EXCEPTION, EventStatusEnum.FAIL, null, e);
            log.error("", e);
            throw e;
        }
    }
    void saveLog(ProceedingJoinPoint joinPoint, long beginTime, long time, LogLevelEnum logLevelEnum, EventStatusEnum eventStatusEnum, Object result, Exception e){
        // 创建操作日志对象
        SysWebLogDTO log = new SysWebLogDTO();

        // 获取当前操作用户
        Object object= request.getSession().getAttribute("user");
        Gson gson = new Gson();
        String json = gson.toJson(object);

        UserVo userVO =  gson.fromJson( json, UserVo.class);
        if(userVO != null){
            long uiserId = userVO.getId();
            log.setCreator(uiserId);
            log.setCreatorName(userVO.getRealName());
            log.setCreatorAccount(userVO.getMobile());
        }

        // 获取操作日志注解
        LogOperation annotation = ((MethodSignature) joinPoint.getSignature()).getMethod().getAnnotation(LogOperation.class);
        if(annotation != null){
            // 获取操作类型和描述
            log.setLogTypeId(annotation.operationType().value());
            log.setLogTypeName(annotation.operationType().desc());
            log.setEventTypeName(annotation.description());
        }
        //日志级别
        log.setLogLevelId(logLevelEnum.value());
        log.setLogLevelName(logLevelEnum.desc());

        // 获取请求的 URL
        log.setRequestUri(request.getRequestURI());
        // 获取用户 IP 地址
        log.setRequestTime((int)time);
        log.setUserAgent(request.getHeader(HttpHeaders.USER_AGENT));
        log.setIp(IpUtils.getFirstIpAddr(request));

        //创建时间
        Instant instant = LocalDateTime.now().atZone(ZoneId.systemDefault()).toInstant();
        Date date= Date.from(instant);
        log.setCreateDate(date);
        if (result != null) {
            log.setResponseParams(JSON.toJSONString(result));
        }
        //请求头内容
        String machineName = request.getHeader("machineName");
        if (StringUtils.isNotBlank(machineName)) {
            log.setMachineName(machineName);
        }
        String macAddress = request.getHeader("macAddress");
        if (StringUtils.isNotBlank(macAddress)) {
            log.setMacAddress(macAddress);
        }
        log.setStatus(eventStatusEnum.value());

        if (e != null) {
            log.setErrorInfo(ExceptionUtils.getErrorStackTrace(e));
        }

        // 保存操作日志
        saveLogService.saveLog(log);
    }
}


package cn.gson.financial.log;

import cn.gson.financial.enums.LogTypeEnum;

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

@Target(ElementType.METHOD)  // 该注解作用于方法
@Retention(RetentionPolicy.RUNTIME)  // 运行时可用
public @interface LogOperation {
    LogTypeEnum operationType() default LogTypeEnum.MANAGER;
    String description() default "";
}


Exception工具类

package cn.gson.financial.exception;

import lombok.extern.slf4j.Slf4j;

import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;

/**
 * Exception工具类
 *
 * @author Mark sunlightcs@gmail.com
 */
@Slf4j
public class ExceptionUtils {
    private ExceptionUtils() {
        throw new UnsupportedOperationException();
    }

    /**
     * 获取异常信息
     * @param ex  异常
     * @return    返回异常信息
     */
    public static String getErrorStackTrace(Exception ex){
        try (StringWriter sw = new StringWriter();
            PrintWriter pw = new PrintWriter(sw, true)) {
            ex.printStackTrace(pw);
            return sw.toString();
        } catch (IOException ie) {
            log.error(ie.getMessage(),ie);
        }
        return null;
    }
}

IP工具类

package cn.gson.financial.Utils;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

import javax.servlet.http.HttpServletRequest;

/**
 * IP工具类
 *
 * @author Mark sunlightcs@gmail.com
 * @since 1.0.0
 */
@Slf4j
public class IpUtils {
    private IpUtils() {
        throw new UnsupportedOperationException();
    }

    public static String getIpAddr(HttpServletRequest request) {
    	String ip = null;
        try {
            String str = "unknown";
            ip = request.getHeader("x-forwarded-for");
            if (StringUtils.isEmpty(ip) || str.equalsIgnoreCase(ip)) {
                ip = request.getHeader("Proxy-Client-IP");
            }
            if (StringUtils.isEmpty(ip) || ip.length() == 0 || str.equalsIgnoreCase(ip)) {
                ip = request.getHeader("WL-Proxy-Client-IP");
            }
            if (StringUtils.isEmpty(ip) || str.equalsIgnoreCase(ip)) {
                ip = request.getHeader("HTTP_CLIENT_IP");
            }
            if (StringUtils.isEmpty(ip) || str.equalsIgnoreCase(ip)) {
                ip = request.getHeader("HTTP_X_FORWARDED_FOR");
            }
            if (StringUtils.isEmpty(ip) || str.equalsIgnoreCase(ip)) {
                ip = request.getRemoteAddr();
            }
        } catch (Exception e) {
            log.error(e.getMessage(),e);
        }
        
        return ip;
    }

    public static String getFirstIpAddr(HttpServletRequest request) {
        String ip = getIpAddr(request);
        if (StringUtils.isBlank(ip)) {
            return ip;
        }
        return ip.split(",")[0];
    }
}

接口增加注解

 @LogOperation(operationType = LogTypeEnum.MANAGER, description = "部门列表查询")

日志类型枚举

package cn.gson.financial.enums;

/**
 * 日志类型枚举
 */
public enum LogTypeEnum //日志类型
{

    APP(1, "APP"),

    MANAGER(2, "管理后端"),
    CLIENT(3, "第三方");

    private int value;

    private String desc;

    LogTypeEnum(int value, String desc) {
        this.desc = desc;
        this.value = value;
    }

    public int value() {
        return this.value;
    }

    public String desc() {
        return this.desc;
    }
}



package cn.gson.financial.kernel.enums;

/**
 * 事件状态枚举
 */
public enum EventStatusEnum //事件状态
{

    FAIL(0, "失败"),

    SUCCESS(1, "成功");

    private int value;

    private String desc;

    EventStatusEnum(int value, String desc) {
        this.desc = desc;
        this.value = value;
    }

    public int value() {
        return this.value;
    }

    public String desc() {
        return this.desc;
    }
}



package cn.gson.financial.kernel.enums;

/**
 * 日志级别枚举
 */
public enum LogLevelEnum //日志级别
{

    INFO(1, "信息"),

    ERROR(2, "错误"),

    EXCEPTION(3, "异常");

    private int value;

    private String desc;

    LogLevelEnum(int value, String desc) {
        this.desc = desc;
        this.value = value;
    }

    public int value() {
        return this.value;
    }

    public String desc() {
        return this.desc;
    }
}

日志保存

@Slf4j
@Service
@AllArgsConstructor
public class SysWebLogServiceImpl extends ServiceImpl<SysWebLogMapper, SysWebLog> implements SysWebLogService {
    @Override
    public void saveLog(SysWebLogDTO log) {
        SysWebLog sysWebLog = ConvertUtils.sourceToTarget(log, SysWebLog.class);
        sysWebLog.setId(IdWorker.getId());
        baseMapper.insert(sysWebLog);
    }
}

日志分页查询

@GetMapping("PageList")
    public JsonResult PageList(@RequestParam Map<String, String> params) {
        System.out.println("操作日志查询接口");
        //查询条件
        QueryWrapper qw = Wrappers.query();
        //时间
        String minDate = (String) params.get("minDate");
        String maxDate = (String) params.get("maxDate");
        qw.ge(StringUtils.isNotBlank(minDate),"create_date", minDate);
        qw.le(StringUtils.isNotBlank(maxDate),"create_date", maxDate);
        this.setQwAccountSetsId(qw);
        //分页数据
        Map<String, String> paramPage = new HashMap<>();
        paramPage.put("page",params.get("page"));
        paramPage.put("size",params.get("size"));
        JsonResult jsonResult = this.getPageList(paramPage,service);
        return jsonResult;
    }