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)

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM