最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Springboot使用@Aspect、自定義注解記錄日志方式

 更新時間:2024年11月14日 09:55:51   作者:月半花開  
本文介紹了如何使用AOP技術進行日志記錄,包括掃描包和自定義注解兩種方式,掃描包方式通過添加依賴和配置切入點表達式實現(xiàn),自定義注解方式則通過創(chuàng)建自定義注解和AOP切面類來實現(xiàn)方法執(zhí)行時間的統(tǒng)計和記錄

1、前言

日志的作用不言而喻,協(xié)助運維故障排查,問題分析,數(shù)據(jù)統(tǒng)計,記錄查詢等。

  • 故障排查:通過日志可對系統(tǒng)進行實時健康度監(jiān)控,系統(tǒng)日志記錄程序 Syslog 就是為這個目的而設計的。
  • 數(shù)據(jù)分析:通過對業(yè)務系統(tǒng)日志進行關聯(lián)分析,可以掌握業(yè)務系統(tǒng)的整體運行情況,并可通過日志進一步掌握用戶畫像、用戶訪問地域、用戶訪問熱點資源等信息,從而為業(yè)務平臺的市場營銷、銷售策略等提供數(shù)據(jù)支撐。
  • 安全合規(guī)審計:根據(jù)國家網(wǎng)絡安全法等級保護要求,需要對安全設備日志進行集中存儲和分析。
  • 內(nèi)網(wǎng)安全監(jiān)控:很多企業(yè)的信息泄露源于內(nèi)部,使用日志進行用戶行為分析以監(jiān)控內(nèi)網(wǎng)安全,已成為行業(yè)共識。
  • 智能運維:隨著大數(shù)據(jù)時代的到來,數(shù)據(jù)管理和分析方案越來越智能,自動化運維已逐漸普及。機器數(shù)據(jù)作為智能運維的基礎數(shù)據(jù),必將發(fā)揮越來越重要的作用。

日志各位大佬記錄都會,但是規(guī)范有效記錄日志的很少,本文為工具類文章,開箱即用,直接導入項目即可,CV大法一鍵搞定

2、切面方法說明

  • @Aspect -- 作用是把當前類標識為一個切面供容器讀取
  • @Pointcut -- (切入點):就是帶有通知的連接點,在程序中主要體現(xiàn)為書寫切入點表達式
  • @Before -- 標識一個前置增強方法,相當于BeforeAdvice的功能
  • @AfterReturning -- 后置增強,相當于AfterReturningAdvice,方法退出時執(zhí)行
  • @AfterThrowing -- 異常拋出增強,相當于ThrowsAdvice
  • @After -- final增強,不管是拋出異?;蛘哒M顺龆紩?zhí)行
  • @Around -- 環(huán)繞增強,相當于MethodInterceptor

AOP五種通知工作

  • 前置通知:在目標方法調(diào)用之前執(zhí)行,可以獲得切入點信息;
  • 后置通知:在目標方法執(zhí)行后執(zhí)行,目標方法有異常不執(zhí)行;
  • 異常通知:在目標方法拋出異常時執(zhí)行,可以獲取異常信息;
  • 最終通知:在目標方法執(zhí)行后執(zhí)行,無論是否有異常都執(zhí)行;
  • 環(huán)繞通知:最強大的通知類型,在目標方法執(zhí)行前后操作,可以阻止目標方法執(zhí)行。

3、AOP日志記錄方式

aop解決的這個辦法有很多種,這里介紹兩種最簡單、最常用的

  • 掃描包的方式。傳入的參數(shù)在請求頭里面(企業(yè)常用)
  • 自定義注解

3.1、掃描包的方式

1)添加依賴

<--AOP的依賴-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<--JSON的依賴-->
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.2.79</version>
</dependency>
<--mysql-data-jpa的依賴-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<--lombok的依賴-->
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <optional>true</optional>
</dependency>
/**   
 * Copyright ? 2022 eSunny Info. Tech Ltd. All rights reserved.
 * 功能描述:
 * @Title: WebLogAspect.java  
 * @Package com.police.violation.aop  
 * @Description: TODO  
 * @author Administrator   
 * @date 2022年8月31日 上午9:48:11  
 * @version  
 */

package com.police.violation.aop;

import java.util.HashMap;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
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 org.springframework.web.multipart.MultipartFile;

import com.google.gson.Gson;

/**
 * @author www.exception.site (exception 教程網(wǎng))
 * @date 2019/2/12
 * @time 14:03
 * @discription
 **/
