当前位置: 首页 > news >正文

预防缓存穿透工具类

1. 前言

缓存穿透大家都知道,这里简单过一下

缓存和数据库中都没有的数据,而用户不断发起请求。比如查询id = -1 的值

想着很多面向C端的查询接口,可能都需要做一下缓存操作,这里简单写了个自定义注解,将查询结果(包含null值)做个缓存

这个只能预防单秒内接口高频次请求,要是一直搞随机值请求这个只能采取其他手段处理了(比如IP拉黑什么的…)

工具类留底,以后兴许可以直接抄~( ̄▽ ̄)"

2. 正文

直接上代码了

2.1 自定义注解

CacheResult

import java.lang.annotation.*;/*** <pre>* 接口缓存* 根据接口的第一个入参对象,和返回值进行缓存* 缓存的前缀为 TEMPORARY_CACHE:类名:方法名:key值* 示例:@CacheResult(key="userId + '_' + ecommerceId", seconds = 2L)* 缓存的key:TEMPORARY_CACHE:EcommerceController:getOrderList:407622341504839680_527203683850731520* </pre>* @author weiheng* @date 2023-08-25**/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE,ElementType.METHOD})
public @interface CacheResult {/** 入参支持 SpEL表达式 做参数提取,比如入参对象有属性userId和ecommerceId -> key="userId + '_' + ecommerceId" */String key();/** 缓存时长,单位:秒 */long seconds();
}

2.2 统一做缓存处理的切面

CacheAspect

