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{ ValueOperations operations=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(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。