@Aspect
@Component
public class WebLogAspect {

	private final static Logger logger = LoggerFactory.getLogger(WebLogAspect.class);

	/** 以 controller 包下定義的所有請求為切入點 */
	@Pointcut("execution(public * com.police.violation.controller..*.*Ticket(..))")
	public void webLog() {
	}

	/**
	 * 在切點之前織入
	 * 
	 * @param joinPoint
	 * @throws Throwable
	 */
	@Before("webLog()")
	public void doBefore(JoinPoint joinPoint) throws Throwable {
		// 開始打印請求日志
		ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
		HttpServletRequest request = attributes.getRequest();

		// 打印請求相關參數(shù)
		logger.info("========================================== Start ==========================================");
		// 打印請求 url
		logger.info("URL            : {}", request.getRequestURL().toString());
		// 打印 Http method
		logger.info("HTTP Method    : {}", request.getMethod());
		// 打印調(diào)用 controller 的全路徑以及執(zhí)行方法
		logger.info("Class Method   : {}.{}", joinPoint.getSignature().getDeclaringTypeName(),
				joinPoint.getSignature().getName());
		// 打印請求的 IP
		logger.info("IP             : {}", request.getRemoteAddr());
		// 打印請求入?yún)?
		logger.info("Request Args   : {}", new Gson().toJson(joinPoint.getArgs()));
	}

	/**
	 * 在切點之后織入
	 * 
	 * @throws Throwable
	 */
	@After("webLog()")
	public void doAfter() throws Throwable {
		logger.info("=========================================== End ===========================================");
		// 每個請求之間空一行
		logger.info("");
	}

	/**
	 * 環(huán)繞
	 * 
	 * @param proceedingJoinPoint
	 * @return
	 * @throws Throwable
	 */
    @Around("webLog()")
    public Object doAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        long startTime = System.currentTimeMillis();
        Object result = proceedingJoinPoint.proceed();
        // 打印出參
        logger.info("Response Args  : {}", new Gson().toJson(result));
        // 執(zhí)行耗時
        logger.info("Time-Consuming : {} ms", System.currentTimeMillis() - startTime);
        return result;
    }


	/**
	 *
	 * @param proceedingJoinPoint 切面
	 * @return
	 * @throws Throwable
	 */
//	@Around("webLog()")
//	public Object doAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
//		long start = System.currentTimeMillis();
//		Object result = proceedingJoinPoint.proceed();
//		logger.info("Request Params       : {}", getRequestParams(proceedingJoinPoint));
//		logger.info("Result               : {}", result);
//		logger.info("Time Cost            : {} ms", System.currentTimeMillis() - start);
//
//		return result;
//	}

	/**
	 * 獲取入?yún)?
	 * 
	 * @param proceedingJoinPoint
	 *
	 * @return
	 */
	private Map<String, Object> getRequestParams(ProceedingJoinPoint proceedingJoinPoint) {
		Map<String, Object> requestParams = new HashMap<>();

		// 參數(shù)名
		String[] paramNames = ((MethodSignature) proceedingJoinPoint.getSignature()).getParameterNames();
		// 參數(shù)值
		Object[] paramValues = proceedingJoinPoint.getArgs();

		for (int i = 0; i < paramNames.length; i++) {
			Object value = paramValues[i];

			// 如果是文件對象
			if (value instanceof MultipartFile) {
				MultipartFile file = (MultipartFile) value;
				// 獲取文件名
				value = file.getOriginalFilename();
			}

			requestParams.put(paramNames[i], value);
		}

		return requestParams;
	}

}

3.2、自定義注解方式

3.2.1.Maven依賴

<!--引入AOP依賴-->
 <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-aop</artifactId>
 </dependency>

3.2.2. 自定義注解

package com.ruoyi.aspect;

import java.lang.annotation.*;
 
/**
 * 統(tǒng)計耗時
 */
@Documented //用于描述其它類型的annotation應該被作為被標注的程序成員的公共API,因此可以被例如javadoc此類的工具文檔化.Documented是一個標記注解,沒有成員.
@Target(ElementType.METHOD) //指定被修飾的Annotation可以放置的位置(被修飾的目標)類,方法,屬性
@Retention(RetentionPolicy.RUNTIME) //定義注解的保留策略, RetentionPolicy.RUNTIME:注解會在class字節(jié)碼文件中存在,在運行時可以通過反射獲取到
public @interface TakeTime {
 
    String methodName() default "";
}

3.2.3. TakeTimeAspect(使用AOP技術統(tǒng)計方法執(zhí)行前后消耗時間)

