spring——基于mongolist元素实现固定大小队列

    最近手上有一个需求,需要记录任意两人的会话,并且需要记录最近N条聊天记录。我们首先可以想到一个表记录所有人的聊天记录:发送方,接收方,发送内容,时间。然后一个表记录会话,用户1,用户2,最新的会话时间。然后根据会话表查询聊天记录表获取两人之间的按时间倒序的聊天内容。但是如果最近的N条聊天记录要同会话列表有一同展示就有点头秃了。如果查到一个会话列表,然后遍历去查每个会话的前N条聊天记录。那假设每查一次200ms(因为聊天记录表是庞大的,就算加上了索引,也在几百毫秒的性能损耗),那如果一个列表50条数据,这个接口就得至少等10s才会有返回。这性能,炸裂了。
    基于上面的性能考虑,决定在每次插入会话表的时候,实现一个固定大小的队列来保存会话的最近N条记录。好在mongo可以原子级的实现这个功能,mongo实现:

db.test_col.update({ _id: 1 }, { $push: { "list": { $each: [{ "list.name": "eee", "list.time": 3 }], $slice: 3, $position: 0 } } }, { upsert: true })

在test_col这个集合中,对于id为1的文档,将其list元素,增加一条记录:{ “list.name”: “eee”, “list.time”: 3 }, $slice限制list的总大小,$position设置插入位置在最前面。这样就能实现一个固定大小队列了,当元素超过队列大小时,会自动剔除队列底部的内容,来保证队列的大小不变。最主要的是整套操作是原子的。

    那从java/kotlin基于spring-data-mongo怎么实现呢,如下:

    fun save(id: String, user1: ChatSessionLog.UserInfo, user2: ChatSessionLog.UserInfo, latestChat: ChatSessionLog.ChatContent) {
        val query = Query.query(Criteria.where("_id").`is`(id))
        val update = Update()
                .set("user1", user1)
                .set("user2", user2)
                .set("update_time", LocalDateTime.now())
                .set("read_flag", 0)
                .push("latest_chat_content")).atPosition(0).slice(4).each(latestChat)
        ttlLogMongo.upsert(query, update, ChatSessionLog::class.java)
    }
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spring AOP是Spring框架中的一个重要模块,它提供了面向切面编程(AOP)的支持。AOP是一种编程思想,它可以在不改变原有代码的情况下,通过在程序运行时动态地将代码“织入”到现有代码中,从而实现对原有代码的增强。 Spring AOP提供了基于注解的AOP实现,使得开发者可以通过注解的方式来定义切面、切点和通知等相关内容,从而简化了AOP的使用。 下面是一个基于注解的AOP实现的例子: 1. 定义切面类 ```java @Aspect @Component public class LogAspect { @Pointcut("@annotation(Log)") public void logPointcut() {} @Before("logPointcut()") public void beforeLog(JoinPoint joinPoint) { // 前置通知 System.out.println("执行方法:" + joinPoint.getSignature().getName()); } @AfterReturning("logPointcut()") public void afterLog(JoinPoint joinPoint) { // 后置通知 System.out.println("方法执行完成:" + joinPoint.getSignature().getName()); } @AfterThrowing(pointcut = "logPointcut()", throwing = "ex") public void afterThrowingLog(JoinPoint joinPoint, Exception ex) { // 异常通知 System.out.println("方法执行异常:" + joinPoint.getSignature().getName() + ",异常信息:" + ex.getMessage()); } } ``` 2. 定义业务逻辑类 ```java @Service public class UserService { @Log public void addUser(User user) { // 添加用户 System.out.println("添加用户:" + user.getName()); } @Log public void deleteUser(String userId) { // 删除用户 System.out.println("删除用户:" + userId); throw new RuntimeException("删除用户异常"); } } ``` 3. 在配置文件中开启AOP ```xml <aop:aspectj-autoproxy/> <context:component-scan base-package="com.example"/> ``` 在这个例子中,我们定义了一个切面类LogAspect,其中通过@Aspect注解定义了一个切面,通过@Pointcut注解定义了一个切点,通过@Before、@AfterReturning和@AfterThrowing注解分别定义了前置通知、后置通知和异常通知。 在业务逻辑类中,我们通过@Log注解标注了需要增强的方法。 最后,在配置文件中,我们通过<aop:aspectj-autoproxy/>开启了AOP功能,并通过<context:component-scan>扫描了指定包下的所有组件。 这样,当我们调用UserService中的方法时,就会触发LogAspect中定义的通知,从而实现对原有代码的增强。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值