引言:
之前在开发中,使用了spring-redis-data中的@CacheAble和@CacheEvict,但是在使用过程中发现,存在key串掉或失效的情况,同时,在redis客户端直接 get key查询时,并不是直接返回value,因此,抽空自己写了这个注解。
思路:
使用了jedis客户端,然后再用aop切入service所有使用缓存的方法,缓存数据至redis
代码:
1、spring-redis.xml
<bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
<property name="maxTotal" value="300" />
<property name="maxIdle" value="50" />
<property name="minIdle" value="1" />
<property name="maxWaitMillis" value="3000" />
<property name="testOnBorrow" value="true" />
</bean>
<!-- jedis pool配置 -->
<!-- redis的连接池pool,不是必选项:timeout/password -->
<bean id="jedisPool" class="redis.clients.jedis.JedisPool">
<constructor-arg index="0" ref="jedisPoolConfig" />
<constructor-arg index="1" value="${redishost}" />
<constructor-arg index="2" value="${redisport}" type="int" />
<constructor-arg index="3" value="300000" type="int" />
<constructor-arg index="4" value="${redispwd}"></constructor-arg>
</bean>
<bean id="redisCache" class="com.netease.mail.vip.commenta.service.redis.RedisCache">
<property name="jedisPool" ref="jedisPool"></property>
</bean>
2、RedisCache.java
public class RedisCache {
private JedisPool jedisPool;
public JedisPool getJedisPool() {
return jedisPool;
}
public void setJedisPool(JedisPool jedisPool) {
this.jedisPool = jedisPool;
}
public void set(String key, Object value, int seconds) {
Jedis jedis = null;
try {
jedis = jedisPool.getResource();
jedis.set(key, String.valueOf(value));
jedis.expire(key, seconds);
} catch (Exception e) {
e.printStackTrace();
if (jedis != null) {
jedisPool.returnBrokenResource(jedis);
}
} finally {
if (jedis != null) {
jedisPool.returnResource(jedis);
}
}
}
public void set(String key, Object value) {
set(key, value, 3600);
}
public String get(String key) {
Jedis jedis = null;
try {
jedis = jedisPool.getResource();
String value = jedis.get(key);
return value;
} catch (Exception e) {
e.printStackTrace();
if (jedis != null) {
jedisPool.returnBrokenResource(jedis);
}
return null;
} finally {
if (jedis != null) {
jedisPool.returnResource(jedis);
}
}
}
public void del(String key) {
Jedis jedis = null;
try {
jedis = jedisPool.getResource();
jedis.del(key);
} catch (Exception e) {
e.printStackTrace();
if (jedis != null) {
jedisPool.returnBrokenResource(jedis);
}
} finally {
if (jedis != null) {
jedisPool.returnResource(jedis);
}
}
}
public Object getObject(String key) {
Jedis jedis = null;
try {
jedis = jedisPool.getResource();
byte[] value = jedis.get(key.getBytes());
return SerializeUtil.unserialize(value);
} catch (Exception e) {
e.printStackTrace();
if (jedis != null) {
jedisPool.returnBrokenResource(jedis);
}
return null;
} finally {
if (jedis != null) {
jedisPool.returnResource(jedis);
}
}
}
public void setObject(String key, Object value, Integer seconds) {
Jedis jedis = null;
try {
jedis = jedisPool.getResource();
jedis.set(key.getBytes(), SerializeUtil.serialize(value));
jedis.expire(key.getBytes(), seconds);
} catch (Exception e) {
e.printStackTrace();
if (jedis != null) {
jedisPool.returnBrokenResource(jedis);
}
} finally {
if (jedis != null) {
jedisPool.returnResource(jedis);
}
}
}
public void setObject(String key, Object value) {
Jedis jedis = null;
try {
jedis = jedisPool.getResource();
jedis.set(key.getBytes(), SerializeUtil.serialize(value));
} catch (Exception e) {
e.printStackTrace();
if (jedis != null) {
jedisPool.returnBrokenResource(jedis);
}
} finally {
if (jedis != null) {
jedisPool.returnResource(jedis);
}
}
}
public void delObject(String key) {
Jedis jedis = null;
try {
jedis = jedisPool.getResource();
jedis.del(key.getBytes());
} catch (Exception e) {
e.printStackTrace();
if (jedis != null) {
jedisPool.returnBrokenResource(jedis);
}
} finally {
if (jedis != null) {
jedisPool.returnResource(jedis);
}
}
}
}
SerializeUtil.java
public class SerializeUtil {
public static byte[] serialize(Object object) {
ObjectOutputStream oos = null;
ByteArrayOutputStream baos = null;
try {
// 序列化
baos = new ByteArrayOutputStream();
oos = new ObjectOutputStream(baos);
oos.writeObject(object);
byte[] bytes = baos.toByteArray();
return bytes;
} catch (Exception e) {
}
return null;
}
public static Object unserialize( byte[] bytes) {
ByteArrayInputStream bais = null;
try {
// 反序列化
bais = new ByteArrayInputStream(bytes);
ObjectInputStream ois = new ObjectInputStream(bais);
return ois.readObject();
} catch (Exception e) {
}
return null;
}
}
@CacheAble
@Target({ ElementType.METHOD, ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface Cacheable{
public static String DEFAULT_KEY = "d_key";
/**
* 前缀标志位
*
* @return
*/
@AliasFor("value")
public abstract String value() default "default_prefix";
/**
* 当key为空,或非#开头,或没有该参数,则将这个注解对应的方法名作为key,否则以数#标志位,从1开始
*
* @return
*/
public abstract String key() default DEFAULT_KEY;
public abstract int expiretime() default 3600;
}
@CacheEvict
@Target({ ElementType.METHOD, ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface CacheEvict {
public static String DEFAULT_KEY = "d_key";
/**
* 前缀标志位
*
* @return
*/
@AliasFor("value")
public abstract String value() default "default_prefix";
/**
* 当key为空,或非#开头,或没有该参数,则默认为无参数(仅存储一个key)
*
* @return
*/
public abstract String key() default DEFAULT_KEY;
}
CacheUtils.java
@Aspect
@Component
public class CacheUtils {
static Logger logger = Logger.getLogger(CacheUtils.class);
@Autowired
RedisCache redisCache;
@Around(value = "execution (* com.cxjhihihi.service..*Service.*(..)) && @annotation(cache)")
public Object cacheableMethod(ProceedingJoinPoint pjd, Cacheable cache) throws Throwable {
Object result = null;
String key = cache.key();
String value = cache.value();
String realKey = getRealKey(pjd, key, value);
result = redisCache.getObject(realKey.toString());
if (ObjectUtils.isEmpty(result)) {
logger.info("[cacheable] key=" + realKey.toString() + " result is null");
result = pjd.proceed();
redisCache.setObject(realKey.toString(), result, cache.expiretime());
logger.info("[cacheable] set cache key=" + realKey.toString() + " expiretime=" + cache.expiretime());
}
return result;
}
@Around(value = "execution (* com.cxjhihihi.service..*Service.*(..)) && @annotation(cache)")
public void cacheEvitMethod(ProceedingJoinPoint pjd, CacheEvict cache) throws Throwable {
String key = cache.key();
String value = cache.value();
String realKey = getRealKey(pjd, key, value);
logger.info("[cacheEvict] key=" + realKey.toString());
redisCache.delObject(realKey.toString());
}
private String getRealKey(ProceedingJoinPoint pjd, String key, String value)
throws ClassNotFoundException, NotFoundException {
logger.info("[cache realkey] key=" + key + " value=" + value);
Object[] args = pjd.getArgs();
String methodName = pjd.getSignature().getName();
StringBuffer realKey = new StringBuffer().append(value).append("_");
if (key.equals(Cacheable.DEFAULT_KEY) || !key.startsWith("#")) {
realKey.append(methodName);
} else {
Integer key_index = Integer.parseInt(key.substring(1)) - 1;
realKey.append(args[key_index]);
}
return realKey.toString();
}
}
网友评论