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

基于Spring AOP的Log收集匯總

 更新時(shí)間:2024年10月24日 14:29:53   作者:不惑_  
張三針對(duì)公司現(xiàn)有日志處理系統(tǒng)的不足,采用了SpringAOP技術(shù)和Redis存儲(chǔ),設(shè)計(jì)并實(shí)現(xiàn)了一個(gè)性能更高效的日志處理系統(tǒng),該系統(tǒng)通過(guò)SpringAOP的切面攔截功能,捕獲方法調(diào)用信息作為日志內(nèi)容,并將其統(tǒng)一格式化后存儲(chǔ)到Redis中

前情提要 ??

張三對(duì)于公司的日志處理系統(tǒng)不滿意,認(rèn)為其性能不佳且功能有限。為了展示自己的能力和技術(shù)實(shí)力,他決定利用Spring AOP(面向切面編程)開發(fā)一個(gè)更高效的日志處理系統(tǒng),并將其存儲(chǔ)在Redis中。

首先,張三分析了現(xiàn)有日志處理系統(tǒng)的不足之處,如性能瓶頸、日志格式不統(tǒng)一、存儲(chǔ)容量有限等。然后,他開始著手設(shè)計(jì)和實(shí)現(xiàn)一個(gè)新的日志處理系統(tǒng)。

?? 使用Spring AOP進(jìn)行日志攔截:張三利用Spring AOP的切面功能,為需要記錄日志的方法添加了一個(gè)切面。在這個(gè)切面中,他可以捕獲方法的調(diào)用信息,如方法名、參數(shù)、返回值等,并將這些信息作為日志內(nèi)容。

?? 日志格式化:為了確保日志的一致性和可讀性,張三設(shè)計(jì)了一種統(tǒng)一的日志格式。他將日志分為不同的級(jí)別,如DEBUG、INFO、WARN和ERROR,并為每個(gè)級(jí)別設(shè)置了不同的顏色和標(biāo)簽。

?? Redis存儲(chǔ):張三選擇將日志存儲(chǔ)在Redis中,因?yàn)镽edis是一個(gè)高性能的鍵值存儲(chǔ)系統(tǒng),適合存儲(chǔ)大量的日志數(shù)據(jù)。他為每個(gè)日志級(jí)別創(chuàng)建了一個(gè)Redis列表,用于存儲(chǔ)相應(yīng)級(jí)別的日志。同時(shí),他還設(shè)置了一個(gè)定時(shí)任務(wù),定期清理過(guò)期的日志數(shù)據(jù),以保持存儲(chǔ)空間的整潔。

?? 監(jiān)控與告警:為了方便監(jiān)控日志系統(tǒng)的運(yùn)行狀況,張三還開發(fā)了一個(gè)簡(jiǎn)單的監(jiān)控界面,可以實(shí)時(shí)查看各個(gè)日志級(jí)別的數(shù)量、存儲(chǔ)空間使用情況等信息。此外,他還設(shè)置了一些告警規(guī)則,當(dāng)某個(gè)日志級(jí)別的數(shù)量超過(guò)閾值時(shí),會(huì)自動(dòng)發(fā)送告警通知給相關(guān)人員。

經(jīng)過(guò)一段時(shí)間的努力,張三成功地完成了這個(gè)基于Spring AOP的日志處理系統(tǒng),并將其部署到了生產(chǎn)環(huán)境。公司同事對(duì)他的工作表示贊賞,認(rèn)為這個(gè)新的日志處理系統(tǒng)不僅提高了性能,還提供了更多有用的功能。這無(wú)疑突顯了張三的技術(shù)能力和對(duì)公司的貢獻(xiàn)。

以下是一個(gè)簡(jiǎn)化的代碼實(shí)現(xiàn)示例,展示了如何使用Spring AOP和Redis來(lái)實(shí)現(xiàn)日志處理系統(tǒng)。

場(chǎng)景實(shí)現(xiàn) ??

