版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/yhflyl/article/details/87716969
Redis获取策略
检测缓冲是否失效,未失效获取缓冲,获取超时,捕获异常,查数据表,重置缓冲,并设置失效时间,返回数据。
Redis跟更新策略
获取key缓冲时间是否已经失效,没有失效设置为失效。
当用户再次获取数据是,会自动更新缓冲,并设置缓冲失效时间。
使用方式
// 自定义RedisCacheable注解,设置value和key,并设置有效时间为3600*100
@Override
@RedisCacheable(Value = "job", Key = "page", time = 3600*100)
public List<PartTimeJob> jobAll(Integer page, Integer limit) {
RowBounds rowBounds = new RowBounds((page - 1) * 8, limit);
return jobMapper.selectPage(rowBounds, new EntityWrapper<PartTimeJob>().where("job_check", 1).orderBy("job_time_pulish", false));
}
// 自定义RedisCacheUpdate注解
@Override
@RedisCacheUpdate(Value = "job", Key = "page")
public Integer updatePartJob(Integer id, Integer status) {
return jobMapper.changeCheckStatus(id, status);
}
原理:
通过AOP+反射,通过切面环绕对方法进行缓冲操作。
Redis配置类
使用lettuce作为redis连接池,lettuce是springboot2默认的客户端,自动集成,如果要使用jedis配置麻烦,并且lettuce是线程安全可以自动扩展的;jedis是非线程安全。
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Bean;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
/**
* lettuce的redis连接池
* @author 进击的Coder
* @date 2019/1/31
*/
@Configuration
@AutoConfigureAfter(RedisAutoConfiguration.class)
public class RedisConfig {
@Bean
public RedisTemplate<String, Object> redisTemplate (LettuceConnectionFactory connectionFactory) {
RedisTemplate<String, Object> template = new RedisTemplate<String, Object>();
template.setConnectionFactory(connectionFactory);
Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
ObjectMapper om = new ObjectMapper();
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
jackson2JsonRedisSerializer.setObjectMapper(om);
StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
// key采用String的序列化方式
template.setKeySerializer(stringRedisSerializer);
// hash的key也采用String的序列化方式
template.setHashKeySerializer(stringRedisSerializer);
// value序列化方式采用jackson
template.setValueSerializer(jackson2JsonRedisSerializer);
// hash的value序列化方式采用jackson
template.setHashValueSerializer(jackson2JsonRedisSerializer);
template.afterPropertiesSet();
// 开启事务
template.setEnableTransactionSupport(true);
return template;
}
}
自定义的注解
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* @author 易水●墨龙吟
* @Description 自定义的查询缓冲注解
* @create 2019-02-16 15:02
*/
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface RedisCacheable {
String Value() default "";
String Key() default "";
long time() default 0L;
}
AOP方法类
import com.lehui.molong.config.redis.annotation.RedisCacheable;
import com.lehui.molong.config.redis.utils.RedisUtil;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.AfterThrowing;
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.core.annotation.Order;
import org.springframework.stereotype.Component;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* @author 易水●墨龙吟
* @Description
* @create 2019-02-16 15:39
* Order 拦截器执行顺序
*/
@Aspect
@Order(1)
@Component
public class InterceptorSelect extends Common {
@Autowired
private RedisUtil redisUtil;
@Pointcut("@annotation(redisCacheable)")
public void pointCut(RedisCacheable redisCacheable) {}
// 设置切面为加有 @RedisCacheable注解的方法
@Around("@annotation(redisCacheable)")
public Object around(ProceedingJoinPoint proceedingJoinPoint, RedisCacheable redisCacheable) throws Throwable {
System.out.println("拦截到方法:" + proceedingJoinPoint.getSignature().getName() + "方法...");
return redisSelect(proceedingJoinPoint, redisCacheable);
}
@AfterThrowing(pointcut = "@annotation(redisCacheable)", throwing = "error")
public void afterThrowing (Throwable error, RedisCacheable redisCacheable){
System.out.println("出现异常");
}
/**
* 获取缓冲
* @param proceedingJoinPoint
* @param redisCacheable
* @return
*/
private Object redisSelect (ProceedingJoinPoint proceedingJoinPoint, RedisCacheable redisCacheable) throws Throwable {
String value = redisCacheable.Value();
String key = redisCacheable.Key();
// 通过反射获取方法的参数、value、key 拼接为一个 value:key [...参数]的key值
String newKey = super.getKey(proceedingJoinPoint, value, key);
Object result = null;
try {
if(redisUtil.hasKey(newKey)) {
long expire = redisUtil.getExpire(newKey);
if (expire > System.currentTimeMillis()) {
result = redisUtil.get(newKey);
} else {
result = getNewRedis(proceedingJoinPoint, redisCacheable, newKey, result);
}
} else {
result = getNewRedis(proceedingJoinPoint, redisCacheable, newKey, result);
}
} catch (Exception exception) {
System.out.println("Redis连接超时");
result = getNewRedis(proceedingJoinPoint, redisCacheable, newKey, result);
}
return result;
}
/**
* 获取数据库数据,并更新缓冲
* @param proceedingJoinPoint
* @param redisCacheable
* @param newKey
* @param result
* @return
* @throws Throwable
*/
private Object getNewRedis (ProceedingJoinPoint proceedingJoinPoint, RedisCacheable redisCacheable, String newKey, Object result) throws Throwable {
Long time = redisCacheable.time();
System.out.println(time);
long newTime = System.currentTimeMillis() + time;
System.out.println(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date(newTime)));
result = proceedingJoinPoint.proceed();
if(time > 0L) {
redisUtil.set(newKey, result, newTime);
} else {
redisUtil.set(newKey, result);
}
return result;
}
}
效果图
初次请求
再次请求
其他
完整结构
工具类和其他的注解类太多代码,就不一一展示了;有需要的就可以评论发出邮箱,我给大家发一份。