导入redis的jar包
org.springframework.boot
spring-boot-starter-data-redis
2.0.4.RELEASE
编写自定义缓存注解
@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;
@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;
@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 keys = redisTemplate.keys(className+"*");
redisTemplate.delete(keys);
logger.warn("执行方法 : [ "+methodName+" ] : 清除 key 包含 [ "+className+" ] 的缓存数据");
logger.warn("AOP 缓存切面处理 >>>> end 耗时:" + (System.currentTimeMillis() - beginTime));
}
// 调用原始方法
return joinPoint.proceed();
}
private Object getObject(long beginTime,ProceedingJoinPoint joinPoint,String key) throws Throwable {
ValueOperations 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; public class ResultBodyimplements 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; } public ResultBody success(){ return success((T) null); } public ResultBody success(Integer count,T data){ return new ResultBody(0,"请求成功!",count,data); } public ResultBody success(String msg,Integer count,T data){ return new ResultBody(0,msg,count,data); } public ResultBody success(T data){ return new ResultBody(0,"请求成功!",data); } public ResultBody success(String msg,T data){ return new ResultBody(0,msg,data); } public ResultBody success(Code code,T data){ return new ResultBody(code.getCode(),code.getMsg(),data); } public ResultBody success(Code code){ return new ResultBody(code.getCode(),code.getMsg(),null); } public ResultBody error(Integer code,String msg){ return new ResultBody(code,msg,null); } 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;
public enum Code {
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;
public class ResultUtils {
public static ResultBody success(){
return success((Object)null);
}
public static ResultBody success(Object object){
return success(0,object);
}
public static ResultBody success(Integer count,Object object){
return new ResultBody().success(count,object);
}
public static ResultBody success(String msg,Integer count,Object object){
return new ResultBody().success(msg,count,object);
}
public static ResultBody success(Code code,Object object){
return new ResultBody().success(code,object);
}
public static ResultBody success(Code code){
return new ResultBody().success(code);
}
public static ResultBody error(Integer code,String msg){
return new ResultBody().error(code,msg);
}
public static ResultBody error(Code code){
return new ResultBody().error(code);
}
public static ResultBody successByLimit(Integer page,Integer limit,Integer totalNum,Integer curCount,Object object){
Map 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);
}
}
总结
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对考高分网的支持。如果你想了解更多相关内容请查看下面相关链接