package com.ruoyi.aspect;

import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
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.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.Date;
 
/**
 * 耗時統(tǒng)計
 */
@Slf4j
@Aspect
@Component
public class TakeTimeAspect {
    //統(tǒng)計請求的處理時間
    ThreadLocal<Long> startTime = new ThreadLocal<>();
    ThreadLocal<Long> endTime = new ThreadLocal<>();
 
    /**
     * 帶有@TakeTime注解的方法
     */
//    @Pointcut("within(com.lwx.backend.user.controller.*)")
//    @Pointcut("execution(* com.lwx.backend.user.controller.*.*(..))")
    @Pointcut("@annotation(com.ruoyi.aspect.TakeTime)")
    public void TakeTime() {
 
    }
 
    //    @Before("within(com.lwx.backend.user.controller.*)")
    @Before("TakeTime()")
    public void doBefore(JoinPoint joinPoint) throws Throwable {
        // 獲取方法的名稱
        String methodName = joinPoint.getSignature().getName();
        // 獲取方法入?yún)?
        Object[] param = joinPoint.getArgs();
        StringBuilder sb = new StringBuilder();
        for (Object o : param) {
            sb.append(o + ";");
        }
        log.info("進入《{}》 方法,參數(shù)為: {}", methodName,sb.toString());
 
        System.out.println("System.currentTimeMillis(): "+System.currentTimeMillis());
        System.out.println("new Date(): "+new Date());
        startTime.set(System.currentTimeMillis());
        log.info("方法開始時間:" +startTime.get());
        //接收到請求,記錄請求內(nèi)容
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
 
        //記錄請求的內(nèi)容
        log.info("請求URL:" + request.getRequestURL().toString());
        log.info("請求METHOD:" + request.getMethod());
    }
 
    //    @AfterReturning(returning = "ret", pointcut = "within(com.lwx.backend.user.controller.*)")
    @AfterReturning(returning = "ret", pointcut = "TakeTime()")
    public void doAfterReturning(Object ret) {
        //處理完請求后,返回內(nèi)容
        log.info("方法返回值:" + JSON.toJSONString(ret));
        endTime.set(System.currentTimeMillis());
        log.info("方法結束時間" +endTime.get());
        log.info("方法結束時間" +new Date());
        log.info("方法執(zhí)行時間:" + (endTime.get() - startTime.get()));
    }
}

3.2.4. 在接口方法上加上注解

@RequestMapping("/loadForTestVariableCategories")
@TakeTime(methodName = "loadForTestVariableCategories")
public void loadForTestVariableCategories(HttpServletRequest req, HttpServletResponse resp) throws Exception {
   KnowledgeBase knowledgeBase = buildKnowledgeBase(req);
   List<VariableCategory> vcs=knowledgeBase.getResourceLibrary().getVariableCategories();
   httpSessionKnowledgeCache.put(req, RuleConstant.VCS_KEY, vcs);
   writeObjectToJson(resp, vcs);
}

3.2.5. 打印查看接口耗時

2022-07-30 22:40:47.057 INFO 16276 --- [nio-8080-exec-2] com.lwx.common.aspect.TakeTimeAspect : 進入《queryUserList》 方法,參數(shù)為: {pageNum=1, pageSize=10, userName=張三};
System.currentTimeMillis(): 1659192047058
new Date(): Sat Jul 30 22:40:47 CST 2022
2022-07-30 22:40:47.058 INFO 16276 --- [nio-8080-exec-2] com.lwx.common.aspect.TakeTimeAspect : 方法開始時間:1659192047058
2022-07-30 22:40:47.059 INFO 16276 --- [nio-8080-exec-2] com.lwx.common.aspect.TakeTimeAspect : 請求URL:http://localhost:8080/user/queryUserList
2022-07-30 22:40:47.059 INFO 16276 --- [nio-8080-exec-2] com.lwx.common.aspect.TakeTimeAspect : 請求METHOD:POST
com.lwx.common.aspect.TakeTimeAspect : 方法返回值:{"data":{"endRow":1,"hasNextPage":false,"hasPreviousPage":false,"isFirstPage":true,"isLastPage":true,"list":[{"comment":"男","userAddress":"廣東","userAge":20,"userBirth":1640966400000,"userId":1,"userName":"張三","userSex":"男"}],"navigateFirstPage":1,"navigateLastPage":1,"navigatePages":8,"navigatepageNums":[1],"nextPage":0,"pageNum":1,"pageSize":10,"pages":1,"prePage":0,"size":1,"startRow":1,"total":1},"message":"success","status":100,"timestamp":1659192047819}
2022-07-30 22:40:47.846 INFO 16276 --- [nio-8080-exec-2] com.lwx.common.aspect.TakeTimeAspect : 方法結束時間1659192047846
2022-07-30 22:40:47.846 INFO 16276 --- [nio-8080-exec-2] com.lwx.common.aspect.TakeTimeAspect : 方法結束時間Sat Jul 30 22:40:47 CST 2022
2022-07-30 22:40:47.846 INFO 16276 --- [nio-8080-exec-2] com.lwx.common.aspect.TakeTimeAspect : 方法執(zhí)行時間:788

注:

  • 如果接口引用的注解失效可能是配置注解的類是在別的包下面
  • 需要在啟動類上設置掃描注解類的包
@SpringBootApplication(scanBasePackages {"com.Lwx.backend","com.Lwx.common"})

總結

以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。

相關文章

  • Maven安裝和配置阿里云鏡像(解決加載慢)

    Maven安裝和配置阿里云鏡像(解決加載慢)

    本文介紹了Maven中配置阿里云鏡像以解決依賴加載慢的問題,包括安裝Maven、配置環(huán)境變量、在IDEA中配置Maven等內(nèi)容,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2024-11-11
  • SpringBoot2零基礎到精通之JUnit 5與指標監(jiān)控

    SpringBoot2零基礎到精通之JUnit 5與指標監(jiān)控

    SpringBoot是一種整合Spring技術棧的方式(或者說是框架),同時也是簡化Spring的一種快速開發(fā)的腳手架,本篇讓我們一起學習JUnit 5與指標監(jiān)控
    2022-03-03
  • springboot集成dubbo過程詳解

    springboot集成dubbo過程詳解

    本文詳細介紹了Spring Boot集成Dubbo的過程,包括多個BeanPostProcessor和初始化器的作用,以及ClassPathBeanDefinitionScanner和DubboClassPathBeanDefinitionScanner的使用方法
    2025-11-11
  • 簡單談談Java中的方法和方法重載

    簡單談談Java中的方法和方法重載

    下面小編就為大家?guī)硪黄唵握務凧ava中的方法和方法重載。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-09-09
  • java基于jdbc實現(xiàn)簡單學生管理系統(tǒng)

    java基于jdbc實現(xiàn)簡單學生管理系統(tǒng)

    本文主要主要介紹了java連接mysql數(shù)據(jù)庫的一個簡單學生系統(tǒng),通過jdbc連接數(shù)據(jù)庫。文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-10-10
  • 如何解決@value獲取不到y(tǒng)aml數(shù)組的問題

    如何解決@value獲取不到y(tǒng)aml數(shù)組的問題

    文章介紹了在使用YAML配置文件時,通過@Value注解獲取整數(shù)和數(shù)組列表的配置方法,并提供了兩種解決方案:一種適用于非嵌套列表,另一種適用于嵌套列表等復雜配置
    2024-11-11
  • Springboot?yml?Map?List讀取方式

    Springboot?yml?Map?List讀取方式

    這篇文章主要介紹了Springboot?yml?Map?List讀取方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-02-02
  • 模仿mybatis-plus實現(xiàn)rpc調(diào)用

    模仿mybatis-plus實現(xiàn)rpc調(diào)用

    這篇文章主要為大家介紹了模仿mybatis-plus實現(xiàn)rpc調(diào)用示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-02-02
  • Spring中property-placeholder的使用與解析詳解

    Spring中property-placeholder的使用與解析詳解

    本篇文章主要介紹了Spring中property-placeholder的使用與解析詳解,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-05-05
  • java開發(fā)Activiti進階篇流程實例詳解

    java開發(fā)Activiti進階篇流程實例詳解

    這篇文章主要為大家介紹了java開發(fā)Activiti進階篇流程實例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-08-08

最新評論

西青区| 张家界市| 靖边县| 天水市| 嫩江县| 志丹县| 永济市| 嵊州市| 馆陶县| 建平县| 广饶县| 洞口县| 江都市| 化隆| 呼和浩特市| 察哈| 大余县| 津南区| 秭归县| 无极县| 龙井市| 友谊县| 道孚县| 建湖县| 井陉县| 新乡市| 永嘉县| 神池县| 鄱阳县| 行唐县| 建湖县| 田东县| 德令哈市| 萨嘎县| 瓦房店市| 乐山市| 成安县| 建瓯市| 麟游县| 寿阳县| 浏阳市|