redis应用—缓存

来源:互联网 发布:google linux翻墙插件 编辑:程序博客网 时间:2024/05/22 17:34

  项目的缓存设计主要是这样的,监听数据库中表的改变,如果会发生变动,则对缓存做一些处理,具体实现如下:

 (1)缓存支持类(实体、辅助类等)的设计

实体缓存注释类 NeedCache

/** * 缓存的注释类,如果需要缓存某个类,请在类上添加此注释类,并给出cache的处理类 *  * @author liuyang *  */@Documented@Target(value = ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)public @interface NeedCache {Class<?> cacheDealClass();}

缓存类 Cache

/** * 对象缓存类 *  * @author liuyang *  */public class Cache {private String key;private Map<String,String> fieldHashMap;private int expiredSeconds;private long expiredTime;/** * 键 *  * @return */public String getKey() {return key;}public void setKey(String key) {this.key = key;}/** * 缓存的对象map * @return */public Map<String, String> getFieldHashMap() {return fieldHashMap;}public void setFieldHashMap(Map<String, String> fieldHashMap) {this.fieldHashMap = fieldHashMap;}/** * 过期秒数 *  * @return */public int getExpiredSeconds() {return expiredSeconds;}public void setExpiredSeconds(int expiredSeconds) {this.expiredSeconds = expiredSeconds;}/** * 过期时间 *  * @return */public long getExpiredTime() {return expiredTime;}public void setExpiredTime(long expiredTime) {this.expiredTime = expiredTime;}}

缓存处理接口类 CacheDeal

/** * 缓存处理接口 *  * @author liuyang *  */public interface CacheDeal {/** * 添加缓存 *  * @param cachedEntity */void addCache(Object cachedEntity);/** * 移除缓存 *  * @param cachedEntity */void removeCache(Object cachedEntity);/** * 更新缓存 *  * @param cachedEntity */void updateCache(Object cachedEntity);/** * 获取缓存 *  * @param key * @return */Cache getCache(String key);}

(2)缓存监听、管理类设计

          这里用了hibernate的监听类,创建3个监听类,插入、修改、删除分别继承Ejb3PostInsertEventListener,Ejb3PostUpdateEventListener,Ejb3DeleteInsertEventListener,srping配置文件如下配置:

<!-- Jpa Entity Manager 配置 --><bean id="entityManagerFactory"class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"><property name="dataSource" ref="dataSource" /><property name="persistenceUnitName" value="defaultPU" /><property name="persistenceUnitManager" ref="persistenceUnitManager"/><property name="jpaVendorAdapter" ref="hibernateJpaVendorAdapter" /><property name="jpaProperties"><props><prop key="hibernate.dialect">${hibernate.dialect}</prop><prop key="hibernate.show_sql">false</prop><prop key="hibernate.format_sql">false</prop><prop key="hibernate.hbm2ddl.auto">update</prop><prop key="hibernate.ejb.naming_strategy">org.hibernate.cfg.ImprovedNamingStrategy</prop><prop key="hibernate.search.default.directory_provider">org.hibernate.search.store.impl.FSDirectoryProvider</prop><prop key="hibernate.search.default.indexBase">./build/indexes</prop><prop key="hibernate.search.lucene_version">LUCENE_35</prop><!-- for hibernate ejb event --><prop key="hibernate.ejb.event.post-insert">com.liuyang.infrastructure.cache.listener.ejb.PostInsertEventListener</prop><prop key="hibernate.ejb.event.post-update">com.liuyang.infrastructure.cache.listener.ejb.PostUpdateEventListener</prop><prop key="hibernate.ejb.event.post-delete">com.liuyang.infrastructure.cache.listener.ejb.PostDeleteEventListener</prop></props></property></bean>


缓存管理类

