缓存工厂-CacheManager

    记录下项目中用到的缓存的功能,个人感觉这种实现方式还是挺不错的,该实现方式是通过结合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去使用缓存的功能了


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值