SpringBoot AOP控制Redis自动缓存和更新的示例
导入redis的jar包
org.springframework.boot spring-boot-starter-data-redis 2.0.4.RELEASE
编写自定义缓存注解
/**
*@Description:redis缓存注解编写在需要缓存的类上
**/
@Documented
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public@interfaceRedisCache{
}
编写切面类
packagecom.ys.edu.aop;
importcom.ys.edu.utils.ResultUtils;
importorg.apache.log4j.Logger;
importorg.aspectj.lang.ProceedingJoinPoint;
importorg.aspectj.lang.annotation.Around;
importorg.aspectj.lang.annotation.Aspect;
importorg.aspectj.lang.annotation.Pointcut;
importorg.springframework.beans.factory.annotation.Autowired;
importorg.springframework.data.redis.core.RedisTemplate;
importorg.springframework.data.redis.core.ValueOperations;
importorg.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
importorg.springframework.data.redis.serializer.RedisSerializer;
importorg.springframework.data.redis.serializer.StringRedisSerializer;
importorg.springframework.stereotype.Service;
importorg.aspectj.lang.reflect.MethodSignature;
importjavax.annotation.Resource;
importjava.util.Arrays;
importjava.util.Set;
importjava.util.concurrent.TimeUnit;
/**
*@ClassNameRedisAOP
*@description:redis切面缓存
**/
@Aspect
@Service
publicclassRedisAOP{
privatestaticfinalLoggerlogger=Logger.getLogger(RedisAOP.class);
privatestaticfinalIntegerTIME_OUT=30;//redis存活时长分钟
@Resource
privateRedisTemplateredisTemplate;
/**
*@Title:queryCachePointcut
*@Description:定义切点为缓存注解
*@returnvoid
**/
@Pointcut("@within(com.ys.edu.annotation.RedisCache)")
publicvoidqueryCachePointcut(){
}
@Around("queryCachePointcut()")
publicObjectInterceptor(ProceedingJoinPointjoinPoint)throwsThrowable{
longbeginTime=System.currentTimeMillis();
MethodSignaturesignature=(MethodSignature)joinPoint.getSignature();
//类路径名
StringclassPathName=joinPoint.getTarget().getClass().getName();
//类名
StringclassName=classPathName.substring(classPathName.lastIndexOf(".")+1,classPathName.length());
//获取方法名
StringmethodName=signature.getMethod().getName();
String[]strings=signature.getParameterNames();
Stringkey=className+"_"+methodName+"_"+Arrays.toString(strings);
if((methodName.indexOf("select")!=-1&&methodName.substring(0,6).equalsIgnoreCase("select"))||(methodName.indexOf("query")!=-1&&methodName.substring(0,5).equalsIgnoreCase("query"))||(methodName.indexOf("get")!=-1&&methodName.substring(0,3).equalsIgnoreCase("get"))){
Objectdata=getObject(beginTime,joinPoint,key);
if(data!=null){
returnResultUtils.success(data);
}
returnjoinPoint.proceed();
}elseif((methodName.indexOf("add")!=-1&&methodName.substring(0,3).equalsIgnoreCase("add"))||(methodName.indexOf("insert")!=-1&&methodName.substring(0,6).equalsIgnoreCase("insert"))||(methodName.indexOf("update")!=-1&&methodName.substring(0,6).equalsIgnoreCase("update"))){
Setkeys=redisTemplate.keys(className+"*");
redisTemplate.delete(keys);
logger.warn("执行方法:["+methodName+"]:清除key包含["+className+"]的缓存数据");
logger.warn("AOP缓存切面处理>>>>end耗时:"+(System.currentTimeMillis()-beginTime));
}
//调用原始方法
returnjoinPoint.proceed();
}
/**
*@Title:getObject
*@Description:使用key获取数据不存在则查询添加
*@parambeginTime:切面开始时间
*@paramjoinPoint:切面对象
*@paramkey:获取redis数据的key值
*@returnjava.lang.Object
**/
privateObjectgetObject(longbeginTime,ProceedingJoinPointjoinPoint,Stringkey)throwsThrowable{
ValueOperationsoperations=redisTemplate.opsForValue();
booleanhasKey=redisTemplate.hasKey(key);
Objectobject=null;
if(hasKey){
//缓存中获取到数据,直接返回。
object=operations.get(key);
logger.warn("从缓存中获取到key为["+key+"]:的数据>>>>"+object.toString());
logger.warn("AOP缓存切面处理>>>>end耗时:"+(System.currentTimeMillis()-beginTime));
returnobject;
}
if(object==null){
//缓存中没有数据,调用原始方法查询数据库
object=joinPoint.proceed();
operations.set(key,object,TIME_OUT,TimeUnit.MINUTES);//设置超时时间30分钟
logger.warn("向Redis添加key为["+key+"],存活时长为"+TIME_OUT+"min的数据>>>>"+object.toString());
logger.warn("AOP缓存切面处理>>>>end耗时:"+(System.currentTimeMillis()-beginTime));
}
returnobject;
}
@Autowired(required=false)
publicvoidsetRedisTemplate(RedisTemplateredisTemplate){
RedisSerializerstringSerializer=newStringRedisSerializer();//序列化为String
Jackson2JsonRedisSerializerjackson2JsonRedisSerializer=newJackson2JsonRedisSerializer(Object.class);//序列化为Json
redisTemplate.setKeySerializer(stringSerializer);
redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);
redisTemplate.setHashKeySerializer(stringSerializer);
redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer);
this.redisTemplate=redisTemplate;
}
}
在想要使用redis缓存的controller类上添加@RedisCache注解.
切面方法则会切以select/get/query开头的查询方法,获取方法名和参数拼接为key,存到redis.
在执行add/insert/update开头的方法时,则清空该类下的所有缓存.
方法返回值格式统一实体类:
packagecom.ys.edu.bean; importjava.io.Serializable; /** *@ClassNameResultBody *@description:RestFulAPI方法返回值格式统一实体类 **/ publicclassResultBodyimplementsSerializable{ privatestaticfinallongserialVersionUID=694858559908048578L; privateIntegercode; privateStringmsg; privateIntegercount=0; privateTdata; publicResultBody(){} publicResultBody(Integercode,Stringmsg,Integercount,Tdata){ this.code=code; this.msg=msg; this.count=count; this.data=data; } publicResultBody(Integercode,Stringmsg,Tdata){ this.code=code; this.msg=msg; this.data=data; } /** *@Title:success *@Description:成功(无参)默认code:"0"msg:"请求成功",count:0,data:null *@date2018/11/2910:28 **/ publicResultBodysuccess(){ returnsuccess((T)null); } /** *@Title:success *@Description:成功默认code:"0"msg:"请求成功" *@paramcount:数据条数 *@paramdata:数据 *@date2018/11/2911:46 **/ publicResultBodysuccess(Integercount,Tdata){ returnnewResultBody(0,"请求成功!",count,data); } /** *@Title:success *@Description:成功默认code:"0" *@parammsg:提示信息 *@paramcount:数据条数 *@paramdata:数据 **/ publicResultBodysuccess(Stringmsg,Integercount,Tdata){ returnnewResultBody(0,msg,count,data); } /** *@Title:success *@Description:成功默认code:"0",msg:"请求成功" *@paramdata:数据 **/ publicResultBodysuccess(Tdata){ returnnewResultBody(0,"请求成功!",data); } /** *@Title:success *@Description:成功默认code:"0" *@parammsg:提示信息 *@paramdata:数据 *@date2018/11/2911:47 **/ publicResultBodysuccess(Stringmsg,Tdata){ returnnewResultBody(0,msg,data); } /** *@Title:success *@Description:成功默认code:"0" *@paramcode:枚举类代码 *@paramdata:数据 **/ publicResultBodysuccess(Codecode,Tdata){ returnnewResultBody(code.getCode(),code.getMsg(),data); } /** *@Title:success *@Description:成功默认code:"0" *@paramcode:枚举类代码 **/ publicResultBodysuccess(Codecode){ returnnewResultBody(code.getCode(),code.getMsg(),null); } /** *@Title:error *@Description:错误默认data:null *@paramcode:错误代码 *@parammsg:错误信息 **/ publicResultBodyerror(Integercode,Stringmsg){ returnnewResultBody(code,msg,null); } /** *@Title:error *@Description:错误默认data:null *@paramcode:枚举类错误代码 **/ publicResultBodyerror(Codecode){ returnnewResultBody(code.getCode(),code.getMsg(),null); } publicIntegergetCode(){ returncode; } publicvoidsetCode(Integercode){ this.code=code; } publicStringgetMsg(){ returnmsg; } publicvoidsetMsg(Stringmsg){ this.msg=msg; } publicIntegergetCount(){ returncount; } publicvoidsetCount(Integercount){ this.count=count; } publicTgetData(){ returndata; } publicvoidsetData(Tdata){ this.data=data; } }
自定义提示枚举类:
packagecom.ys.edu.bean;
/**
*@ClassNameCode
*@description:自定义提示枚举类
**/
publicenumCode{
/**
*@Description:请求状态码
**/
SUCCESS(0,"请求成功"),
ERROR(-1,"请求错误");
privateIntegercode;
privateStringmsg;
publicIntegergetCode(){
returncode;
}
publicvoidsetCode(Integercode){
this.code=code;
}
publicStringgetMsg(){
returnmsg;
}
publicvoidsetMsg(Stringmsg){
this.msg=msg;
}
Code(Integercode,Stringmsg){
this.code=code;
this.msg=msg;
}
}
返回结果工具类:
packagecom.ys.edu.utils;
importcom.ys.edu.bean.Code;
importcom.ys.edu.bean.ResultBody;
importcom.ys.edu.entity.Page;
importjava.util.HashMap;
importjava.util.Map;
/**
*@ClassNameResultUtils
*@description:返回结果工具类
**/
publicclassResultUtils{
/**
*@Title:success
*@Description:无参成功返回默认值code:"0",msg:"请求成功",count:0,data:null
**/
publicstaticResultBodysuccess(){
returnsuccess((Object)null);
}
publicstaticResultBodysuccess(Objectobject){
returnsuccess(0,object);
}
/**
*@Title:success
*@Description:有参成功返回默认值code:"0",msg:"请求成功"
*@paramcount:数据条数
*@paramobject:数据
**/
publicstaticResultBodysuccess(Integercount,Objectobject){
returnnewResultBody().success(count,object);
}
/**
*@Title:success
*@Description:有参成功返回默认值code:"0"
*@parammsg:提示信息
*@paramcount:数据条数
*@paramobject:数据
**/
publicstaticResultBodysuccess(Stringmsg,Integercount,Objectobject){
returnnewResultBody().success(msg,count,object);
}
/**
*@Title:error
*@Description:有参成功返回默认值code:"0"
*@paramcode:
*@paramobject:数据
**/
publicstaticResultBodysuccess(Codecode,Objectobject){
returnnewResultBody().success(code,object);
}
/**
*@Title:error
*@Description:有参成功返回默认值code:"0"data:null
*@paramcode:枚举类代码
**/
publicstaticResultBodysuccess(Codecode){
returnnewResultBody().success(code);
}
/**
*@Title:error
*@Description:错误返回格式默认值data:null
*@paramcode:错误代码
**/
publicstaticResultBodyerror(Integercode,Stringmsg){
returnnewResultBody().error(code,msg);
}
/**
*@Title:error
*@Description:错误返回格式默认值data:null
*@paramcode:枚举类错误代码
**/
publicstaticResultBodyerror(Codecode){
returnnewResultBody().error(code);
}
/**
*@Title:successByLimit
*@Description:分页返回数据格式
*@parampage:查询的页数
*@paramlimit:查询的条数
*@paramtotalNum:数据总条数
*@paramcurCount:当前页条数
*@paramobject:查询结果数据
**/
publicstaticResultBodysuccessByLimit(Integerpage,Integerlimit,IntegertotalNum,IntegercurCount,Objectobject){
Mapmap=newHashMap<>();
PagepageInfo=newPage();
pageInfo.setPage(page);
pageInfo.setLimit(limit);
pageInfo.setTotalNum(totalNum);
pageInfo.setTotalPages((totalNum+limit-1)/limit);
map.put("page",pageInfo);
map.put("data",object);
returnsuccess(curCount,map);
}
}
总结
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对毛票票的支持。如果你想了解更多相关内容请查看下面相关链接
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。