?? 創(chuàng)建一個(gè)日志切面類**LoggingAspect**

在此過(guò)程中,我們創(chuàng)建了一個(gè)日志切面類LoggingAspect,它會(huì)攔截指定包路徑下的所有方法調(diào)用。在方法調(diào)用完成后,它會(huì)將方法的調(diào)用信息(如方法名、參數(shù)、返回值等)作為日志內(nèi)容,并將這些信息傳遞給LogService進(jìn)行處理。

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.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Aspect
@Component
public class LoggingAspect {
    @Autowired
    private LogService logService;
    @Pointcut("execution(* com.example.service.*.*(..))")
    public void logPointcut() {}
    @AfterReturning(pointcut = "logPointcut()", returning = "result")
    public void logAfterReturning(JoinPoint joinPoint, Object result) {
        logService.log(joinPoint, result);
    }
}

?? 創(chuàng)建一個(gè)日志服務(wù)類**LogService****:**

LogService負(fù)責(zé)將日志內(nèi)容存儲(chǔ)到Redis中。在這個(gè)示例中,我們使用了RedisTemplate來(lái)操作Redis。我們將日志內(nèi)容存儲(chǔ)在名為log的Redis列表中。

import org.aspectj.lang.JoinPoint;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
@Service
public class LogService {
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;
    public void log(JoinPoint joinPoint, Object result) {
        String methodName = joinPoint.getSignature().getName();
        Object[] args = joinPoint.getArgs();
        String logMessage = String.format("Method: %s, Args: %s, Result: %s", methodName, Arrays.toString(args), result);
        // 將日志存儲(chǔ)到Redis
        redisTemplate.opsForList().rightPush("log", logMessage);
    }
}

還可以為不同級(jí)別的日志創(chuàng)建不同的Redis列表:

public class LogService {
    // ...
    public void log(JoinPoint joinPoint, Object result, LogLevel logLevel) {
        String methodName = joinPoint.getSignature().getName();
        Object[] args = joinPoint.getArgs();
        String logMessage = String.format("Method: %s, Args: %s, Result: %s", methodName, Arrays.toString(args), result);
        // 根據(jù)日志級(jí)別將日志存儲(chǔ)到不同的Redis列表中
        String redisKey = "log:" + logLevel.name().toLowerCase();
        redisTemplate.opsForList().rightPush(redisKey, logMessage);
    }
}

也可以修改日志格式化:

public class LogService {
    // ...
    public void log(JoinPoint joinPoint, Object result, LogLevel logLevel) {
        String methodName = joinPoint.getSignature().getName();
        Object[] args = joinPoint.getArgs();
        String logMessage = String.format("[%s] Method: %s, Args: %s, Result: %s", logLevel, methodName, Arrays.toString(args), result);
        // 根據(jù)日志級(jí)別將日志存儲(chǔ)到不同的Redis列表中
        String redisKey = "log:" + logLevel.name().toLowerCase();
        redisTemplate.opsForList().rightPush(redisKey, logMessage);
    }
}

?? 配置RedisTemplate:

最后,我們配置了一個(gè)RedisTemplate Bean,用于序列化和反序列化Redis的key和value值。這樣,我們就可以將日志內(nèi)容以結(jié)構(gòu)化的方式存儲(chǔ)在Redis中,并在需要時(shí)方便地進(jìn)行查詢和分析。

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
@Configuration
public class RedisConfig {
    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(factory);
        // 使用Jackson2JsonRedisSerializer來(lái)序列化和反序列化redis的value值
        GenericJackson2JsonRedisSerializer genericJackson2JsonRedisSerializer = new GenericJackson2JsonRedisSerializer();
        template.setValueSerializer(genericJackson2JsonRedisSerializer);
        template.setHashValueSerializer(genericJackson2JsonRedisSerializer);
        // 使用StringRedisSerializer來(lái)序列化和反序列化redis的key值
        StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
        template.setKeySerializer(stringRedisSerializer);
        template.setHashKeySerializer(stringRedisSerializer);
        template.afterPropertiesSet();
        return template;
    }
}

