导入redis的jar包
<!-- redis --> <dependency> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
<version>2.0.4.RELEASE</version> </dependency>
编写自定义缓存注解
/** * @Description: redis缓存注解 编写在需要缓存的类上 **/ @Documented
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) public @interface
RedisCache { }
编写切面类
package com.ys.edu.aop; import com.ys.edu.utils.ResultUtils; import
org.apache.log4j.Logger; import org.aspectj.lang.ProceedingJoinPoint; import
org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut; import
org.springframework.beans.factory.annotation.Autowired; import
org.springframework.data.redis.core.RedisTemplate; import
org.springframework.data.redis.core.ValueOperations; import
org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; import
org.springframework.data.redis.serializer.RedisSerializer; import
org.springframework.data.redis.serializer.StringRedisSerializer; import
org.springframework.stereotype.Service; import
org.aspectj.lang.reflect.MethodSignature; import javax.annotation.Resource;
import java.util.Arrays; import java.util.Set; import
java.util.concurrent.TimeUnit; /** * @ClassName RedisAOP * @description: redis
切面缓存 **/ @Aspect @Service public class RedisAOP { private static final Logger
logger = Logger.getLogger(RedisAOP.class); private static final Integer
TIME_OUT = 30 ; //redis 存活时长 分钟 @Resource private RedisTemplate redisTemplate;
/** * @Title: queryCachePointcut * @Description: 定义切点为缓存注解 * @return void **/
@Pointcut("@within(com.ys.edu.annotation.RedisCache)") public void
queryCachePointcut(){ } @Around("queryCachePointcut()") public Object
Interceptor(ProceedingJoinPoint joinPoint) throws Throwable{ long beginTime =
System.currentTimeMillis(); MethodSignature signature = (MethodSignature)
joinPoint.getSignature(); //类路径名 String classPathName =
joinPoint.getTarget().getClass().getName(); //类名 String className =
classPathName.substring(classPathName.lastIndexOf(".")+1,classPathName.length());
//获取方法名 String methodName = signature.getMethod().getName(); String[] strings =
signature.getParameterNames(); String key =
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"))){ Object data =
getObject(beginTime,joinPoint,key); if(data != null){ return
ResultUtils.success(data); } return joinPoint.proceed(); }else
if((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"))){ Set<String> keys =
redisTemplate.keys(className+"*"); redisTemplate.delete(keys);
logger.warn("执行方法 : [ "+methodName+" ] : 清除 key 包含 [ "+className+" ] 的缓存数据");
logger.warn("AOP 缓存切面处理 >>>> end 耗时:" + (System.currentTimeMillis() -
beginTime)); } // 调用原始方法 return joinPoint.proceed(); } /** * @Title: getObject
* @Description: 使用key获取数据 不存在则查询添加 * @param beginTime : 切面开始时间 * @param
joinPoint : 切面对象 * @param key : 获取redis数据的key值 * @return java.lang.Object **/
private Object getObject(long beginTime,ProceedingJoinPoint joinPoint,String
key) throws Throwable { ValueOperations<String, Object> operations =
redisTemplate.opsForValue(); boolean hasKey = redisTemplate.hasKey(key); Object
object = null; if(hasKey){ // 缓存中获取到数据,直接返回。 object = operations.get(key);
logger.warn("从缓存中获取到 key 为 ["+key+" ] : 的数据 >>>> " + object.toString());
logger.warn("AOP 缓存切面处理 >>>> end 耗时:" + (System.currentTimeMillis() -
beginTime)); return object; } 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)); } return object; }
@Autowired(required = false) public void setRedisTemplate(RedisTemplate
redisTemplate) { RedisSerializer stringSerializer = new
StringRedisSerializer();//序列化为String Jackson2JsonRedisSerializer
jackson2JsonRedisSerializer = new
Jackson2JsonRedisSerializer(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 开头的方法时,则清空该类下的所有缓存.

方法返回值格式统一实体类:
package com.ys.edu.bean; import java.io.Serializable; /** * @ClassName
ResultBody * @description: RestFul API 方法返回值格式统一实体类 **/ public class
ResultBody<T> implements Serializable { private static final long
serialVersionUID = 694858559908048578L; private Integer code; private String
msg; private Integer count = 0; private T data; public ResultBody(){} public
ResultBody(Integer code, String msg,Integer count,T data) { this.code = code;
this.msg = msg; this.count = count; this.data = data; } public
ResultBody(Integer code, String msg,T data) { this.code = code; this.msg = msg;
this.data = data; } /** * @Title: success * @Description: 成功 (无参) 默认 code : " 0
" msg : "请求成功" , count : 0 , data: null * @date 2018/11/29 10:28 **/ public
ResultBody success(){ return success((T) null); } /** * @Title: success *
@Description: 成功 默认 code : " 0 " msg : "请求成功" * @param count : 数据条数 * @param
data : 数据 * @date 2018/11/29 11:46 **/ public ResultBody success(Integer
count,T data){ return new ResultBody(0,"请求成功!",count,data); } /** * @Title:
success * @Description: 成功 默认 code : " 0 " * @param msg : 提示信息 * @param count :
数据条数 * @param data : 数据 **/ public ResultBody success(String msg,Integer
count,T data){ return new ResultBody(0,msg,count,data); } /** * @Title: success
* @Description: 成功 默认 code : " 0 " , msg : "请求成功" * @param data : 数据 **/ public
ResultBody success(T data){ return new ResultBody(0,"请求成功!",data); } /** *
@Title: success * @Description: 成功 默认 code : " 0 " * @param msg : 提示信息 * @param
data : 数据 * @date 2018/11/29 11:47 **/ public ResultBody success(String msg,T
data){ return new ResultBody(0,msg,data); } /** * @Title: success *
@Description: 成功 默认 code : " 0 " * @param code : 枚举类代码 * @param data : 数据 **/
public ResultBody success(Code code,T data){ return new
ResultBody(code.getCode(),code.getMsg(),data); } /** * @Title: success *
@Description: 成功 默认 code : " 0 " * @param code : 枚举类代码 **/ public ResultBody
success(Code code){ return new ResultBody(code.getCode(),code.getMsg(),null); }
/** * @Title: error * @Description: 错误 默认 data : null * @param code : 错误代码 *
@param msg : 错误信息 **/ public ResultBody error(Integer code,String msg){ return
new ResultBody(code,msg,null); } /** * @Title: error * @Description: 错误 默认 data
: null * @param code : 枚举类错误代码 **/ public ResultBody error(Code code){ return
new ResultBody(code.getCode(),code.getMsg(),null); } public Integer getCode() {
return code; } public void setCode(Integer code) { this.code = code; } public
String getMsg() { return msg; } public void setMsg(String msg) { this.msg =
msg; } public Integer getCount() { return count; } public void setCount(Integer
count) { this.count = count; } public T getData() { return data; } public void
setData(T data) { this.data = data; } }
自定义提示枚举类:
package com.ys.edu.bean; /** * @ClassName Code * @description: 自定义提示枚举类 **/
public enum Code { /** * @Description: 请求状态码 **/ SUCCESS(0,"请求成功"),
ERROR(-1,"请求错误"); private Integer code; private String msg; public Integer
getCode() { return code; } public void setCode(Integer code) { this.code =
code; } public String getMsg() { return msg; } public void setMsg(String msg) {
this.msg = msg; } Code(Integer code, String msg){ this.code = code; this.msg =
msg; } }
返回结果工具类:
package com.ys.edu.utils; import com.ys.edu.bean.Code; import
com.ys.edu.bean.ResultBody; import com.ys.edu.entity.Page; import
java.util.HashMap; import java.util.Map; /** * @ClassName ResultUtils *
@description: 返回结果工具类 **/ public class ResultUtils { /** * @Title: success *
@Description: 无参成功返回 默认值 code : "0" , msg : "请求成功" , count : 0 , data : null
**/ public static ResultBody success(){ return success((Object)null); } public
static ResultBody success(Object object){ return success(0,object); } /** *
@Title: success * @Description: 有参成功返回 默认值 code : "0" , msg : "请求成功" * @param
count : 数据条数 * @param object : 数据 **/ public static ResultBody success(Integer
count,Object object){ return new ResultBody().success(count,object); } /** *
@Title: success * @Description: 有参成功返回 默认值 code : "0" * @param msg : 提示信息 *
@param count : 数据条数 * @param object : 数据 **/ public static ResultBody
success(String msg,Integer count,Object object){ return new
ResultBody().success(msg,count,object); } /** * @Title: error * @Description:
有参成功返回 默认值 code : "0" * @param code : * @param object : 数据 **/ public static
ResultBody success(Code code,Object object){ return new
ResultBody().success(code,object); } /** * @Title: error * @Description: 有参成功返回
默认值 code : "0" data : null * @param code : 枚举类代码 **/ public static ResultBody
success(Code code){ return new ResultBody().success(code); } /** * @Title:
error * @Description: 错误返回格式 默认值 data : null * @param code : 错误代码 **/ public
static ResultBody error(Integer code,String msg){ return new
ResultBody().error(code,msg); } /** * @Title: error * @Description: 错误返回格式 默认值
data : null * @param code : 枚举类错误代码 **/ public static ResultBody error(Code
code){ return new ResultBody().error(code); } /** * @Title: successByLimit *
@Description: 分页返回数据格式 * @param page : 查询的页数 * @param limit : 查询的条数 * @param
totalNum : 数据总条数 * @param curCount : 当前页条数 * @param object : 查询结果数据 **/ public
static ResultBody successByLimit(Integer page,Integer limit,Integer
totalNum,Integer curCount,Object object){ Map<String,Object> map = new
HashMap<>(); Page pageInfo = new Page(); pageInfo.setPage(page);
pageInfo.setLimit(limit); pageInfo.setTotalNum(totalNum);
pageInfo.setTotalPages((totalNum + limit - 1)/limit); map.put("page",pageInfo);
map.put("data",object); return success(curCount,map); } }

友情链接
KaDraw流程图
API参考文档
OK工具箱
云服务器优惠
阿里云优惠券
腾讯云优惠券
华为云优惠券
站点信息
问题反馈
邮箱:ixiaoyang8@qq.com
QQ群:637538335
关注微信