基于Spring Cloud自定义注解 - 登录日志

操作日志代码实现

java 复制代码
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;

import org.springframework.context.annotation.Import;

import com.martian.api.log.common.aspect.SysLogAspect;
import com.martian.api.log.fallback.SysLogApiProviderFallback;

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import({SysLogAspect.class, SysLogApiProviderFallback.class})
public @interface EnableSysLog {

}
java 复制代码
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.annotation.ElementType;


@Documented
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface SysLog {
   String value() default "";
}
java 复制代码
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang.ArrayUtils;
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.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import com.alibaba.fastjson.JSON;
import com.martian.api.log.SysLogApiProvider;
import com.martian.api.log.common.utils.HttpContextUtils;
import com.martian.api.log.common.utils.IPUtils;
import com.martian.common.config.auth.utils.UserContextHolder;
import com.martian.common.config.auth.vo.UserContext;
import com.martian.common.utils.R;

import io.swagger.annotations.ApiOperation;

@Component
@Aspect
public class SysLogAspect {

   @Autowired
   SysLogApiProvider sysLogApiProvider;

   @Pointcut("@annotation(com.martian.api.log.annotation.SysLog)")
   public void logPointCut() {

   }

   @Around("logPointCut()")
   public Object around(ProceedingJoinPoint point) throws Throwable {
      long beginTime = System.currentTimeMillis();
      // 执行方法
      Object result = point.proceed();
      // 执行时长(毫秒)
      long time = System.currentTimeMillis() - beginTime;

      // 保存日志
      saveSysLog(point, time, result);

      return result;
   }

   private void saveSysLog(ProceedingJoinPoint joinPoint, long time, Object result) {

      Map<String, Object> param = new HashMap<String, Object>();

      MethodSignature signature = (MethodSignature) joinPoint.getSignature();
      Method method = signature.getMethod();

      ApiOperation syslog = method.getAnnotation(ApiOperation.class);
      if (syslog != null) {
         // 注解上的描述
         param.put("operation", syslog.value());
      }

      // 请求的方法名
      String className = joinPoint.getTarget().getClass().getName();
      String methodName = signature.getName();
      param.put("method", className + "." + methodName + "()");

      // 请求的参数
      Object[] args = joinPoint.getArgs();
      // HttpServletRequest、MultipartFile等不能序列化,从入参里排除,否则报异常
      Stream<?> stream = ArrayUtils.isEmpty(args) ? Stream.empty() : Arrays.asList(args).stream();
      List<Object> logArgs = stream.filter(arg -> (!(arg instanceof HttpServletRequest)
            && !(arg instanceof HttpServletResponse) && !(arg instanceof MultipartFile)))
            .collect(Collectors.toList());
      try {
         param.put("params", JSON.toJSONString(logArgs));
      } catch (Exception e) {
         param.put("params", args.toString());
      }

      // 获取request
      HttpServletRequest request = HttpContextUtils.getHttpServletRequest();
      // url
      param.put("url", request.getRequestURL().toString());
      // 设置IP地址
      param.put("ip", IPUtils.getIpAddr(request));

      // 用户名
      UserContext user = UserContextHolder.getInstance().getContext();
      if (user != null) {
         param.put("username", user.getUsername());
         param.put("trueName", user.getTrueName());
         param.put("systemType", user.getSystemType());
      }
      if (result != null) {
         // 返回结果
         R r = (R) result;
         param.put("msg", r.getMessage());
         param.put("status", r.getStatus());
      }
      param.put("time", time);
      param.put("createDate", new Date());
      sysLogApiProvider.saveLog(param);

   }

}

Feign远程调用保存日志信息到数据库

java 复制代码
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;

import com.martian.api.log.fallback.SysLogApiProviderFallback;
import com.martian.common.utils.R;

@Component
@FeignClient(name="martian-log-center", fallback = SysLogApiProviderFallback.class)
public interface SysLogApiProvider {
    
    @GetMapping(value="/sys/log/pageList")
    R pageList(@RequestParam Map<String, Object> param); 
    
    @PostMapping(value="/sys/log/save", consumes="application/json")
    R saveLog(@RequestBody Map<String, Object> param);

    @PostMapping(value="/sys/loginLog/save", consumes="application/json")
    R saveLoginLog(Map<String, Object> param);

    @GetMapping(value="/sys/loginLog/pageList")
    R pageListLogin(@RequestParam Map<String, Object> param);

}
java 复制代码
import java.util.Map;
import org.springframework.stereotype.Component;
import com.martian.api.log.SysLogApiProvider;
import com.martian.common.utils.R;
import lombok.extern.slf4j.Slf4j;

@Slf4j
@Component
public class SysLogApiProviderFallback implements SysLogApiProvider {

   @Override
   public R pageList(Map<String, Object> param) {
      log.error("pageList fallback, param={}", param);
      return R.error("martian-log-center not available when list param=" + param);
   }

   @Override
   public R saveLog(Map<String, Object> param) {
      log.error("saveLog fallback, param={}", param);
      return R.error("martian-log-center not available when save param=" + param);
   }

   @Override
   public R saveLoginLog(Map<String, Object> param) {
      log.error("saveLoginLog fallback, param={}", param);
      return R.error("martian-log-center not available when saveLoginLog param=" + param);
   }

   @Override
   public R pageListLogin(Map<String, Object> param) {
      log.error("pageListLogin fallback, param={}", param);
      return R.error("martian-log-center not available when pageList param=" + param);
   }
}
相关推荐
Jaising6669 分钟前
PF4J 日志类冲突与 JVM 类加载机制
jvm·后端
Undoom43 分钟前
智能开发环境下的 Diagram-as-Code 实践:MCP Mermaid 技术链路拆解
后端
计算机毕设VX:Fegn08951 小时前
计算机毕业设计|基于springboot + vue图书借阅管理系统(源码+数据库+文档)
数据库·vue.js·spring boot·后端·课程设计
疯狂的程序猴1 小时前
IPA 深度混淆是什么意思?分析其与普通混淆的区别
后端
cci1 小时前
Remote ssh无法连接?
后端
JohnYan1 小时前
Bun技术评估 - 22 Stream
javascript·后端·bun
饕餮争锋1 小时前
Spring AOP原理简析
java·spring
okseekw2 小时前
Maven从入门到实战:核心概念+配置详解+避坑指南
java·后端
该用户已不存在2 小时前
Node.js后端开发必不可少的7个核心库
javascript·后端·node.js
踏浪无痕2 小时前
计算机算钱为什么会算错?怎么解决?
后端·算法·面试