zoukankan      html  css  js  c++  java
  • SpringBoot使用切面+注解实现对所有请求的日志记录到数据库中

    业务场景:项目拆分微服务,恰巧鄙人负责几个基础的服务,各种对接其他服务。到后期运维,接各种锅:我调用你接口了,你那数据不对。我传递是这个参数,你那处理的有问题......。只好加上日志记录,业务场景就是:防止背锅!

    1.定义注解

    package com.haier.hwork.qwrgqk.business.annotation;
    import java.lang.annotation.*;
    @Target(ElementType.METHOD)
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    public @interface OperationLog {
        String value() default "";
        //1-增删改,2-查询,默认是1
        int type() default 1;
    }

    2.定义AOP

    @Aspect
    @Component
    public class OperationLogAspect {
    
        @Autowired
        private TlOperationLogDao tlOperationLogDao;
    
      //扫描使用这个注解的方法 @Pointcut(
    "@annotation(com.haier.hwork.qwrgqk.business.annotation.OperationLog)") public void logPointCut() {} @Around("logPointCut()") public Object around(ProceedingJoinPoint point) throws Throwable { Date beginTime=new Date(); String result=null; String status=null;
        //执行代码,都加try catch,即使出错也不能影响主进程
    try { Object obj = point.proceed();//放行请求的主进程并拿到返回值 if(obj!=null) { result=JSONObject.toJSONString(obj); } status="success"; return obj; } catch (Exception e) {
            //请求执行出错 result
    =e.getMessage(); status="error"; throw e; } finally {
            //无论成功失败,都保存下日志 saveLog(point, beginTime,
    new Date(), result, status); } }
      //保存日志
    private void saveLog(ProceedingJoinPoint joinPoint, Date beginTime, Date endTime, String result, String status) { TlOperationLog tlOperationLog=new TlOperationLog(); try { MethodSignature signature = (MethodSignature) joinPoint.getSignature(); Method method = signature.getMethod(); OperationLog annotation = method.getAnnotation(OperationLog.class); int type=1;//注解类型 if (annotation != null) { //注解上的描述 tlOperationLog.setOperateModule(annotation.value());
              //注解类型 tlOperationLog.setOperateType(String.valueOf(annotation.type())); type
    =annotation.type(); }
          //记录入参
    if(joinPoint.getArgs()!=null) { try { tlOperationLog.setParam(JSONObject.toJSONString(joinPoint.getArgs())); } catch (Exception e) { e.printStackTrace(); } }
            //如果注解类型是1(增删改)或者是2(查询)报错,记录返回值,如果是查询正常就不记录,有可能返回值太多
    if(type==1 || "error".equals(status)) { tlOperationLog.setResult(result); } tlOperationLog.setStartTime(beginTime);//记录请求开始时间 tlOperationLog.setEndTime(endTime);//记录请求结束时间 tlOperationLog.setStatus(status);//记录执行状态 HttpServletRequest request = HttpContextUtils.getHttpServletRequest(); if (request != null) { tlOperationLog.setUserAgent(request.getHeader(HttpHeaders.USER_AGENT));//记录请求头信息 tlOperationLog.setUserCode(request.getHeader(Constant.HEADER_CURRENT_USER));//获取登录人,登录信息放在了header里 if(request.getRequestURL()!=null) {//记录请求地址 tlOperationLog.setUrl(request.getRequestURL().toString()); } } } catch (Exception e) { e.printStackTrace(); }
        //启动一个线程,执行报错日志,防止影响主请求
    new Thread() { @Override public void run() { try {
                //保存数据到数据库 tlOperationLogDao.insertSelective(tlOperationLog); }
    catch (Exception e) { e.printStackTrace(); } } }.start(); } }

    3.配置需要记录日志的方法

    @PostMapping("/save")
    @OperationLog("新增APP TOKEN管理")
    public BaseResponse save() {
        return ResponseMsgUtil.success(tsSysAppTokenService.save());
    }

    凡是加上OperationLog注解的方法,都会记录日志,注解参数需要一个描述当前方法的字符串,会记录到数据库中。另外还需要参数type,非必填,默认1,代表是增删改,type=2代表查询。
    @OperationLog("新增APP TOKEN管理")
    @OperationLog(value="查询管理客户接口", type=2)
  • 相关阅读:
    python unittest单元测试框架-3用例执行顺序、多级目录、装饰器、fixtures
    python unittest单元测试框架-2discover
    python unittest单元测试框架-1
    python selenium-4自动化测试模型
    python selenium-9 grid模式
    20)PHP,数组的遍历
    19)PHP,数组知识
    18)PHP,可变函数,匿名函数 变量的作用域
    17)PHP,函数基础和参数问题
    16)PHP, set_include_path
  • 原文地址:https://www.cnblogs.com/DreamFather/p/13640093.html
Copyright © 2011-2022 走看看