AOP,請求日誌記錄

實現一,使用log日誌,無差別記錄

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.Arrays;
import java.util.UUID;

/**
 * 記錄http請求日誌。作用aop,對所有的Controller的所有訪求進行攔截。獲取其中參數,進行記錄
 */
@Aspect
@Component
public class WebLogAspect {

    private Logger logger = LoggerFactory.getLogger("httpReqLog");
    //用於計算 該交請求執行的時間
    ThreadLocal<Long> startTime = new ThreadLocal<>();
    //區分一次請求的tonken
    ThreadLocal<String> tonken = new ThreadLocal<>();

    /**
     * 切點,com.tod.ctm.controller包下的所有類的所有方法
     */
    @Pointcut("execution(* com.tod.sgop.controller..*.*(..))")
    public void webLog(){}

    /**
     * controller執行前進行日誌記錄,記錄url和參數
     */
    @Before("webLog()")
    public void doBefore(JoinPoint joinPoint) throws Throwable {
        String uuid = UUID.randomUUID().toString();
        startTime.set(System.currentTimeMillis());
        tonken.set(uuid);
        // 接收到請求,記錄請求內容
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        // 記錄下請求內容
        logger.info("["+uuid+"]  URL : " + request.getRequestURL().toString());
        //logger.info("HTTP_METHOD : " + request.getMethod());
        //logger.info("IP : " + request.getRemoteAddr());
        //logger.info("CLASS_METHOD : " + joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName());
        logger.info("["+uuid+"]  ARGS : " + Arrays.toString(joinPoint.getArgs()));
    }
    /**
     * controller執行後進行日誌記錄,記錄返回參數和執行時間
     */
    @AfterReturning(returning = "ret", pointcut = "webLog()")
    public void doAfterReturning(Object ret) throws Throwable {
        // 處理完請求,返回內容
        logger.info("["+tonken.get()+"]  RESPONSE : " + ret);
        logger.info("["+tonken.get()+"]  SPEND TIME : " + (System.currentTimeMillis() - startTime.get()));
    }


}

 

實現二、存入數據庫,根據請求接口類別來記錄(只記錄接口有OperLog 註解的請求)

import com.tod.bim.annotation.OperLog;
import com.tod.bim.domain.OperationLog;
import com.tod.bim.domain.User;
import com.tod.bim.service.OperationLogService;
import com.tod.bim.service.UserService;
import com.tod.bim.utils.SessionUtil;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * @author zj
 * @version 1.0
 * @functin
 * @date 2020/5/19 10:39
 */
@Aspect
@Component
public class OperLogAspect {


    @Autowired
    private UserService userService;
    @Autowired
    private OperationLogService operationLogService;

    /**
     * 設置操作日誌切入點 記錄操作日誌 在註解的位置切入代碼
     */
    @Pointcut("@annotation(com.tod.bim.annotation.OperLog)")
    public void operLogPoinCut() {
    }

    /**
     * 正常返回通知,攔截用戶操作日誌,連接點正常執行完成後執行, 如果連接點拋出異常,則不會執行
     *
     * @param joinPoint 切入點
     * @param keys      返回結果
     */
    @AfterReturning(value = "operLogPoinCut()", returning = "keys")
    public void saveOperLog(JoinPoint joinPoint, Object keys) {
        // 獲取RequestAttributes
        RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
        // 從獲取RequestAttributes中獲取HttpServletRequest的信息
        HttpServletRequest request = (HttpServletRequest) requestAttributes
                .resolveReference(RequestAttributes.REFERENCE_REQUEST);

        OperationLog operlog = new OperationLog();
        try {
            // 從切面織入點處通過反射機制獲取織入點處的方法
            MethodSignature signature = (MethodSignature) joinPoint.getSignature();
            // 獲取切入點所在的方法
            Method method = signature.getMethod();
            // 獲取操作
            OperLog opLog = method.getAnnotation(OperLog.class);
            if (opLog != null) {
                String operType = opLog.operType().getValue();
                String operDesc = opLog.operDesc();
                operlog.setOperType(operType); // 操作類型
                operlog.setOperDesc(operDesc); // 操作描述
            }
            // 獲取請求的類名
            String className = joinPoint.getTarget().getClass().getName();
            // 獲取請求的方法名
            String methodName = method.getName();
            methodName = className + "." + methodName;

            operlog.setOperMethod(methodName); // 請求方法

            // 請求的參數
            Map<String, String> rtnMap = converMap(request.getParameterMap());
            // 將參數所在的數組轉換成json
            String params = new JSONObject(rtnMap).toString();

            operlog.setOperRequParam(params); // 請求參數
            operlog.setOperRespParam(""); // 返回結果
            User loginUser = SessionUtil.getUserSession();
            operlog.setOperCname(loginUser.getCname());
            operlog.setOperUserName(loginUser.getUsername());
            operlog.setOperRoles(loginUser.getRoleNames());
            operlog.setOperPhone(loginUser.getPhone());

            operlog.setOperIp(request.getRemoteAddr()); // 請求IP
            operlog.setOperUri(request.getRequestURI()); // 請求URI
            operlog.setOperTime(new Date());
            operationLogService.save(operlog);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 轉換request 請求參數
     *
     * @param paramMap request獲取的參數數組
     */
    public Map<String, String> converMap(Map<String, String[]> paramMap) {
        Map<String, String> rtnMap = new HashMap<String, String>();
        for (String key : paramMap.keySet()) {
            rtnMap.put(key, paramMap.get(key)[0]);
        }
        return rtnMap;
    }

    /**
     * 轉換異常信息爲字符串
     *
     * @param exceptionName    異常名稱
     * @param exceptionMessage 異常信息
     * @param elements         堆棧信息
     */
    public String stackTraceToString(String exceptionName, String exceptionMessage, StackTraceElement[] elements) {
        StringBuffer strbuff = new StringBuffer();
        for (StackTraceElement stet : elements) {
            strbuff.append(stet + "\n");
        }
        String message = exceptionName + ":" + exceptionMessage + "\n\t" + strbuff.toString();
        return message;
    }
}

 

import com.tod.bim.enu.OperType;

import java.lang.annotation.*;

/**
 * @author zj
 * @version 1.0
 * @functin 自定義操作日誌註解
 * @date 2020/5/19 10:36
 */
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface OperLog {

    OperType operType() ;  // 操作類型

    String operDesc() default "";  // 操作說明

}

 

/**
 * @author zj
 * @version 1.0
 * @functin
 * @date 2020/5/19 11:39
 */
public enum OperType {
    modify("修改"),
    query("查詢"),
    delete("刪除");
    private String value;

    OperType(String value) {
        this.value = value;
    }

    public String getValue() {
        return value;
    }

    public void setValue(String value) {
        this.value = value;
    }
}

 


    @RequestMapping("/monitoring")
    @ResponseBody
    @OperLog(operType = OperType.query, operDesc = "查詢系統監測信息")
    public AjaxResult monitoring(
            @RequestParam(defaultValue = "10") int pageSize,
            @RequestParam(defaultValue = "0") int pageNo) {

        List<SystemMonitoring> monitoring = systemMonitoringService.monitoring();

        return AjaxResult.ajaxSuccessResult("成功", monitoring);
    }

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章