springboot+redis缓存方案
一、注解
import java.lang.annotation.elementtype;
import java.lang.annotation.retention;
import java.lang.annotation.retentionpolicy;
import java.lang.annotation.target;
import java.util.concurrent.timeunit;
/**
* @author lch
* @date 2023/8/03 09:29
*/
@target(elementtype.method)
@retention(retentionpolicy.runtime)
public @interface rediscache {
/**
* key,支持 spring el表达式
*/
string key();
/**
* 统一格式:服务名:场景,如:info
*/
string prefix();
/**
* 过期时间
*/
int expiretime() default 36000;
/**
* 时间单位
*/
timeunit timeunit() default timeunit.seconds;
}二、注解切面类
import com.dewav.tms.framework.aspectj.lang.annotation.rediscache;
import com.dewav.tms.framework.redis.redisservice;
import lombok.extern.slf4j.slf4j;
import org.aspectj.lang.proceedingjoinpoint;
import org.aspectj.lang.annotation.around;
import org.aspectj.lang.annotation.aspect;
import org.aspectj.lang.reflect.methodsignature;
import org.springframework.context.expression.methodbasedevaluationcontext;
import org.springframework.core.defaultparameternamediscoverer;
import org.springframework.expression.evaluationcontext;
import org.springframework.expression.expression;
import org.springframework.expression.spel.standard.spelexpressionparser;
import org.springframework.stereotype.component;
import org.springframework.util.assert;
import javax.annotation.resource;
import java.lang.reflect.method;
import java.util.concurrent.timeunit;
/**
* @author lch
* @date 2023/8/03 09:29
*/
@component
@aspect
@slf4j
public class rediscacheaspect {
private final spelexpressionparser spelexpressionparser = new spelexpressionparser();
private final defaultparameternamediscoverer parameternamediscoverer = new defaultparameternamediscoverer();
@resource
private redisservice redisservice;
@around("@annotation(rediscache)")
public object querybyrediscache(proceedingjoinpoint pjp, rediscache rediscache) {
int expiretime = rediscache.expiretime();
string key = rediscache.key();
string prefix = rediscache.prefix();
assert.hastext(key, "@rediscache key不能为空!");
assert.hastext(prefix, "@rediscache prefix不能为空!");
string evaluateexpression = evaluateexpression(key, pjp);
string rediskey = prefix + evaluateexpression;
object obj = null;
try {
if (null != rediskey){
if (redisservice.haskey(rediskey)){
obj = redisservice.getcacheobject(rediskey);
return obj;
}
}
} catch (exception e) {
log.error("从redis获取"+rediskey+"失败:"+e.getmessage());
}
try{
obj = pjp.proceed();
}catch(throwable e){
log.error("执行异常", e);
throw new runtimeexception(e.getmessage());
}
if (null != rediskey){
redisservice.setcacheobject(rediskey, obj, expiretime, timeunit.seconds);
}
return obj;
}
/**
* 解析el表达式
*
* @param expression
* @param point
* @return
*/
private string evaluateexpression(string expression, proceedingjoinpoint point) {
// 获取目标对象
object target = point.gettarget();
// 获取方法参数
object[] args = point.getargs();
methodsignature methodsignature = (methodsignature) point.getsignature();
method method = methodsignature.getmethod();
evaluationcontext context = new methodbasedevaluationcontext(target, method, args, parameternamediscoverer);
expression exp = spelexpressionparser.parseexpression(expression);
return exp.getvalue(context, string.class);
}
}三、使用样例
@override
@rediscache(key = "{#customerid + ':' + #dicttype}", prefix = cacheconstants.sys_dict_key)
public list<sysdictdata> selectdictdatabytype(long customerid, string dicttype) {
return dictdatamapper.selectdictdatabytype(customerid, dicttype);
}
@override
@rediscache(key = "#apikey", prefix = cacheconstants.open_key + "apiinfo:apikey:")
public ediapiinfo getbyapikey(string apikey) {
return basemapper.selectone(new querywrapper<ediapiinfo>()
.eq("api_key", apikey)
.eq("status", true)
.eq("del_flag", false));
}总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持代码网。
发表评论