public class CacheManager {private static CacheManager instance = null;private static CacheDeal cacheDeal = null;private static Object cachedEntity = null;private CacheManager() {}public static CacheManager getNewInstance(Object cachedEntity) {CacheManager.cacheDeal = getCacheDealObject(cachedEntity.getClass());CacheManager.cachedEntity = cachedEntity;if (instance == null)synchronized (CacheManager.class) {if (instance == null) {instance = new CacheManager();}}return instance;}public void addCache() {if (isNull())return;cacheDeal.addCache(cachedEntity);}public void removeCache() {if (isNull())return;cacheDeal.removeCache(cachedEntity);}public void updateCache() {if (isNull())return;cacheDeal.updateCache(cachedEntity);}public Cache getCache(String key) {if (isNull())return null;return cacheDeal.getCache(key);}private boolean isNull() {return cacheDeal == null || cachedEntity == null;}private static CacheDeal getCacheDealObject(Class<?> cachedClazz) {CacheDeal cacheDealObject = null;try {boolean hasNeedCacheAnnotation = cachedClazz.isAnnotationPresent(NeedCache.class);if (hasNeedCacheAnnotation) {NeedCache needCache = cachedClazz.getAnnotation(NeedCache.class);cacheDealObject = (CacheDeal) SpringContextHolder.getBean(needCache.cacheDealClass());}} catch (Exception e) {LoggerUtil.error(CacheManager.class, cachedClazz + "获取缓存处理类失败", e);}return cacheDealObject;}}


PostInsertEventListener类为例

public class PostInsertEventListener extends EJB3PostInsertEventListener{private static final long serialVersionUID = 7401854577429048855L;@Overridepublic void onPostInsert(PostInsertEvent event) {super.onPostInsert(event);CacheManager cacheManager = CacheManager.getNewInstance(event.getEntity());cacheManager.addCache();}}

以上是缓存设计的核心代码,如果要实现用户的缓存管理需要创建用户缓存管理类,并实现CacheDeal接口:

需要缓存的用户实体类 UserInfo

/** * 用户类 *  * @author liuyang *  */@Entity@Indexed@Table(name = "user_info")@NeedCache(cacheDealClass = UserCacheManager.class)//用户缓存管理类public class UserInfo extends IdEntity implements Serializable {private static final long serialVersionUID = 8046430120913324930L;private String loginName;private String password;private String name;private String email;
//getter setter省略
}

用户缓存管理类

