您的位置:首页 > 其它

缓存工厂-CacheManager

2015-12-04 09:12 260 查看
记录下项目中用到的缓存的功能,个人感觉这种实现方式还是挺不错的,该实现方式是通过结合spring的IOC容器进行bean管理。

1. 缓存类型配置(这里实现了两种memcached和redis),因为是结合spring使用,所以这个类型配置就可以像数据库连接源那样在properties文件中进行配置,在config.properties配置文件中的memcached配置如下:

#缓存类型
cache.provinder=memcached
#缓存服务器地址和端口
cache.addresses=172.16.1.114:11211
#连接池大小
cache.poolsize=1


2. 缓存接口方法定义,接口中的方法个数可根据实际情况进行添加或删减:

public interface CacheManager {
/**
* 保存键值并指定存储时长,单位秒。
* @param key
* @param value
* @param duration
* @return
*/
void set(String key, String value, int duration);

/**
* 保存键值并指定存储时长和时长单位
* @param key
* @param value
* @param duration
* @param unit
* @return
*/
void set(String key, String value, int duration, TimeUnit unit);

/**
* 永久保存键值
* @param key
* @param value
* @return
*/
void set(String key, String value);

/**
* 根据键获取值
* @param key
* @return null表示没有找到
*/
String get(String key);

/**
* 根据键删除对应键值对
* @param key
* @return
*/
void delete(String key);

/**
* 获取一个计数器,增加相应的值并返回
* @param counter			计数器键名
* @param incrBy			增加的值
* @param defaultValue		计数器默认初始值
* @return
*/
long incrementAndGet(String counter, long incrBy, long defaultValue);

/**
* 获取一个计数器,减少相应的值并返回
* @param counter			计数器键名
* @param decrBy			减少的值
* @param defaultValue		计数器默认初始值
* @return
*/
long decrementAndGet(String counter, long decrBy, long defaultValue);

/**
* 关掉链接,释放资源
*/
void shutdown();
}


2. 缓存工厂类实现

public class CacheManagerFactoryBean implements FactoryBean<CacheManager>{
private Logger log = LoggerFactory.getLogger(CacheManagerFactoryBean.class);
private String provinder;
private String addresses;
private int poolsize;
private CacheManager cm;

public CacheManager getObject() throws Exception {
if("memcached".equals(provinder)){
addresses = addresses.replaceAll("(,\\s*|\\s+)", " ");
cm = new MemcachedCacheManager(addresses, poolsize);
return cm;
}else if("redis".equals(provinder)){
cm = new RedisCacheManager(addresses, poolsize);
return cm;
}else{
throw new Exception("缓存服务器提供商不正确,请设置config.properties中的cache.provinder,值为memcached或redis");
}
}

public void shutdown(){
log.info("shutdown cache manager.");
cm.shutdown();
}

public Class<?> getObjectType() {
return CacheManager.class;
}

public boolean isSingleton() {
return true;
}

public String getAddresses() {
return addresses;
}

public void setAddresses(String addresses) {
this.addresses = addresses;
}

public int getPoolsize() {
return poolsize;
}

public void setPoolsize(int poolsize) {
this.poolsize = poolsize;
}

public String getProvinder() {
return provinder;
}

public void setProvinder(String provinder) {
this.provinder = provinder;
}

}
3. memcached的实现

import java.io.IOException;

import net.rubyeye.xmemcached.MemcachedClient;
import net.rubyeye.xmemcached.MemcachedClientBuilder;
import net.rubyeye.xmemcached.XMemcachedClientBuilder;
import net.rubyeye.xmemcached.utils.AddrUtil;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class MemcachedCacheManager implements CacheManager {

private Logger log = LoggerFactory.getLogger(MemcachedCacheManager.class);
private MemcachedClient client;

public MemcachedCacheManager(String addresses, int poolsize){
MemcachedClientBuilder builder = new XMemcachedClientBuilder(AddrUtil.getAddresses(addresses));
builder.setConnectionPoolSize(poolsize);
try {
client = builder.build();
} catch (IOException e) {
log.error("failed to build memcached client params:");
log.error("[addresses:{}, poolsize:{}]", new Object[]{addresses, poolsize});
log.error("failed to build memcached client details:", e);
throw new RuntimeException(e);
}
}

public void delete(String key){
try {
client.delete(key);
} catch(Exception e){
log.error("memcached delete failed params:");
log.error("[key:{}]", new Object[]{key});
log.error("memcahced delete failed details:", e);
throw new RuntimeException(e);
}
}

public String get(String key){
try {
return client.get(key);
} catch(Exception e){
log.error("memcached get failed params:");
log.error("[key:{}]", new Object[]{key});
log.error("memcahced get failed details:", e);
throw new RuntimeException(e);
}

}

public void set(String key, String value){
set(key, value, 0);
}

public void set(String key, String value, int duration) {
try {
client.set(key, duration, value);
} catch(Exception e){
log.error("memcached set failed params:");
log.error("[key:{}, value:{}, duration:{}]", new Object[]{key, value, duration});
log.error("memcached set failed details:", e);
throw new RuntimeException(e);
}
}

public void set(String key, String value, int duration, TimeUnit unit) {
set(key, value, duration*unit.getValue());
}

public long incrementAndGet(String counter, long incrBy,
long defaultValue) {
try {
return client.incr(counter, incrBy, defaultValue);
} catch(Exception e){
log.error("memcached incr failed params:");
log.error("[counter:{}, incrBy:{}, defaultValue:{}]", new Object[]{counter, incrBy, defaultValue});
log.error("memcached incr failed details:", e);
throw new RuntimeException(e);
}
}

public long decrementAndGet(String counter, long decrBy,
long defaultValue) {
try {
return client.decr(counter, decrBy, defaultValue);
} catch(Exception e){
log.error("memcached decr failed params:");
log.error("[counter:{}, decrBy:{}, defaultValue:{}]", new Object[]{counter, decrBy, defaultValue});
log.error("memcached decr failed details:", e);
throw new RuntimeException(e);
}
}

public void shutdown() {
try {
client.shutdown();
} catch (IOException e) {
log.error("failed to shutdown memcached client.", e);
}
}
}