?? 定時(shí)任務(wù):

我們創(chuàng)建了一個(gè)定時(shí)任務(wù)LogCleanupTask,它會(huì)定期清理過(guò)期的日志數(shù)據(jù)。我們使用了Spring的@Scheduled注解來(lái)實(shí)現(xiàn)定時(shí)任務(wù),并使用RedisTemplate來(lái)操作Redis。在cleanupLogs方法中,我們遍歷所有的日志列表,并根據(jù)日志的時(shí)間戳判斷它們是否過(guò)期。如果過(guò)期,則將其從Redis中移除。

import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
@Component
public class LogCleanupTask {
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;
    @Scheduled(cron = "0 0 * * * ?") // 每小時(shí)執(zhí)行一次
    public void cleanupLogs() {
        // 清理過(guò)期的日志數(shù)據(jù),例如保留最近7天的日志
        String redisKeyPattern = "log:*";
        Set<String> keys = redisTemplate.keys(redisKeyPattern);
        for (String key : keys) {
            List<Object> logs = redisTemplate.opsForList().range(key, 0, -1);
            List<Object> logsToRemove = logs.stream()
                    .filter(log -> isExpired(log))
                    .collect(Collectors.toList());
            redisTemplate.opsForList().remove(key, 0, logsToRemove);
        }
    }
    private boolean isExpired(Object log) {
        // 判斷日志是否過(guò)期,例如根據(jù)日志的時(shí)間戳和當(dāng)前時(shí)間進(jìn)行比較
        // ...
    }
}

?? 監(jiān)控界面:

我們創(chuàng)建了一個(gè)監(jiān)控界面LogMonitorController,它可以實(shí)時(shí)查看日志數(shù)據(jù)。我們使用了Spring的@RestController注解來(lái)創(chuàng)建一個(gè)RESTful API,并使用RedisTemplate來(lái)操作Redis。在getLogs方法中,我們遍歷所有的日志列表,并將它們以JSON格式返回給客戶端。客戶端可以使用這些數(shù)據(jù)來(lái)實(shí)時(shí)監(jiān)控日志系統(tǒng)的運(yùn)行狀況。

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class LogMonitorController {
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;
    @GetMapping("/monitor/logs")
    public Map<String, Object> getLogs() {
        Map<String, Object> logs = new HashMap<>();
        String redisKeyPattern = "log:*";
        Set<String> keys = redisTemplate.keys(redisKeyPattern);
        for (String key : keys) {
            List<Object> logList = redisTemplate.opsForList().range(key, 0, -1);
            logs.put(key, logList);
        }
        return logs;
    }
}

??? 請(qǐng)注意!??! 這個(gè)示例僅用于演示如何使用Spring AOP和Redis實(shí)現(xiàn)日志處理系統(tǒng)。在實(shí)際項(xiàng)目中,需要根據(jù)具體需求進(jìn)行更多的定制和優(yōu)化。例如,可以為不同級(jí)別的日志創(chuàng)建不同的Redis列表,以便更好地管理和查詢?nèi)罩緮?shù)據(jù)。此外,還可以考慮使用更高級(jí)的日志框架,如Logback或Log4j2,以實(shí)現(xiàn)更豐富的日志功能和更好的性能。

Get知識(shí)點(diǎn) ??

?? AOP概念:AOP(面向切面編程)是一種編程范式,它允許開發(fā)者在不修改原有代碼的情況下,對(duì)程序的某些方面進(jìn)行增強(qiáng)。AOP通過(guò)將橫切關(guān)注點(diǎn)(如日志記錄、事務(wù)管理、權(quán)限控制等)與業(yè)務(wù)邏輯分離,使得代碼更加模塊化和可維護(hù)。