import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.redisson.api.RBucket;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.Expression;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;
import org.springframework.stereotype.Component;import javax.annotation.Resource;/*** 缓存统一处理* @author weiheng* @date 2023-08-25**/
@Slf4j
@Aspect
@Component
public class CacheAspect {/** 临时缓存的统一前缀 */public static final String DEFAULT_PREFIX = "TEMPORARY_CACHE:";/** 缓存分隔符 */public static final String DELIMITER = ":";@Resourceprivate RedissonHelper redissonHelper;/*** 拦截通知** @param proceedingJoinPoint 入参* @return Object*/@Around("@annotation(cacheSeconds)")public Object around(ProceedingJoinPoint proceedingJoinPoint, CacheResult cacheSeconds) {Object[] args = proceedingJoinPoint.getArgs();if (args.length == 0) {// 方法没有入参,不做缓存return proceed(proceedingJoinPoint);}// 1. 判断缓存中是否存在,有则直接返回Object firstArg = args[0];// 获取用户指定的参数ExpressionParser parser = new SpelExpressionParser();EvaluationContext context = new StandardEvaluationContext(firstArg);Expression keyExpression = parser.parseExpression(cacheSeconds.key());String businessKey = keyExpression.getValue(context, String.class);// 拼装缓存keyString className = proceedingJoinPoint.getTarget().getClass().getSimpleName();String methodName = proceedingJoinPoint.getSignature().getName();String prefix = className + DELIMITER + methodName;String cacheKey = DEFAULT_PREFIX + prefix + DELIMITER + businessKey;RBucket<?> bucket = redissonHelper.getBucket(cacheKey);boolean exists = bucket.isExists();if (exists) {// 缓存中有值,直接返回return bucket.get();}// 2. 执行方法体Object returnValue = proceed(proceedingJoinPoint);// 3. 做个N秒的缓存long seconds = cacheSeconds.seconds();redissonHelper.setValueAndSeconds(cacheKey, returnValue, seconds);return returnValue;}private Object proceed(ProceedingJoinPoint proceedingJoinPoint) {Object returnValue;try {returnValue = proceedingJoinPoint.proceed();} catch (Throwable e) {log.error("error msg:", e);if (e instanceof SystemException) {throw (SystemException) e;}throw new SystemException(e.getMessage());}return returnValue;}

3. 使用示例

原本定义个2秒就OK了,这里为了方便看测试结果,给了60秒

@CacheResult(key=“userId + ‘_’ + ecommerceId”, seconds = 60L)

redis缓存如下:
在这里插入图片描述
就到这里了

相关文章:

预防缓存穿透工具类

1. 前言 缓存穿透大家都知道&#xff0c;这里简单过一下 缓存和数据库中都没有的数据&#xff0c;而用户不断发起请求。比如查询id -1 的值 想着很多面向C端的查询接口&#xff0c;可能都需要做一下缓存操作&#xff0c;这里简单写了个自定义注解&#xff0c;将查询结果(包含…...

会员管理系统实战开发教程04-会员开卡

我们已经用3篇篇幅介绍了会员管理的功能&#xff0c;接着就要开发会员的业务。通常我们开通会员之后需要给会员开通会员卡&#xff0c;一个会员可以有多张会员卡。 在数据源设计的时候&#xff0c;像这种一个会员有多张会员卡的&#xff0c;我们称之为一对多的关系&#xff0c…...

数据结构(2)

冒泡排序&#xff1a; 1.比较相邻的两个元素。如果前一个元素比后一个元素大&#xff0c;则交换两者位置。 2.对每一对相邻元素做相同工作&#xff0c;从第一对元素到最后一对元素&#xff0c;最后的一个元素就是最大的元素。 for(int ia.length-1;i>0;i--){for (int j 0…...

使用ELK(ES+Logstash+Filebeat+Kibana)收集nginx的日志

文章目录 Nginx日志格式修改配置logstash收集nginx日志引入Redis收集日志写入redis从redis中读取日志 引入FilebeatFilebeat简介Filebeat安装和配置 配置nginx转发ES和kibanaELK设置账号和密码 书接上回&#xff1a;《ELK中Logstash的基本配置和用法》 Nginx日志格式修改 默认…...

TDengine server连接遇到的坑

一、TDengine安装 TDengine目前只有linux版本的server端&#xff0c;安装教程参考 https://zhuanlan.zhihu.com/p/302413259 二、TDengine连接 TDengine连接目前支持两种方式&#xff0c;一种是原生连接&#xff0c;该方法的默认端口号为6030&#xff1b;另一种是REST API连…...

什么是NetDevOps

NetDevOps 是一种新兴的方法&#xff0c;它结合了 NetOps 和 DevOps 的流程&#xff0c;即将网络自动化集成到开发过程中。NetDevOps 的目标是将虚拟化、自动化和 API 集成到网络基础架构中&#xff0c;并实现开发和运营团队之间的无缝协作。 开发运营&#xff08;DevOps&…...

中小金融机构数字化转型最大的挑战是什么?

中国银保监会办公厅印发的《关于银行业保险业数字化转型的指导意见》强调&#xff0c;银行保险机构要加强顶层设计和统筹规划&#xff0c;科学制定数字化转型战略&#xff0c;统筹推进工作&#xff0c;并从战略规划与组织流程建设、业务经营管理数字化、数据能力建设、科技能力…...

Facebook HiPlot “让理解高维数据变得容易”

在这个全球信息化的时代&#xff0c;数据量呈爆炸式增长&#xff0c;数据的复杂性也是如此。如何有效地处理高维数据并找到隐藏在其中的相关性和模式是一个严峻的挑战。近年来&#xff0c;可视化和可视化分析已被应用于该任务&#xff0c;并取得了一些积极成果。Facebook的新Hi…...

【python】:python新设备环境移植(requirements.txt)

环境移植 condapip conda 你可以使用conda命令来创建一个包含所有已安装包的requirements.txt文件&#xff0c;并将其复制到新电脑上。然后&#xff0c;你可以在新电脑上使用pip命令来安装这些包及其依赖项。 以下是一个示例命令&#xff1a; conda list --export > requ…...

分类预测 | MATLAB实现1D-2D-CNN-GRU的多通道输入数据分类预测

分类预测 | MATLAB实现1D-2D-CNN-GRU的多通道输入数据分类预测 目录 分类预测 | MATLAB实现1D-2D-CNN-GRU的多通道输入数据分类预测分类效果基本介绍程序设计参考资料 分类效果 基本介绍 结合1D时序-2D图像多模态融合的CNN-GRU故障识别算法&#xff0c;基于一维时序信号和二维图…...

【LeetCode】125. 验证回文串 - 双指针

这里写自定义目录标题 2023-8-24 09:31:12 125. 验证回文串 2023-8-24 09:31:12 最关键的是 注意 题目中的 “字母和数字都属于字母数字字符。” 使用ascii码进行判断就行了 class Solution {public boolean isPalindrome(String s) {int p 0, q s.length() - 1;while (…...

centos7设置java后端项目开机自启【脚本、开机自启】

1.切换目录 cd /etc/init.d/2.编辑脚本 vim wbs-service-start.sh编辑内容 #!/bin/bash # chkconfig: 2345 80 90 # description: auto_runnohup java -jar /usr/java/wbs-service.jar > /dev/null 2>&1 & echo $! > /var/run/wbs-service.pid3.添加进入系…...

亿赛通电子文档安全管理系统 RCE漏洞复现(QVD-2023-19262)

0x01 产品简介 亿赛通电子文档安全管理系统&#xff08;简称&#xff1a;CDG&#xff09;是一款电子文档安全加密软件&#xff0c;该系统利用驱动层透明加密技术&#xff0c;通过对电子文档的加密保护&#xff0c;防止内部员工泄密和外部人员非法窃取企业核心重要数据资产&…...

一文读懂 Nuxt.js 服务端组件

服务端组件在 Web 开发生态系统中变得越来越普遍。传统上&#xff0c;在单页面应用中&#xff0c;即使是服务端渲染的应用&#xff0c;服务端仅与第一次加载相关&#xff0c;之后将由客户端接管。这意味着 Web 应用的每个部分都必须能够在客户端和服务端上渲染。 相反&#xf…...

LeetCode--HOT100题(39)

目录 题目描述&#xff1a;101. 对称二叉树&#xff08;简单&#xff09;题目接口解题思路代码 PS: 题目描述&#xff1a;101. 对称二叉树&#xff08;简单&#xff09; 给你一个二叉树的根节点 root &#xff0c; 检查它是否轴对称。 LeetCode做题链接&#xff1a;LeetCode-…...

“车-路-网”电动汽车充电负荷时空分布预测(matlab)

目录 1 主要内容 2 部分代码 3 程序结果 4 下载链接 1 主要内容 该程序参考《基于动态交通信息的电动汽车充电负荷时空分布预测》和《基于动态交通信息的电动汽车充电需求预测模型及其对配网的影响分析》文献模型&#xff0c;考虑私家车、出租车和共用车三类交通工具特性和…...

【核磁共振成像】方格化重建

目录 一、缩放比例二、方格化变换的基础三、重建时间四、方格化核 一、缩放比例 对于笛卡尔K空间直线轨迹数据可直接用FFT重建&#xff0c;而如果K空间轨迹的任何部分都是非均匀取样的 可用DFT直接重建&#xff0c;有时称为共轭相位重建&#xff0c;但此法太慢不实用。把数据再…...

JAVA中时间戳和LocalDateTime的互转

时间戳转LocalDateTime&#xff1a; 要将时间戳转换为LocalDateTime并将LocalDateTime转换回时间戳&#xff0c;使用Java的java.time包。以下是示例代码&#xff1a; import java.time.Instant; import java.time.LocalDateTime; import java.time.ZoneId;public class Times…...

无涯教程-进程 - 创建终止

到现在为止&#xff0c;我们知道无论何时执行程序&#xff0c;都会创建一个进程&#xff0c;并且该进程将在执行完成后终止&#xff0c;如果我们需要在程序中创建一个进程&#xff0c;并且可能希望为其安排其他任务&#xff0c;该怎么办。能做到吗?是的&#xff0c;显然是通过…...

LLMs参考资料第一周以及BloombergGPT特定领域的训练 Domain-specific training: BloombergGPT

1. 第1周资源 以下是本周视频中讨论的研究论文的链接。您不需要理解这些论文中讨论的所有技术细节 - 您已经看到了您需要回答讲座视频中的测验的最重要的要点。 然而&#xff0c;如果您想更仔细地查看原始研究&#xff0c;您可以通过以下链接阅读这些论文和文章。 1.1 Trans…...

【SQL学习笔记1】增删改查+多表连接全解析(内附SQL免费在线练习工具)

可以使用Sqliteviz这个网站免费编写sql语句&#xff0c;它能够让用户直接在浏览器内练习SQL的语法&#xff0c;不需要安装任何软件。 链接如下&#xff1a; sqliteviz 注意&#xff1a; 在转写SQL语法时&#xff0c;关键字之间有一个特定的顺序&#xff0c;这个顺序会影响到…...

spring:实例工厂方法获取bean

spring处理使用静态工厂方法获取bean实例&#xff0c;也可以通过实例工厂方法获取bean实例。 实例工厂方法步骤如下&#xff1a; 定义实例工厂类&#xff08;Java代码&#xff09;&#xff0c;定义实例工厂&#xff08;xml&#xff09;&#xff0c;定义调用实例工厂&#xff…...

Springcloud:Eureka 高可用集群搭建实战(服务注册与发现的底层原理与避坑指南)

引言&#xff1a;为什么 Eureka 依然是存量系统的核心&#xff1f; 尽管 Nacos 等新注册中心崛起&#xff0c;但金融、电力等保守行业仍有大量系统运行在 Eureka 上。理解其高可用设计与自我保护机制&#xff0c;是保障分布式系统稳定的必修课。本文将手把手带你搭建生产级 Eur…...

css的定位(position)详解:相对定位 绝对定位 固定定位

在 CSS 中&#xff0c;元素的定位通过 position 属性控制&#xff0c;共有 5 种定位模式&#xff1a;static&#xff08;静态定位&#xff09;、relative&#xff08;相对定位&#xff09;、absolute&#xff08;绝对定位&#xff09;、fixed&#xff08;固定定位&#xff09;和…...

rnn判断string中第一次出现a的下标

# coding:utf8 import torch import torch.nn as nn import numpy as np import random import json""" 基于pytorch的网络编写 实现一个RNN网络完成多分类任务 判断字符 a 第一次出现在字符串中的位置 """class TorchModel(nn.Module):def __in…...

C++:多态机制详解

目录 一. 多态的概念 1.静态多态&#xff08;编译时多态&#xff09; 二.动态多态的定义及实现 1.多态的构成条件 2.虚函数 3.虚函数的重写/覆盖 4.虚函数重写的一些其他问题 1&#xff09;.协变 2&#xff09;.析构函数的重写 5.override 和 final关键字 1&#…...

tomcat指定使用的jdk版本

说明 有时候需要对tomcat配置指定的jdk版本号&#xff0c;此时&#xff0c;我们可以通过以下方式进行配置 设置方式 找到tomcat的bin目录中的setclasspath.bat。如果是linux系统则是setclasspath.sh set JAVA_HOMEC:\Program Files\Java\jdk8 set JRE_HOMEC:\Program Files…...

mac:大模型系列测试

0 MAC 前几天经过学生优惠以及国补17K入手了mac studio,然后这两天亲自测试其模型行运用能力如何&#xff0c;是否支持微调、推理速度等能力。下面进入正文。 1 mac 与 unsloth 按照下面的进行安装以及测试&#xff0c;是可以跑通文章里面的代码。训练速度也是很快的。 注意…...

Linux中《基础IO》详细介绍

目录 理解"文件"狭义理解广义理解文件操作的归类认知系统角度文件类别 回顾C文件接口打开文件写文件读文件稍作修改&#xff0c;实现简单cat命令 输出信息到显示器&#xff0c;你有哪些方法stdin & stdout & stderr打开文件的方式 系统⽂件I/O⼀种传递标志位…...

C++实现分布式网络通信框架RPC(2)——rpc发布端

有了上篇文章的项目的基本知识的了解&#xff0c;现在我们就开始构建项目。 目录 一、构建工程目录 二、本地服务发布成RPC服务 2.1理解RPC发布 2.2实现 三、Mprpc框架的基础类设计 3.1框架的初始化类 MprpcApplication 代码实现 3.2读取配置文件类 MprpcConfig 代码实现…...