4. redis的实现

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
import redis.clients.jedis.Transaction;

public class RedisCacheManager implements CacheManager {

private Logger log = LoggerFactory.getLogger(RedisCacheManager.class);

private JedisPool pool;

public RedisCacheManager(String addresses, int poolsize){
try{
String host = addresses.split(":")[0];
String port = addresses.split(":")[1];
JedisPoolConfig config = new JedisPoolConfig();
config.setMaxActive(poolsize);
pool = new JedisPool(config, host, Integer.valueOf(port));
}catch(Exception e){
log.error("failed to build redis client params:");
log.error("[addresses:{}, poolsize:{}]", new Object[]{addresses, poolsize});
log.error("failed to build redis client details:", e);
throw new RuntimeException(e);
}
}

public String get(String key)  {
Jedis jedis = null;
boolean success = true;
try{
jedis = pool.getResource();
String value = jedis.get(key);
return value;
}catch(Exception e){
// jedis 操作失败把无效的jedis 实例返回给池做销毁处理
success = false;
pool.returnBrokenResource(jedis);
log.error("redis get failed params:");
log.error("[key:{}]", new Object[]{key});
log.error("redis get failed details:", e);
throw new RuntimeException(e);
}finally{
if(success){
// jedis 操作成功,把jedis返回给池,得以重用
pool.returnResource(jedis);
}
}
}

public void set(String key, String value){
Jedis jedis = null;
boolean success = true;
try{
jedis = pool.getResource();
jedis.set(key, value);
}catch(Exception e){
success = false;
pool.returnBrokenResource(jedis);
log.error("redis set failed params:");
log.error("[key:{}, value:{}]", new Object[]{key, value});
log.error("redis set failed details:", e);
throw new RuntimeException(e);
}finally{
if(success){
pool.returnResource(jedis);
}
}
}

public void set(String key, String value, int duration){
Jedis jedis = null;
boolean success = true;
try{
jedis = pool.getResource();
Transaction tx = jedis.multi();
tx.set(key, value);
tx.expire(key, duration);
tx.exec();
}catch(Exception e){
success = false;
pool.returnBrokenResource(jedis);
log.error("redis set failed params:");
log.error("[key:{}, value:{}, duration:{}]", new Object[]{key, value, duration});
log.error("redis set failed details:", e);
throw new RuntimeException(e);
}finally{
if(success){
pool.returnResource(jedis);
}
}
}

public void set(String key, String value, int duration, TimeUnit unit) {
set(key, value, duration*unit.getValue());
}

public void delete(String key){
Jedis jedis = null;
boolean success = true;
try{
jedis = pool.getResource();
jedis.del(key);
}catch(Exception e){
success = false;
pool.returnBrokenResource(jedis);
log.error("redis delete failed params:");
log.error("[key:{}]", new Object[]{key});
log.error("redis delete failed details:", e);
throw new RuntimeException(e);
}finally{
if(success){
pool.returnResource(jedis);
}
}
}

public long incrementAndGet(String counter, long incrBy, long defaultValue) {
Jedis jedis = null;
boolean success = true;
try{
jedis = pool.getResource();
long count = jedis.incrBy(counter, incrBy);
return count;
}catch(Exception e){
success = false;
pool.returnBrokenResource(jedis);
log.error("redis incr failed params:");
log.error("[counter:{}, incrBy:{}, defaultValue:{}]", new Object[]{counter, incrBy, defaultValue});
log.error("redis incr failed details:", e);
throw new RuntimeException(e);
}finally{
if(success){
pool.returnResource(jedis);
}
}
}

public long decrementAndGet(String counter, long decrBy, long defaultValue) {
Jedis jedis = null;
boolean success = true;
try{
jedis = pool.getResource();
long count = jedis.decrBy(counter, decrBy);
return count;
}catch(Exception e){
success = false;
pool.returnBrokenResource(jedis);
log.error("redis decr failed params:");
log.error("[counter:{}, incrBy:{}, defaultValue:{}]", new Object[]{counter, decrBy, defaultValue});
log.error("redis decr failed details:", e);
throw new RuntimeException(e);
}finally{
if(success){
pool.returnResource(jedis);
}
}
}

public void shutdown() {
try{
pool.destroy();
}catch(Exception e){
log.error("failed to shutdown redis client.", e);
}
}
}
还可以添加其他的缓存实现,然后在缓存工厂类里面同步加上创建方式就可以了

5. spring中配置缓存工厂实体bean的生成

<bean id="cacheManager" class="com.lutongnet.game.apiserver.cache.CacheManagerFactoryBean" destroy-method="shutdown">
<property name="provinder" value="${cache.provinder}"></property>
<property name="addresses" value="${cache.addresses}"></property>
<property name="poolsize" value="${cache.poolsize}"></property>
</bean>


这样在其他地方就可以通过cacheManager这个实体bean去使用缓存的功能了
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: