基于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);
   }
}
相关推荐
某鹏39 分钟前
网关选型:Go、Java、Graal 谁都不能完胜
后端
用户0247836530971 小时前
从屎山到防线:14 行状态迁移表,给任务系统装上防瞎跳闸门
后端
CQU_JIAKE1 小时前
11.13[体系结构】指标,五级流水线,八级流水线,虚实地址思考
后端
panbook3 小时前
从0到1实现一个分布式时序数据库(三):主从复制、故障检测与切换
后端
上线再说3 小时前
图片从 8.2MB 压到 296KB:我把小程序图片链路的账单拆了一遍
后端
dpharness3 小时前
我原以为 MCP 装完就能用,直到工具列表是空的
后端
dpharness3 小时前
153 个 MCP 服务,我把工具数一个个数了一遍
后端
打工仔折腾 AI6 小时前
Changedetection.io 网页变动监控:Docker 部署、通知配置与公网暴露实践
运维·人工智能·后端·python·docker·容器·性能优化
SomeOtherTime6 小时前
Rust 闭包语法和原理(AI回答)
开发语言·后端·rust