前言

在做项目得时候需要日志记录,就是操作了那个接口得功能记录以及成功情况和操作id
就在这样的情况下,我做了一个全局日志配置
写的不是很好,大佬忽喷~~~

废话不多说,直接开干

首先我们得去创建一个存储日志得表,我这里存储得东西不duo

SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;

-- ----------------------------
-- Table structure for sys_log
-- ----------------------------
DROP TABLE IF EXISTS `sys_log`;
CREATE TABLE `sys_log`  (
  `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键',
  `url` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '请求得url',
  `method_name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '请求得方法',
  `http_method` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT 'http请求类型',
  `clazz_method` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '请求方法全名称',
  `ip` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '请求ip',
  `request_args` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '请求得参数',
  `response_result` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '返回得状态信息',
  `create_by` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '修改人',
  `create_time` datetime NULL DEFAULT NULL COMMENT '创建时间',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 87 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '日志表' ROW_FORMAT = Dynamic;

SET FOREIGN_KEY_CHECKS = 1;

我们要创建表对应得实体类字段

@Data
@AllArgsConstructor
@NoArgsConstructor
@TableName("sys_log")
public class Log  {
    //主键
    private Long id;
    //请求得url
    private String url;
    //请求得方法
    private String methodName;
    //http请求类型
    private String httpMethod;
    //请求方法全名称
    private String clazzMethod;
    //请求ip
    private String ip;
    //请求得参数
    private String requestArgs;
    // 返回得信息
    private String responseResult;
    //创建时间
    private Date createTime;
    // 创建人
    private String createBy;

}

接下来我们要去创建表对应得mapper层稍后用来存储数据库操作使用

@Mapper
public interface LogMapper extends BaseMapper<Log> {
}

再去创建一个注解用来标注,该接口需要使用日志记录功能

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface  SystemLog {
    String businessName();
}

注意 : 接下里是重点了,我们使用Aop来获取日志

/**
 * @Description: 日志
 * @Author: 沐光
 */
@Component
@Aspect
@Slf4j
public class LogAspect {

    /**
     * @description 定义切入点 后面只要方法上面加上@SystemLog 都需要进行日志打印
     * @author 沐光
     */
    @Pointcut("@annotation(com.muguang.annotation.SystemLog)")
    public void pt(){}

    public Map<String, String> stringMap = new HashMap<>();

    @Autowired
    private LogMapper logMapper;

    @Around("pt()")
    public Object printLog(ProceedingJoinPoint joinPoint) throws Throwable{
        Object ret ;
        try {
            handleBefore(joinPoint);
            ret = joinPoint.proceed();
            handleAfter(ret);
        } finally {
            // 结束后换行 System.lineSeparator():获取系统换行符
            log.info("=======End=======" + System.lineSeparator());
            setSqlLogResult(stringMap);
        }
        return ret;
    }

    /**
     * description 处理打印前的获取信息
     * @author 沐光
     * @param joinPoint
     */
    private void handleBefore(ProceedingJoinPoint joinPoint) throws Throwable {
        // 使用RequestAttributes实现类来获取request请求对象
        ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = requestAttributes.getRequest();

        // 获取被增强方法上的注解对象
        SystemLog systemLog = getSystemLog(joinPoint);
        // 获取sql语句
//        String sql = getSqlStr(joinPoint);
        log.info("=======Start=======");
        // 打印请求 URL
        log.info("URL            : {}",request.getRequestURL());
        // 打印描述信息
        log.info("BusinessName   : {}", systemLog.businessName());
        // 打印 Http method
        log.info("HTTP Method    : {}", request.getMethod());
        // 打印调用 controller 的全路径以及执行方法
        log.info("Class Method   : {}.{}", joinPoint.getSignature().getDeclaringTypeName(), ((MethodSignature) joinPoint.getSignature()).getName());
        // 打印请求的 IP
        log.info("IP             : {}",request.getRemoteHost());
        // 打印请求入参
        log.info("Request Args   : {}", joinPoint.getArgs());

        stringMap.put("url", request.getRequestURL().toString());
        stringMap.put("methodName", systemLog.businessName());
        stringMap.put("httpMethod", request.getMethod());
        stringMap.put("clazzMethod", joinPoint.getSignature().getDeclaringTypeName()+"."+((MethodSignature) joinPoint.getSignature()).getName());
        stringMap.put("ip", request.getRemoteHost());
        stringMap.put("requestArgs", joinPoint.getArgs().toString());
        // 这里获取操作人得方法,大家可以修改一下,因为我这里使用得SpringSecurity框架里面得东西,所有大家根据自己得实际情况来
        // stringMap.put("createBy", SecurityUtils.getUserId().toString());
    }

    /**
     * @description 把aop拦截得MultipartFile类型文件转换为String类型
     * args[i] instanceof ServletRequest || args[i] instanceof ServletResponse ||
     * @author 沐光
     */
    private String filterArgs(ProceedingJoinPoint joinPoint) throws Throwable {
        Object[] args = joinPoint.getArgs();
        byte[] imageByte = null;
        String base64EncoderImg = "";
        Object[] arguments = new Object[args.length];
        for (int i = 0; i < args.length; i++) {
            if ( args[i] instanceof MultipartFile){
                imageByte = ((MultipartFile) args[i]).getBytes();
                BASE64Encoder base64Encoder = new BASE64Encoder();
                base64EncoderImg = base64Encoder.encode(imageByte);
                base64EncoderImg = base64EncoderImg.replaceAll("[\\s\t\n\r]", "");
                return base64EncoderImg;
            }
            arguments[i] = args[i];
        }
        return JSON.toJSONString(arguments);
    }

    /**
     * description 获取方法上注解里面得信息
     * @author 沐光
     */
    private SystemLog getSystemLog(ProceedingJoinPoint joinPoint) {
        MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
        SystemLog systemLog = methodSignature.getMethod().getAnnotation(SystemLog.class);
        return systemLog;
    }

    /**
     * description 处理打印后的获取信息
     * @author 沐光
     * @param ret
     */
    private void handleAfter(Object ret) {
        // 打印出参
        log.info("Response       : {}", JSON.toJSONString(ret));
        stringMap.put("responseResult", JSON.toJSONString(ret));
    }

    /**
     * description 把日志信息存入数据库中
     * @param map 日志信息map
     * @return void
     * @author 沐光
     */
    private void setSqlLogResult(Map<String, String> map){
        map.put("createTime", Utils.getTime());
        Log log = JSONObject.toJavaObject(JSONObject.parseObject(JSON.toJSONString(map)), Log.class);
        logMapper.insert(log);
    }

    /**
     * @description 获取sql语句日志
     * @author 沐光
     */
//    private String getSqlStr(ProceedingJoinPoint joinPoint) {
//        Signature signature = joinPoint.getSignature();
//        if (signature instanceof MethodSignature){
//            MethodSignature methodSignature = (MethodSignature) signature;
//            Class<?> clazz = methodSignature.getDeclaringType();
//            String methodName = methodSignature.getName();
//            Object[] args = joinPoint.getArgs();
//            // 讲args转为map便于解析
//            HashMap<String, Object> paramMap = new HashMap<>();
//            for (int i = 0; i < args.length; i++) {
//                paramMap.put("arg"+i, args[i]);
//            }
//            // 获取sql语句
//            String sql = SqlHelper.getSql(clazz, methodName, paramMap);
//        }
//    }
}

这样就可以把我们得操作日志记录在数据库里面了,写的并不是很好,希望大佬忽喷,也能给出一点意见。