?? Spring AOP:Spring AOP是Spring框架中的一個(gè)重要組件,它提供了聲明式的AOP支持。Spring AOP使用代理模式來(lái)實(shí)現(xiàn)AOP,可以通過(guò)JDK動(dòng)態(tài)代理或CGLIB代理來(lái)創(chuàng)建代理對(duì)象。Spring AOP支持多種類型的切面,如前置通知、后置通知、異常通知、環(huán)繞通知等。

?? @Aspect — 此注釋將類定義為一個(gè)方面,即關(guān)注點(diǎn)的模塊化。該方面包含建議和要點(diǎn)。
?? @Joinpoint — 連接點(diǎn)是程序執(zhí)行中可以應(yīng)用方面的一個(gè)點(diǎn)。在 Spring AOP 中,連接點(diǎn)是方法調(diào)用。
?? @Advice — 建議是某個(gè)方面在特定連接點(diǎn)上采取的行動(dòng)。有幾種類型的建議,例如“之前”、“之后”、“周圍”等。
?? @Pointcut — 切點(diǎn)是一組應(yīng)應(yīng)用方面的連接點(diǎn)。它定義了一個(gè)模式,該模式與方面應(yīng)截獲的方法相匹配。可以使用表達(dá)式或注釋來(lái)定義切點(diǎn)。

下面是 Spring AOP 注解的示例:

@Aspect
@Component
public class LoggingAspect {
    @Before("execution(public * com.example.myapp.service.*.*(..))")
    public void logBefore(JoinPoint joinPoint) {
        System.out.println("Before " + joinPoint.getSignature().getName() + " method");
    }
    @After("execution(public * com.example.myapp.service.*.*(..))")
    public void logAfter(JoinPoint joinPoint) {
        System.out.println("After " + joinPoint.getSignature().getName() + " method");
    }
    @Around("execution(public * com.example.myapp.service.*.*(..))")
    public Object logAround(ProceedingJoinPoint joinPoint) throws Throwable {
        System.out.println("Before " + joinPoint.getSignature().getName() + " method");
        Object result = joinPoint.proceed();
        System.out.println("After " + joinPoint.getSignature().getName() + " method");
        return result;
    }
    @Pointcut("execution(public * com.example.myapp.service.*.*(..))")
    public void serviceMethods() {}
}

寫在最后 ??

日志使用在現(xiàn)代軟件開發(fā)中非常重要,它可以幫助開發(fā)者和系統(tǒng)管理員監(jiān)控程序運(yùn)行狀態(tài)、排查問(wèn)題和調(diào)試代碼。但是,日志使用也存在一些缺點(diǎn),如干擾員工工作、信息整理工作量大、主觀色彩和日志格式不統(tǒng)一等。因此,在使用日志時(shí),需要權(quán)衡其優(yōu)缺點(diǎn),選擇合適的日志記錄方法,并確保日志數(shù)據(jù)的準(zhǔn)確性和完整性。