/** * 用户缓存管理类 *  * @author liuyang *  */@Componentpublic class UserCacheManager implements CacheDeal {@Autowiredprivate UserRepository userRepository;//数据库user dao@Autowiredprivate JedisManagerCache jedisManagerCache;//jedis管理类@Overridepublic void addCache(Object cachedEntity) {UserInfo user = (UserInfo) cachedEntity;addUserCache(user);}@Overridepublic void removeCache(Object cachedEntity) {UserInfo user = (UserInfo) cachedEntity;removeUserCache(user);}@Overridepublic void updateCache(Object cachedEntity) {UserInfo user = (UserInfo) cachedEntity;String userKey = KeyConstants.USER_ + user.getId();Map<String, String> userHash = buildUserHash(user);jedisManagerCache.saveHash(userKey, userHash);}@Overridepublic Cache getCache(String key) {Cache cache = new Cache();cache.setKey(key);cache.setFieldHashMap(jedisManagerCache.getHashMapByKey(key));return cache;}@Overridepublic void init() {List<UserInfo> allUserList = getAllUsers();for (UserInfo user : allUserList) {addUserCache(user);}}/** * 新增用户时,添加用户缓存 *  * @param user */private void addUserCache(UserInfo user) {Jedis jedis = null;Transaction tran = null;try {jedis = jedisManagerCache.getJedis();tran = jedis.multi();String userKey = KeyConstants.USER_ + user.getId();String userLesseeKey = KeyConstants.USER_LESSEE_+ user.getLessee().getId();Map<String, String> userHash = buildUserHash(user);tran.hmset(userKey, userHash);tran.sadd(userLesseeKey, user.getId().toString());tran.set("user:" + user.getEmail() + ":id", user.getId().toString());tran.exec();} catch (Exception e) {tran.discard();LoggerUtil.error(UserCacheManager.class, "添加" + user.getEmail()+ "缓存失败", e);} finally {jedisManagerCache.returnResource(jedis);}}/** * 移除用户缓存 *  * @param user */private void removeUserCache(UserInfo user) {Jedis jedis = null;Transaction tran = null;try {jedis = jedisManagerCache.getJedis();tran = jedis.multi();String userKey = KeyConstants.USER_ + user.getId();String userLesseeKey = KeyConstants.USER_LESSEE_+ user.getLessee().getId();tran.del(userKey);tran.srem(userLesseeKey, user.getId().toString());tran.del("user:" + user.getEmail() + ":id");tran.exec();} catch (Exception e) {tran.discard();LoggerUtil.error(UserCacheManager.class, "删除" + user.getEmail()+ "缓存失败", e);} finally {jedisManagerCache.returnResource(jedis);}}/** * 构建用户hashmap *  * @param user * @return */private Map<String, String> buildUserHash(UserInfo user) {Map<String, String> userHash = new HashMap<String, String>();userHash.put("login_name", user.getLoginName());userHash.put("name", user.getName());userHash.put("email", user.getEmail());if (null != user.getUserGroup())userHash.put("user_group_name", user.getUserGroup().getName());return userHash;}}


这样,就可以监听数据库改变并跟心缓存了,其中jedisCacheManager就是我自己封装的常用的jedis操作方法,这个大家可以自己实现,用到什么去做封装。

(3)添加服务器启动时,写入缓存功能

我们肯定会遇到,在服务器启动时,去写入很多缓存,这样,在服务器运行中,就可以直接调用缓存了,下面就是这个功能的设计:

让上面的UserCacheManager在多实现一个接口InitializeCache

/** * 缓存数据初始化接口,如果某个实体的缓存数据需要在服务器启动时初始化请实现此接口 *  * @author liuyang *  */public interface InitializeCache {void init();}

@Componentpublic class UserCacheManager implements CacheDeal, InitializeCache {//前面的省略@Overridepublic void init() {List<UserInfo> allUserList = getAllUsers();for (UserInfo user : allUserList) {addUserCache(user);}}}


初始化缓存管理类,这类需要在spring中注入
public class InitializeCahceManager {private List<String> cachedEntityClazzNameList = new ArrayList<String>();public void setCachedEntityClazzNameList(List<String> cachedEntityClazzNameList) {this.cachedEntityClazzNameList = cachedEntityClazzNameList;}public void init() {try {for (String clazzName : cachedEntityClazzNameList) {Class<?> clazz = Class.forName(clazzName);boolean hasNeedCacheAnnotation = clazz.isAnnotationPresent(NeedCache.class);if (hasNeedCacheAnnotation) {NeedCache needCache = clazz.getAnnotation(NeedCache.class);InitializeCache initObject = (InitializeCache) SpringContextHolder.getBean(needCache.cacheDealClass());initObject.init();}}} catch (Exception e) {LoggerUtil.error(InitializeCahceManager.class, "初始化缓存失败", e);}}}
<!-- 初始化缓存管理类    如果需要缓存实体,添加实现类,实现cacheDeal、InitializeCache接口,然后在实体上加needclass的注释,    并把需要缓存的实体加入到下面的集合     -->    <bean id="initializeCacheManager" class="com.liuyang.infrastructure.cache.InitializeCahceManager"><property name="cachedEntityClazzNameList"><list><value>com.liuyang.security.model.UserInfo</value></list></property></bean>

list是需要初始化数据的实体类,下面的serlvet需要加入到web.xml中服务器启动时运行,就大功告成了,启动试试看

@SuppressWarnings("serial")public class InitializeCacheServlet extends HttpServlet {@Overridepublic void init() throws ServletException {super.init();InitializeCahceManager manager = SpringContextHolder.getBean(InitializeCahceManager.class);manager.init();}}

原创粉丝点击