到此這篇關(guān)于基于Spring AOP的Log收集的文章就介紹到這了,更多相關(guān)Spring AOP Log收集內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Spring Boot異常處理try-catch應(yīng)該怎么使用?

    Spring Boot異常處理try-catch應(yīng)該怎么使用?

    這篇文章詳細(xì)介紹了Web系統(tǒng)中異常處理的重要性,以及SpringMVC的異常處理機(jī)制,解釋了異常在系統(tǒng)中的角色,討論了Java異常模型的關(guān)鍵認(rèn)知,包括Throwable體系結(jié)構(gòu)和異常傳播,強(qiáng)調(diào)了在Web系統(tǒng)中不應(yīng)該到處使用try-catch,而是應(yīng)該在邊界層統(tǒng)一處理異常
    2026-01-01
  • Flutter ListView 上拉加載更多下拉刷新功能實(shí)現(xiàn)方法

    Flutter ListView 上拉加載更多下拉刷新功能實(shí)現(xiàn)方法

    這篇文章主要介紹了Flutter ListView 上拉加載更多下拉刷新功能實(shí)現(xiàn)方法,本文給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2019-07-07
  • 在Spring中實(shí)現(xiàn)異步處理的步驟和代碼演示

    在Spring中實(shí)現(xiàn)異步處理的步驟和代碼演示

    在Spring中實(shí)現(xiàn)異步處理通常涉及到@Async注解,通過(guò)步驟和代碼演示,可以在Spring應(yīng)用程序中實(shí)現(xiàn)異步處理,記住要根據(jù)你的應(yīng)用程序的實(shí)際需求來(lái)調(diào)整線程池和異步方法的設(shè)計(jì),感興趣的朋友跟隨小編一起看看吧
    2024-06-06
  • Java中兩個(gè)字符串進(jìn)行大小比較的方法

    Java中兩個(gè)字符串進(jìn)行大小比較的方法

    這篇文章主要介紹了Java中兩個(gè)字符串進(jìn)行大小比較,符串是否相等比較,只能使用equals()方法,不能使用“==”,本文通過(guò)示例代碼給大家介紹的非常詳細(xì),需要的朋友可以參考下
    2022-12-12
  • Java使用數(shù)組實(shí)現(xiàn)ArrayList的動(dòng)態(tài)擴(kuò)容的方法

    Java使用數(shù)組實(shí)現(xiàn)ArrayList的動(dòng)態(tài)擴(kuò)容的方法

    這篇文章主要介紹了Java使用數(shù)組實(shí)現(xiàn)ArrayList的動(dòng)態(tài)擴(kuò)容的方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-06-06
  • Java中的system.getProperty()的作用及使用方法

    Java中的system.getProperty()的作用及使用方法

    System.getProperty()?方法用于獲取系統(tǒng)屬性的值,該方法接受一個(gè)字符串參數(shù),表示要獲取的系統(tǒng)屬性的名稱,返回值為字符串類型,表示該屬性的值,接下來(lái)通過(guò)本文給大家介紹Java中的system.getProperty()的作用及使用方法,感興趣的朋友跟隨小編一起看看吧
    2023-05-05
  • springboot全局日期格式化的兩種方式

    springboot全局日期格式化的兩種方式

    這篇文章主要介紹了springboot全局日期格式化的兩種方式,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-09-09
  • 解決 IDEA 創(chuàng)建 Gradle 項(xiàng)目沒有src目錄問(wèn)題

    解決 IDEA 創(chuàng)建 Gradle 項(xiàng)目沒有src目錄問(wèn)題

    這篇文章主要介紹了解決 IDEA 創(chuàng)建 Gradle 項(xiàng)目沒有src目錄問(wèn)題,本文圖文并茂給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2018-06-06
  • 詳解SpringBoot接收參數(shù)的五種形式

    詳解SpringBoot接收參數(shù)的五種形式

    在Spring Boot中,接收參數(shù)可以通過(guò)多種方式實(shí)現(xiàn),本文給大家介紹了SpringBoot接收參數(shù)的五種形式,并通過(guò)代碼和圖文給大家介紹的非常詳細(xì),需要的朋友可以參考下
    2024-03-03
  • Java中的數(shù)組排序方式(快速排序、冒泡排序、選擇排序)

    Java中的數(shù)組排序方式(快速排序、冒泡排序、選擇排序)

    這篇文章主要介紹了Java中的數(shù)組排序方式(快速排序、冒泡排序、選擇排序),需要的朋友可以參考下
    2014-02-02

最新評(píng)論

太湖县| 海城市| 右玉县| 阿图什市| 南召县| 始兴县| 德钦县| 梧州市| 仁寿县| 雷州市| 扎兰屯市| 霍邱县| 襄汾县| 唐海县| 江口县| 肇庆市| 黑河市| 纳雍县| 合水县| 民县| 屯留县| 儋州市| 莫力| 左权县| 哈尔滨市| 吉安县| 衡阳市| 翼城县| 兴义市| 县级市| 庄河市| 贵定县| 余江县| 登封市| 天气| 玉屏| 武胜县| 通辽市| 中卫市| 临桂县| 福清市|